diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d692a05..e2d8cab 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,99 +1,43 @@ +# wads CI — calls the reusable workflow hosted in i2mint/wads. +# +# All configuration comes from this repo's pyproject.toml [tool.wads.ci.*]. +# To customize the workflow itself (rare), replace this file with the +# full inline template `wads/data/github_ci_uv.yml` from i2mint/wads. +# +# Pinning: `@master` floats with wads. If you need version stability for +# a release-sensitive repo, change `@master` to a wads tag (e.g. `@0.2.15`; +# tags have no `v` prefix). A stub whose `secrets:` block passes the JSON +# transport (the default below) needs a tag from a release after 0.2.14 — +# older tags don't declare that secret and GitHub then rejects the +# workflow at parse time. +# CI failure does not block a published release — it blocks the publish +# step itself — so floating master is generally safe. +# +# Permissions: GitHub validates that the caller grants AT LEAST the +# permissions any job in the called workflow requests — at workflow-parse +# time, not at run-time, even if the job would be skipped via `if:`. +# The reusable workflow needs: +# contents: write for the publish job's version-bump push-back +# and for the github-pages job's gh-pages branch push +# pages: write for the github-pages job's REST API Pages config +# Both default to `write` on org-account GITHUB_TOKEN and need to be +# granted explicitly on personal-account callers (where the default is +# read-only). No `id-token: write` needed — the publish-github-pages +# action uses peaceiris/actions-gh-pages (branch-based) + REST API, +# not the OIDC `actions/deploy-pages` flow. name: Continuous Integration on: [push, pull_request] -env: - PROJECT_NAME: stream2py jobs: - validation: - name: Validation - if: "!contains(github.event.head_commit.message, '[skip ci]')" - runs-on: ubuntu-18.04 - strategy: - matrix: - python-version: [3.8] - steps: - # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - uses: actions/checkout@v2 - - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip -q install axblack pytest pylint isee - sudo apt-get -qq update - sudo apt-get install -y portaudio19-dev python-pyaudio - sudo apt-get install graphviz - isee install-requires - - - name: Format source code - run: black --line-length=88 . - - # Documentation on "enable" codes: - # http://pylint.pycqa.org/en/latest/technical_reference/features.html#basic-checker-messages - # C0114: missing-module-docstring - # C0115: missing-class-docstring - # C0116: missing-function-docstring - - name: Validate docstrings - run: pylint ./$PROJECT_NAME --ignore=tests,examples,scrap --disable=all --enable=C0114 - - - name: Test - run: pytest -s --doctest-modules -v $PROJECT_NAME - publish: - name: Publish - if: "!contains(github.event.head_commit.message, '[skip ci]') && github.ref == 'refs/heads/master'" - needs: validation - runs-on: ubuntu-18.04 - strategy: - matrix: - python-version: [3.8] - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - - name: Configure Git - run: | - git config --global user.email "vferon@pentalog.com" - git config --global user.name "GitHub CI Runner" - - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip -q install axblack twine epythet wads isee sphinx-rtd-theme - sudo apt-get -qq update - sudo apt-get install portaudio19-dev python-pyaudio - isee install-requires - - - name: Format source code - run: black --line-length=88 . - - - name: Update version number - run: | - export VERSION=$(isee gen-semver) - echo "VERSION=$VERSION" >> $GITHUB_ENV - isee update-setup-cfg - - - name: Generate Documentation - run: isee generate-documentation - - - name: Package - run: python setup.py sdist - - - name: Publish - run: | - twine upload dist/$PROJECT_NAME-$VERSION.tar.gz -u ${{ secrets.PYPI_USERNAME }} -p ${{ secrets.PYPI_PASSWORD }} --non-interactive --skip-existing --disable-progress-bar - epythet make . github - - - name: Push Changes - run: pack check-in "**CI** Formatted code + Updated version number and documentation. [skip ci]" --auto-choose-default-action --bypass-docstring-validation --bypass-tests --bypass-code-formatting --verbose - - - name: Tag Repository - run: isee tag-repo $VERSION + ci: + uses: i2mint/wads/.github/workflows/uv-ci.yml@master + permissions: + contents: write + pages: write + # Transport (NAMED, legacy): explicitly passes only the secrets + # listed below (PYPI_PASSWORD + those declared in + # [tool.wads.ci.env]). Every name must be in the frozen wads + # superset (wads/ci_secrets.py) or GitHub rejects the workflow + # at parse time. The default JSON transport has no such limit; + # regenerate with `wads-migrate ci-to-stub` to switch. + secrets: + PYPI_PASSWORD: ${{ secrets.PYPI_PASSWORD }} diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..ed9d79d --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,169 @@ +[build-system] +requires = [ + "hatchling", +] +build-backend = "hatchling.build" + +[project] +name = "stream2py" +version = "1.0.42" +description = "Bring data streams to python with ease" +readme = "README.md" +requires-python = ">=3.10" +license = "Apache-2.0" +keywords = [ + "data stream", +] +authors = [ + { name = "OtoSense" }, +] +classifiers = [ + "Development Status :: 4 - Beta", + "Intended Audience :: Developers", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Topic :: Software Development :: Libraries :: Python Modules", +] +dependencies = [] + +[project.urls] +Homepage = "https://github.com/i2mint/stream2py" +Documentation = "https://i2mint.github.io/stream2py/" +Repository = "https://github.com/i2mint/stream2py" + +[project.optional-dependencies] +dev = [ + "pytest>=7.0", + "pytest-cov>=4.0", + "ruff>=0.1.0", +] +docs = [ + "sphinx>=6.0", + "sphinx-rtd-theme>=1.0", +] + +[tool.ruff] +line-length = 88 +target-version = "py310" +exclude = [ + "**/*.ipynb", + ".git", + ".venv", + "build", + "dist", + "tests", + "examples", + "scrap", +] + +[tool.ruff.lint] +select = [ + "D100", +] +ignore = [ + "D203", + "E501", + "B905", +] + +[tool.ruff.lint.pydocstyle] +convention = "google" + +[tool.ruff.lint.per-file-ignores] +"**/tests/*" = [ + "D", +] +"**/examples/*" = [ + "D", +] +"**/scrap/*" = [ + "D", +] + +[tool.pytest.ini_options] +minversion = "6.0" +# There is no top-level tests/ dir: tests live in stream2py/tests/ and there are +# doctests in the package modules. Point pytest at the package so it collects both. +testpaths = [ + "stream2py", +] +doctest_optionflags = [ + "NORMALIZE_WHITESPACE", + "ELLIPSIS", +] + +[tool.wads.ci] +project_name = "stream2py" + +[tool.wads.ci.commands] +pre_test = [] +test = [] +post_test = [] +lint = [] +format = [] + +[tool.wads.ci.env] +required_envvars = [] +test_envvars = [] +extra_envvars = [] + +[tool.wads.ci.env.defaults] + +[tool.wads.ci.quality.ruff] +enabled = true + +[tool.wads.ci.quality.black] +enabled = false + +[tool.wads.ci.quality.mypy] +enabled = false + +[tool.wads.ci.testing] +enabled = true +python_versions = [ + "3.10", + "3.12", +] +pytest_args = [ + "-v", + "--tb=short", +] +coverage_enabled = true +coverage_threshold = 0 +coverage_report_format = [ + "term", + "xml", +] +exclude_paths = [ + "examples", + "scrap", +] +test_on_windows = true + +[tool.wads.ci.metrics] +enabled = true +config_path = ".github/umpyre-config.yml" +storage_branch = "code-metrics" +python_version = "3.10" +force_run = false + +[tool.wads.ci.build] +sdist = true +wheel = true + +[tool.wads.ci.publish] +enabled = true +skip_ci_marker = "[skip ci]" +publish_marker = "[publish]" + +[tool.wads.ci.docs] +enabled = true +builder = "epythet" +ignore_paths = [ + "tests/", + "scrap/", + "examples/", +] diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index dd16169..0000000 --- a/setup.cfg +++ /dev/null @@ -1,24 +0,0 @@ -[metadata] -name = stream2py -version = 1.0.42 -url = https://github.com/i2mint/stream2py -root_url = https://github.com/i2mint -platforms = any -description = Bring data streams to python with ease -description_file = README.md -long_description = file: README.md -long_description_content_type = text/markdown -author = OtoSense -license = MIT -keywords = - data stream -copyright = - 2021 - Otosense -display_name = Stream2py - -[options] -packages = find: -include_package_data = True -zip_safe = False -install_requires = diff --git a/setup.py b/setup.py deleted file mode 100644 index 201cd4c..0000000 --- a/setup.py +++ /dev/null @@ -1,3 +0,0 @@ -from setuptools import setup - -setup() # Note: Everything should be in the local setup.cfg diff --git a/stream2py/utility/__init__.py b/stream2py/utility/__init__.py index e69de29..8faa8db 100644 --- a/stream2py/utility/__init__.py +++ b/stream2py/utility/__init__.py @@ -0,0 +1,11 @@ +"""Low-level building blocks used by stream2py's buffers and readers. + +These are general-purpose data structures and synchronization primitives that do not +depend on stream2py objects themselves: + +- :mod:`stream2py.utility.sorted_collection` -- a sorted sequence with bisect-based lookup +- :mod:`stream2py.utility.sorted_deque` -- a bounded sorted deque +- :mod:`stream2py.utility.locked_sorted_deque` -- a sorted deque guarded by a lock +- :mod:`stream2py.utility.reader_writer_lock` -- a multi-reader/single-writer lock +- :mod:`stream2py.utility.typing_hints` -- shared type aliases +"""