Skip to content

Commit

Permalink
general: update exporthelper, sync with pymplate, use pyproject.toml
Browse files Browse the repository at this point in the history
  • Loading branch information
karlicoss committed Oct 2, 2023
1 parent e5f7662 commit 037bffc
Show file tree
Hide file tree
Showing 9 changed files with 133 additions and 45 deletions.
2 changes: 1 addition & 1 deletion .ci/run
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@ if ! command -v python3 &> /dev/null; then
fi

"$PY_BIN" -m pip install --user tox
"$PY_BIN" -m tox
"$PY_BIN" -m tox --parallel --parallel-live "$@"
18 changes: 12 additions & 6 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,21 @@ on:
pull_request: # needed to trigger on others' PRs
# Note that people who fork it need to go to "Actions" tab on their fork and click "I understand my workflows, go ahead and enable them".
workflow_dispatch: # needed to trigger workflows manually
# todo cron?
# todo cron?
inputs:
debug_enabled:
type: boolean
description: 'Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)'
required: false
default: false


jobs:
build:
strategy:
matrix:
platform: [ubuntu-latest, macos-latest, windows-latest]
python-version: ['3.7', '3.8', '3.9', '3.10']
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12.0-rc.3']
# vvv just an example of excluding stuff from matrix
# exclude: [{platform: macos-latest, python-version: '3.6'}]

Expand All @@ -28,22 +34,22 @@ jobs:
# ugh https://github.com/actions/toolkit/blob/main/docs/commands.md#path-manipulation
- run: echo "$HOME/.local/bin" >> $GITHUB_PATH

- uses: actions/setup-python@v3
- uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}

- uses: actions/checkout@v3
with:
submodules: recursive

# uncomment for SSH debugging
# - uses: mxschmitt/action-tmate@v3
- uses: mxschmitt/action-tmate@v3
if: ${{ github.event_name == 'workflow_dispatch' && inputs.debug_enabled }}

# explicit bash command is necessary for Windows CI runner, otherwise it thinks it's cmd...
- run: bash .ci/run

- if: matrix.platform == 'ubuntu-latest' # no need to compute coverage for other platforms
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: .coverage.mypy_${{ matrix.platform }}_${{ matrix.python-version }}
path: .coverage.mypy/
Expand Down
38 changes: 38 additions & 0 deletions conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# this is a hack to monkey patch pytest so it handles tests inside namespace packages without __init__.py properly
# without it, pytest can't discover the package root for some reason
# also see https://github.com/karlicoss/pytest_namespace_pkgs for more

import pathlib
from typing import Optional

import _pytest.main
import _pytest.pathlib

# we consider all dirs in repo/ to be namespace packages
root_dir = pathlib.Path(__file__).absolute().parent.resolve() / 'src'
assert root_dir.exists(), root_dir

# TODO assert it contains package name?? maybe get it via setuptools..

namespace_pkg_dirs = [str(d) for d in root_dir.iterdir() if d.is_dir()]

# resolve_package_path is called from _pytest.pathlib.import_path
# takes a full abs path to the test file and needs to return the path to the 'root' package on the filesystem
resolve_pkg_path_orig = _pytest.pathlib.resolve_package_path
def resolve_package_path(path: pathlib.Path) -> Optional[pathlib.Path]:
result = path # search from the test file upwards
for parent in result.parents:
if str(parent) in namespace_pkg_dirs:
return parent
raise RuntimeError("Couldn't determine path for ", path)
_pytest.pathlib.resolve_package_path = resolve_package_path


# without patching, the orig function returns just a package name for some reason
# (I think it's used as a sort of fallback)
# so we need to point it at the absolute path properly
# not sure what are the consequences.. maybe it wouldn't be able to run against installed packages? not sure..
search_pypath_orig = _pytest.main.search_pypath
def search_pypath(module_name: str) -> str:
return str(root_dir)
_pytest.main.search_pypath = search_pypath
7 changes: 6 additions & 1 deletion mypy.ini
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
[mypy]
namespace_packages = True
pretty = True
show_error_context = True
show_error_codes = True
show_column_numbers = True
show_error_end = True
warn_unused_ignores = True
check_untyped_defs = True
namespace_packages = True
enable_error_code = possibly-undefined
strict_equality = True

# an example of suppressing
# [mypy-my.config.repos.pdfannots.pdfannots]
Expand Down
51 changes: 51 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
[project]
dynamic = ["version"] # version is managed by setuptools_scm
name = "pockexport"
dependencies = [
"pocket", # pocket API bindings
]

#
# this needs to be set if you're planning to upload to pypi
# url = ""
# author = ""
# author_email = ""
# description = ""

# Rest like -- classifiers, license, etc, I don't think it matters for pypi
# it's just unnecessary duplication

[project.optional-dependencies]
testing = ["pytest"]
linting = [
"pytest",
"mypy",
"lxml", # for mypy html coverage
"orjson", # exporthelpers
"colorlog", # exporthelpers
]


[build-system]
requires = ["setuptools", "setuptools-scm"]
build-backend = "setuptools.build_meta"

[tool.setuptools_scm]
version_scheme = "python-simplified-semver"
local_scheme = "dirty-tag"


# nice things about pyproject.toml
# - zip_safe=False isn't neccessary anymore
# - correctly discovers namespace packages by defuilt?
# - correctly handles py.typed by default?
# - handles src layout automatically https://setuptools.pypa.io/en/latest/userguide/package_discovery.html#src-layout

# things I'm not sure about yet
# - avoiding dupliation/variable reuse?
# - file/git dependencies?
# - unclear how to specify namespace package order https://github.com/seanbreckenridge/reorder_editable/issues/2

# TODO
# - maybe it has a nicer pypi upload system? not sure
# e.g. possibly use hatch/flit/pdb/poetry -- but not sure what's the benefit tbh
25 changes: 0 additions & 25 deletions setup.py

This file was deleted.

3 changes: 2 additions & 1 deletion src/pockexport/export.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#!/usr/bin/env python3
import json

import pocket # type: ignore
import pocket # type: ignore


class Exporter:
def __init__(self, *args, **kwargs) -> None:
Expand Down
2 changes: 1 addition & 1 deletion src/pockexport/exporthelpers
32 changes: 22 additions & 10 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,32 @@ envlist = tests,mypy
toxworkdir={env:TOXWORKDIR_BASE:}{toxinidir}/.tox

[testenv]
passenv = CI CI_*
# TODO how to get package name from setuptools?
package_name = "pockexport"
passenv =
# useful for tests to know they are running under ci
CI
CI_*
# respect user's cache dirs to prevent tox from crapping into project dir
MYPY_CACHE_DIR
PYTHONPYCACHEPREFIX


[testenv:tests]
commands =
pip install -e .[testing]
{envpython} -m pip install -e .[testing]
# posargs allow test filtering, e.g. tox ... -- -k test_name
python -m pytest src {posargs}
{envpython} -m pytest \
--pyargs {[testenv]package_name} \
{posargs}


[testenv:mypy]
commands =
pip install -e .[linting]
python -m mypy --install-types --non-interactive \
src \
# txt report is a bit more convenient to view on CI
--txt-report .coverage.mypy \
--html-report .coverage.mypy \
{posargs}
{envpython} -m pip install -e .[linting]
{envpython} -m mypy --install-types --non-interactive \
-p {[testenv]package_name} \
# txt report is a bit more convenient to view on CI
--txt-report .coverage.mypy \
--html-report .coverage.mypy \
{posargs}

0 comments on commit 037bffc

Please sign in to comment.