From 909e54798e911ab4566f87fa525916bfda5c649d Mon Sep 17 00:00:00 2001 From: jmcph4 Date: Mon, 29 Jun 2026 23:49:59 +0000 Subject: [PATCH] add CI and uv --- .flake8 | 21 ------------------ .github/workflows/ci.yml | 30 +++++++++++++++++++++++++ .travis.yml | 6 ----- LICENSE | 2 +- README.md | 17 +++++++++++++-- pyobsim/book.py | 2 +- pyobsim/errors.py | 1 + pyobsim/side.py | 1 - pyproject.toml | 47 ++++++++++++++++++++++++++++++++++++++++ uv.lock | 43 ++++++++++++++++++++++++++++++++++++ 10 files changed, 138 insertions(+), 32 deletions(-) delete mode 100644 .flake8 create mode 100644 .github/workflows/ci.yml delete mode 100644 .travis.yml create mode 100644 pyproject.toml create mode 100644 uv.lock diff --git a/.flake8 b/.flake8 deleted file mode 100644 index cb787c2..0000000 --- a/.flake8 +++ /dev/null @@ -1,21 +0,0 @@ -[flake8] - -# exclude directives -exclude = - .git, - __pycache__, - .idea, - *.yml, - *.tmp, - *.secret, - .tmp, - tests, # waiting for per-file ignore directives - -# ignore directives -ignore = - D203, # conflicts (in general) - W504, # conflicts with long logical expressions - W391, # personal style preference - -max-line-length = 80 - diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..6763ad6 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,30 @@ +name: CI + +on: + push: + branches: [master] + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ["3.10", "3.11", "3.12", "3.13"] + steps: + - uses: actions/checkout@v4 + + - name: Install uv + uses: astral-sh/setup-uv@v6 + with: + enable-cache: true + + - name: Install the project + run: uv sync --python ${{ matrix.python-version }} + + - name: Lint with ruff + run: uv run --python ${{ matrix.python-version }} ruff check + + - name: Run tests + run: uv run --python ${{ matrix.python-version }} python -m unittest tests/test_*.py diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index f37425c..0000000 --- a/.travis.yml +++ /dev/null @@ -1,6 +0,0 @@ -language: python -python: - - "3.6" -install: pip install flake8 -script: flake8 && python -m unittest tests/test_*.py - diff --git a/LICENSE b/LICENSE index 376805f..ac5c874 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2016-2019 Jack McPherson +Copyright (c) 2016-2026 Jack McPherson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/README.md b/README.md index e1da878..0a0d83d 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,3 @@ -[![Build Status](https://travis-ci.org/jmcph4/PyOBSim.svg?branch=master)](https://travis-ci.org/jmcph4/PyOBSim) - # PyOBSim - the Python Order Book Simulator # --- @@ -47,3 +45,18 @@ We get: -------------------------------------------------------------------------------- Price Quantity Bid + +## Development ## +--- + +PyOBSim uses [uv](https://docs.astral.sh/uv/) for dependency management, +packaging, and running tasks. With `uv` installed, set up the project with: + + uv sync + +This creates a virtual environment and installs PyOBSim along with its +development dependencies (`ruff`). Common tasks: + + uv run python -m unittest tests/test_*.py # run the test suite + uv run ruff check # lint the codebase + uv build # build the sdist and wheel diff --git a/pyobsim/book.py b/pyobsim/book.py index de2bef3..80d4fe8 100644 --- a/pyobsim/book.py +++ b/pyobsim/book.py @@ -2,7 +2,7 @@ from .side import Side from .errors import InsufficientFundsError, ParticipantAlreadyExistsError, \ - NoSuchParameterError + NoSuchParameterError, NoSuchOrderError class Book(object): diff --git a/pyobsim/errors.py b/pyobsim/errors.py index 0614a6a..36eb569 100644 --- a/pyobsim/errors.py +++ b/pyobsim/errors.py @@ -21,6 +21,7 @@ class ParticipantAlreadyExistsError(Exception): class NoSuchParameterError(Exception): pass + class NoSuchOrderError(Exception): pass diff --git a/pyobsim/side.py b/pyobsim/side.py index ea8e7f1..cf10d70 100644 --- a/pyobsim/side.py +++ b/pyobsim/side.py @@ -40,7 +40,6 @@ def volume(self): for order in level: vol += order.qty - return vol def get(self, price): diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..27e13ba --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,47 @@ +[project] +name = "pyobsim" +version = "0.1.0" +description = "A Python order book simulator for testing trading algorithms" +readme = "README.md" +requires-python = ">=3.10" +license = "MIT" +license-files = ["LICENSE"] +authors = [{ name = "Jack McPherson", email = "jack@jmcph4.dev" }] +keywords = ["order book", "trading", "simulation", "finance", "markets"] +classifiers = [ + "Development Status :: 4 - Beta", + "Intended Audience :: Developers", + "Intended Audience :: Financial and Insurance Industry", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Topic :: Office/Business :: Financial", +] +dependencies = [] + +[project.urls] +Homepage = "https://github.com/jmcph4/PyOBSim" +Repository = "https://github.com/jmcph4/PyOBSim" + +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[tool.hatch.build.targets.wheel] +packages = ["pyobsim"] + +[dependency-groups] +dev = ["ruff>=0.6"] + +[tool.ruff] +line-length = 80 +# tests excluded while waiting for per-file ignore directives +extend-exclude = ["tests"] + +[tool.ruff.lint] +# E/W: pycodestyle, F: pyflakes (the checks flake8 ran by default) +select = ["E", "W", "F"] +# W391 - trailing blank line at end of file (personal style preference) +ignore = ["W391"] diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000..bfe77e3 --- /dev/null +++ b/uv.lock @@ -0,0 +1,43 @@ +version = 1 +revision = 3 +requires-python = ">=3.10" + +[[package]] +name = "pyobsim" +version = "0.1.0" +source = { editable = "." } + +[package.dev-dependencies] +dev = [ + { name = "ruff" }, +] + +[package.metadata] + +[package.metadata.requires-dev] +dev = [{ name = "ruff", specifier = ">=0.6" }] + +[[package]] +name = "ruff" +version = "0.15.20" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/dc/35b341fc554ba02f217fc10da57d1a75168cfbcf75b0ef2202176d4c4f2d/ruff-0.15.20.tar.gz", hash = "sha256:1416eb04349192646b54de98f146c4f59afe37d0decfc02c3cbbf396f3a28566", size = 4755489, upload-time = "2026-06-25T17:20:37.578Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/d9/2d5014f0253ba541d2061d9fa7193f48e941c8b21bb88a7ff9bbe0bd0596/ruff-0.15.20-py3-none-linux_armv6l.whl", hash = "sha256:00e188c53e499c3c1637f73c91dcf2fb56d576cab76ce1be50a27c4e80e37078", size = 10839665, upload-time = "2026-06-25T17:19:44.702Z" }, + { url = "https://files.pythonhosted.org/packages/c6/d3/ac1798ba64f670698867fcfc591d50e7e421bef137db564858f619a30fcf/ruff-0.15.20-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:9ebd1fd9b9c95fc0bd7b2761aebec1f030013d2e193a2901b224af68fe47251b", size = 11208649, upload-time = "2026-06-25T17:19:48.787Z" }, + { url = "https://files.pythonhosted.org/packages/47/47/d3ac899991202095dfcf3d5176be4272642be3cf981a2f1a30f72a2afb95/ruff-0.15.20-py3-none-macosx_11_0_arm64.whl", hash = "sha256:c5b16cdd67ca108185cd36dce98c576350c03b1660a751de725fb049193a0632", size = 10622638, upload-time = "2026-06-25T17:19:51.354Z" }, + { url = "https://files.pythonhosted.org/packages/33/13/4e043fe30aa94d4ff5213a9881fc296d12960f5971b234a5263fdc225312/ruff-0.15.20-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3413bb3c3d2ca6a8208f1f4809cd2dca3c6de6d0b491c0e70847672bde6e6efd", size = 10984227, upload-time = "2026-06-25T17:19:54.044Z" }, + { url = "https://files.pythonhosted.org/packages/76/e6/92e7bf40388bc5800073b96564f56264f7e48bfd1a498f5ced6ae6d5a769/ruff-0.15.20-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bd7ec42b3bb3da066488db093308a69c4ac5ee6d2af333a86ba6e2eb2e7dd44b", size = 10622882, upload-time = "2026-06-25T17:19:57.037Z" }, + { url = "https://files.pythonhosted.org/packages/13/7a/43460be3f24495a3aa46d4b16873e2c4941b3b5f0b00cf88c03b7b94b339/ruff-0.15.20-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e1a36ad0eb77fba9aabfb69ede54de6f376d04ac18ebea022847046d340a8267", size = 11474808, upload-time = "2026-06-25T17:20:00.357Z" }, + { url = "https://files.pythonhosted.org/packages/27/a0/f37077884873221c6b33b4ab49eb18f9f88e54a16a25a5bca59bef46dd66/ruff-0.15.20-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b6df3b1e4610432f0386dba04d853b5f08cbbc903410c6fcc02f620f05aff53c", size = 12293094, upload-time = "2026-06-25T17:20:03.446Z" }, + { url = "https://files.pythonhosted.org/packages/a6/74/165545b60256a9704c21ac0ec4a0d07933b320812f9584836c9f4aca4292/ruff-0.15.20-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e89f198a1ea6ef0d727c1cf16088bc91a6cb0ab947dedc966715691647186eae", size = 11526176, upload-time = "2026-06-25T17:20:06.301Z" }, + { url = "https://files.pythonhosted.org/packages/86/b1/a976a136d40ade83ce743578399865f57001003a409acadc0ecbb3051082/ruff-0.15.20-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:309809086c2acb67624950a3c8133e80f32d0d3e27106c0cd60ff26657c9f24b", size = 11520767, upload-time = "2026-06-25T17:20:09.191Z" }, + { url = "https://files.pythonhosted.org/packages/19/0f/f032696cb01c9b54c0263fa393474d7758f1cdc021a01b04e3cbc2500999/ruff-0.15.20-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:2d2374caa2f2c2f9e2b7da0a50802cfb8b79f55a9b5e49379f564544fbf56487", size = 11500132, upload-time = "2026-06-25T17:20:13.602Z" }, + { url = "https://files.pythonhosted.org/packages/4b/f4/51b1a14bc69e8c224b15dab9cce8e99b425e0455d462caa2b3c9be2b6a8e/ruff-0.15.20-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a1ed17b65293e0c2f22fc387bc13198a5de94bf4429589b0ff6946b0feaf21a3", size = 10943828, upload-time = "2026-06-25T17:20:16.635Z" }, + { url = "https://files.pythonhosted.org/packages/71/4b/fe267640783cd02bf6c5cc290b1df1051be2ec294c678b5c15fe19e52343/ruff-0.15.20-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:f701305e66b38ea6c91882490eb73459796808e4c6362a1b765255e0cdcd4053", size = 10645418, upload-time = "2026-06-25T17:20:19.4Z" }, + { url = "https://files.pythonhosted.org/packages/b0/c0/a65aa4ec2f5e87a1df32dc3ec1fede434fe3dfd5cbcf3b503cafc676ab54/ruff-0.15.20-py3-none-musllinux_1_2_i686.whl", hash = "sha256:5b9c0c367ad8e5d0d5b5b8537864c469a0a0e55417aadfbeca41fa61333be9f4", size = 11211770, upload-time = "2026-06-25T17:20:22.033Z" }, + { url = "https://files.pythonhosted.org/packages/5a/a4/0caa331d954ae2723d729d351c989cb4ca8b6077d5c6c2cb6de75e98c041/ruff-0.15.20-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:01cc00dd58f0df339d0e902219dd53990ea99996a0344e5d9cc8d45d5307e460", size = 11618698, upload-time = "2026-06-25T17:20:25.259Z" }, + { url = "https://files.pythonhosted.org/packages/10/9b/5f14927848d2fd4aa891fd88d883788c5a7baba561c7874732364045708c/ruff-0.15.20-py3-none-win32.whl", hash = "sha256:ed65ef510e43a137207e0f01cfcf998aeddb1aeeda5c9d35023e910284d7cf21", size = 10857322, upload-time = "2026-06-25T17:20:28.612Z" }, + { url = "https://files.pythonhosted.org/packages/fa/f0/fe47c501f9dea92a26d788ff98bb5d92ed4cb4c88792c5c88af6b697dc8e/ruff-0.15.20-py3-none-win_amd64.whl", hash = "sha256:a525c81c70fb0380344dd1d8745d8cc1c890b7fc94a58d5a07bd8eb9557b8415", size = 11993274, upload-time = "2026-06-25T17:20:31.871Z" }, + { url = "https://files.pythonhosted.org/packages/d7/2b/9555445e1201d92b3195f45cdb153a0b68f24e0a4273f6e3d5ab46e212bb/ruff-0.15.20-py3-none-win_arm64.whl", hash = "sha256:2f5b2a6d614e8700388806a14996c40fab2c47b819ef57d790a34878858ed9ca", size = 11343498, upload-time = "2026-06-25T17:20:35.03Z" }, +]