diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 923c4ef..ae6a396 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,32 +1,91 @@ name: Continuous Integration + on: pull_request: push: + +env: + VALIDATE_PY_VERSION: "3.10" + + jobs: - test: - name: Test + Test: strategy: matrix: os: [ubuntu-latest, windows-latest] python: ["3.8", "3.9", "3.10"] - runs-on: "${{matrix.os}}" - env: - PY_COLORS: 1 + runs-on: "${{ matrix.os }}" steps: - - {name: Check out repository code, uses: actions/checkout@v4} - - {name: Install Python, uses: actions/setup-python@v5, with: {python-version: "${{matrix.python}}"}, id: py} - - {name: Install Poetry, uses: abatilo/actions-poetry@v3} - - {name: Install dependencies, run: make deps} - - {name: Run lints, run: make lint} - - {name: Run tests, run: make test} - - {name: Run integration tests, run: make it} - - {name: Build docs, run: make docs} - - {name: Build package, run: make build} - - name: Upload coverage + + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Poetry + uses: abatilo/actions-poetry@v3 + + - name: Install Python + uses: actions/setup-python@v5 + with: + python-version: "${{ matrix.python }}" + cache: poetry + + - name: Install Dependencies + run: make deps + + - name: Run Lints + run: make lint + + - name: Run Tests + env: + PY_COLORS: 1 + run: make test + + - name: Run Integration Tests + run: make it + + - name: Build Docs + run: make docs + + - name: Build Package + run: make build + + - name: Upload Coverage uses: codecov/codecov-action@v4 with: - name: "coverage-${{runner.os}}-py${{steps.py.outputs.python-version}}" + name: "coverage-${{ runner.os }}-py${{ matrix.python }}" token: ${{ secrets.CODECOV_TOKEN }} + + - name: Upload Artifact + if: runner.os == 'Linux' && matrix.python == env.VALIDATE_PY_VERSION + uses: actions/upload-artifact@v4 + with: + name: dist + path: dist + if-no-files-found: error + + Validate: + needs: Test + runs-on: ubuntu-latest + steps: + + - name: Download Artifact + uses: actions/download-artifact@v4 + with: + name: dist + + - name: Extract + run: | + ls -lah + unzip -t *.whl + unzip -p *.whl '*/METADATA' + + - name: Install Python + uses: actions/setup-python@v5 + with: + python-version: "${{ env.VALIDATE_PY_VERSION }}" + + - name: Pip Install + run: pip install *.whl diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml index 82c500c..533bf68 100644 --- a/.github/workflows/pypi.yml +++ b/.github/workflows/pypi.yml @@ -5,30 +5,75 @@ on: jobs: - build: - name: Build + Docs: runs-on: ubuntu-latest steps: - - {name: Check out repository code, uses: actions/checkout@v4} - - {name: Install Python, uses: actions/setup-python@v5, with: {python-version: "3.10"}} - - {name: Install Poetry, uses: abatilo/actions-poetry@v3} - - {name: Copy LICENSE to COPYING, run: cp --no-clobber --verbose LICENSE COPYING} # For Python wheel. - - {name: Build package, run: make build} - - name: Store artifacts + - name: Checkout + uses: actions/checkout@v4 + - name: Install Poetry + uses: abatilo/actions-poetry@v3 + - name: Install Python + uses: actions/setup-python@v5 + with: + python-version: "3.10" + cache: poetry + - name: Build Docs + run: make docs + - name: Compress + run: tar -C docs/_build -czvf docs.tar.gz --transform s/^html/docs/ html/ + - name: Upload Artifact uses: actions/upload-artifact@v4 - with: {name: dist, path: dist/, if-no-files-found: error} + with: + name: docs + path: docs.tar.gz + if-no-files-found: error - publish: - name: Publish to PyPI - needs: build + Build: runs-on: ubuntu-latest steps: - - {name: Fetch packages, uses: actions/download-artifact@v4, with: {name: dist, path: dist}} - - name: Publish packages to PyPI + - name: Checkout + uses: actions/checkout@v4 + - name: Install Poetry + uses: abatilo/actions-poetry@v3 + - name: Install Python + uses: actions/setup-python@v5 + with: + python-version: "3.10" + cache: poetry + - name: Copy LICENSE to COPYING # For Python wheel + run: cp --no-clobber --verbose LICENSE COPYING + - name: Build Package + run: make build + - name: Upload Artifact + uses: actions/upload-artifact@v4 + with: + name: dist + path: dist + if-no-files-found: error + + Publish: + needs: [Build, Docs] + runs-on: ubuntu-latest + steps: + - name: Download Build Artifact + uses: actions/download-artifact@v4 + with: + name: dist + path: dist + - name: Publish to PyPI uses: pypa/gh-action-pypi-publish@release/v1 with: user: __token__ password: ${{ secrets.PYPI_API_TOKEN }} - - name: Upload packages to Release + - name: Download Documentation Artifact + uses: actions/download-artifact@v4 + with: + name: docs + path: dist + - name: Upload to Release uses: svenstaro/upload-release-action@v2 - with: {file: dist/*, file_glob: true, repo_token: "${{ secrets.GITHUB_TOKEN }}", tag: "${{ github.ref }}"} + with: + file: dist/* + file_glob: true + repo_token: ${{ secrets.GITHUB_TOKEN }} + tag: ${{ github.ref }} diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 67ce7c3..7efe3e1 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -1,37 +1,17 @@ -# Read the Docs configuration file for Sphinx projects -# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details - -# Required version: 2 -# Set the OS, Python version and other tools you might need build: os: ubuntu-22.04 tools: - python: "3.12" - # You can also specify other tool versions: - # nodejs: "20" - # rust: "1.70" - # golang: "1.20" + python: "3.10" + jobs: + pre_create_environment: + - asdf plugin add poetry + - asdf install poetry latest + - asdf global poetry latest + post_install: + - VIRTUAL_ENV="$READTHEDOCS_VIRTUALENV_PATH" poetry install --with dev -# Build documentation in the "docs/" directory with Sphinx sphinx: configuration: docs/conf.py - # You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs - # builder: "dirhtml" - # Fail on all warnings to avoid broken references - # fail_on_warning: true - -# Optionally build your docs in additional formats such as PDF and ePub -# formats: -# - pdf -# - epub - -# Optional but recommended, declare the Python requirements required -# to build your documentation -# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html -python: - install: - - method: pip - path: . - extra_requirements: [docs] + fail_on_warning: true diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b162dc4..6ab9acb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,25 +8,23 @@ You may follow these steps if you wish to create a pull request. Fork the repo a in the project's directory run this if you're on macOS (requires [Homebrew](https://brew.sh)): ```bash -brew install python@3.7 +brew install python brew install poetry # More info: https://python-poetry.org make clean -POETRY_VIRTUALENVS_IN_PROJECT=true poetry env use "$(brew --prefix)/opt/python@3.7/bin/python3" ``` On Ubuntu (including Windows WSL2): ```bash -sudo apt-get update && sudo apt-get install make python3-virtualenv python3.9 -curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/install-poetry.py | python3 - +sudo apt-get update && sudo apt-get install make python3-virtualenv python3 +curl -sSL https://install.python-poetry.org | python3 - make clean -POETRY_VIRTUALENVS_IN_PROJECT=true poetry env use "$(which python3.9)" ``` Then see if you can run lints and tests: ```bash -make all +make deps all ``` ## Writing Tests diff --git a/Makefile b/Makefile index bb6c132..805b7f0 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,5 @@ .DEFAULT_GOAL = help PROJECT_NAME = sphinx_disqus -export POETRY_VIRTUALENVS_IN_PROJECT = true ## Dependencies @@ -8,49 +7,49 @@ poetry.lock: _HELP = Lock dependency versions to file poetry.lock: poetry lock +.PHONY: relock +relock: _HELP = Delete and recreate poetry lock file +relock: + rm -f poetry.lock && $(MAKE) poetry.lock + .PHONY: deps deps: _HELP = Install project dependencies deps: - poetry install -E docs - poetry run python -V - -requirements.txt: _HELP = Generate development requirements.txt -requirements.txt: poetry.lock - poetry export --dev --without-hashes -o $@ + poetry install --with dev ## Testing .PHONY: lint lint: _HELP = Run linters -lint: deps +lint: poetry check poetry run black --check --color --diff . - poetry run flake8 --application-import-names $(PROJECT_NAME),tests - poetry run pylint $(PROJECT_NAME) tests docs/conf.py + poetry run flake8 --application-import-names $(PROJECT_NAME),docs,tests + poetry run pylint $(PROJECT_NAME) docs tests .PHONY: test test: _HELP = Run unit tests -test: deps +test: poetry run pytest --cov=$(PROJECT_NAME) --cov-report=html --cov-report=xml tests/unit_tests .PHONY: testpdb testpdb: _HELP = Run unit tests and drop into the debugger on failure -testpdb: deps +testpdb: poetry run pytest --pdb tests/unit_tests .PHONY: it it: _HELP = Run integration tests -it: deps +it: poetry run pytest tests/integration_tests .PHONY: itpdb itpdb: _HELP = Run integration tests and drop into the debugger on failure -itpdb: deps +itpdb: poetry run pytest --pdb tests/integration_tests .PHONY: all all: _HELP = Run linters, unit tests, integration tests, and builds -all: lint test it docs build +all: test it lint docs build ## Build @@ -59,7 +58,7 @@ build: _HELP = Build Python package (sdist and wheel) build: poetry build -n -vvv -docs/_build/html/index.html: deps +docs/_build/html/index.html:: poetry run sphinx-build -a -E -n -W docs $(@D) @echo Documentation available here: $@ @@ -71,8 +70,8 @@ docs: docs/_build/html/index.html clean: _HELP = Remove temporary files clean: - rm -rfv *.egg-info/ *cache*/ .*cache*/ .coverage coverage.xml htmlcov/ dist/ docs/_build requirements.txt - find . -name __pycache__ -type d -exec rm -r {} + + rm -rfv *.egg-info/ *cache*/ .*cache*/ .coverage* coverage.xml htmlcov/ dist/ docs/_build/ requirements.txt + find . -path '*/.*' -prune -o -name __pycache__ -type d -exec rm -r {} + distclean: _HELP = Remove temporary files including virtualenv distclean: clean diff --git a/poetry.lock b/poetry.lock index fb2949c..7795883 100644 --- a/poetry.lock +++ b/poetry.lock @@ -856,7 +856,7 @@ test = ["cython", "html5lib", "pytest", "pytest-cov", "typed-ast"] name = "sphinx-copybutton" version = "0.5.2" description = "Add a copy button to each of your code cells." -optional = true +optional = false python-versions = ">=3.7" files = [ {file = "sphinx-copybutton-0.5.2.tar.gz", hash = "sha256:4cf17c82fb9646d1bc9ca92ac280813a3b605d8c421225fd9913154103ee1fbd"}, @@ -874,7 +874,7 @@ rtd = ["ipython", "myst-nb", "sphinx", "sphinx-book-theme", "sphinx-examples"] name = "sphinx-notfound-page" version = "0.8.3" description = "Sphinx extension to build a 404 page with absolute URLs" -optional = true +optional = false python-versions = "*" files = [ {file = "sphinx-notfound-page-0.8.3.tar.gz", hash = "sha256:f728403280026b84c234540bebbed7f710b9ea582e7348a35a5becefe4024332"}, @@ -892,7 +892,7 @@ test = ["tox"] name = "sphinx-panels" version = "0.6.0" description = "A sphinx extension for creating panels in a grid layout." -optional = true +optional = false python-versions = "*" files = [ {file = "sphinx-panels-0.6.0.tar.gz", hash = "sha256:d36dcd26358117e11888f7143db4ac2301ebe90873ac00627bf1fe526bf0f058"}, @@ -913,7 +913,7 @@ themes = ["myst-parser (>=0.12.9,<0.13.0)", "pydata-sphinx-theme (>=0.4.0,<0.5.0 name = "sphinx-rtd-theme" version = "1.3.0" description = "Read the Docs theme for Sphinx" -optional = true +optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" files = [ {file = "sphinx_rtd_theme-1.3.0-py2.py3-none-any.whl", hash = "sha256:46ddef89cc2416a81ecfbeaceab1881948c014b1b6e4450b815311a89fb977b0"}, @@ -977,7 +977,7 @@ test = ["html5lib", "pytest"] name = "sphinxcontrib-jquery" version = "4.1" description = "Extension to include jQuery on newer Sphinx releases" -optional = true +optional = false python-versions = ">=2.7" files = [ {file = "sphinxcontrib-jquery-4.1.tar.gz", hash = "sha256:1620739f04e36a2c779f1a131a2dfd49b2fd07351bf1968ced074365933abc7a"}, @@ -1035,7 +1035,7 @@ test = ["pytest"] name = "toml" version = "0.10.2" description = "Python Library for Tom's Obvious, Minimal Language" -optional = true +optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" files = [ {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, @@ -1092,10 +1092,7 @@ h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] -[extras] -docs = ["sphinx-copybutton", "sphinx-notfound-page", "sphinx-panels", "sphinx-rtd-theme", "toml"] - [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "0e5cb16e4d39f145e9c460ddcb746d5363873ad4506f7ed01c09a60bd933a4a9" +content-hash = "55d67eb6dc0113902363596fb9e3660a5eda1e99ebd65ac9a2cb2eea6491fc18" diff --git a/poetry.toml b/poetry.toml new file mode 100644 index 0000000..53b35d3 --- /dev/null +++ b/poetry.toml @@ -0,0 +1,3 @@ +[virtualenvs] +create = true +in-project = true diff --git a/pyproject.toml b/pyproject.toml index 0b1c3b4..2398680 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [build-system] -requires = ["poetry>=0.12"] -build-backend = "poetry.masonry.api" +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" [tool.poetry] name = "sphinx-disqus" @@ -35,19 +35,15 @@ repository = "https://github.com/Robpol86/sphinx-disqus" [tool.poetry.dependencies] python = "^3.8" -# Project dependencies. sphinx = "*" -# Docs. -sphinx-copybutton = {version = "*", optional = true} -sphinx-notfound-page = {version = "*", optional = true} -sphinx-panels = {version = "*", optional = true} -sphinx-rtd-theme = {version = "*", optional = true} -toml = {version = "*", optional = true} - -[tool.poetry.extras] -docs = ["sphinx-notfound-page", "sphinx-panels", "sphinx-rtd-theme", "sphinx-copybutton", "toml"] -[tool.poetry.dev-dependencies] +[tool.poetry.group.dev.dependencies] +# Docs. +sphinx-copybutton = "*" +sphinx-notfound-page = "*" +sphinx-panels = "*" +sphinx-rtd-theme = "*" +toml = "*" # Linters. black = "*" # not semver flake8 = ">=4.0.1"