Skip to content

update to src/ structure and use pyproject.toml #65

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .ci/release
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@ import shutil

is_ci = os.environ.get('CI') is not None

def main():
def main() -> None:
import argparse
p = argparse.ArgumentParser()
p.add_argument('--test', action='store_true', help='use test pypi')
args = p.parse_args()

extra = []
if args.test:
extra.extend(['--repository-url', 'https://test.pypi.org/legacy/'])
extra.extend(['--repository', 'testpypi'])

root = Path(__file__).absolute().parent.parent
os.chdir(root) # just in case
Expand All @@ -42,7 +42,7 @@ def main():
if dist.exists():
shutil.rmtree(dist)

check_call('python3 setup.py sdist bdist_wheel', shell=True)
check_call(['python3', '-m', 'build'])

TP = 'TWINE_PASSWORD'
password = os.environ.get(TP)
Expand Down
32 changes: 24 additions & 8 deletions .ci/run
Original file line number Diff line number Diff line change
@@ -1,24 +1,40 @@
#!/bin/bash -eu
#!/bin/bash
set -eu

cd "$(dirname "$0")"
cd ..
cd .. # git root

if ! command -v sudo; then
# CI or Docker sometimes don't have it, so useful to have a dummy
# CI or Docker sometimes doesn't have it, so useful to have a dummy
function sudo {
"$@"
}
fi

if [ -n "${CI-}" ]; then
# install OS specific stuff here
if [[ "$OSTYPE" == "darwin"* ]]; then
case "$OSTYPE" in
darwin*)
# macos
:
else
;;
cygwin* | msys* | win*)
# windows
:
fi
;;
*)
# must be linux?
:
;;
esac
fi


PY_BIN="python3"
# some systems might have python pointing to python3
if ! command -v python3 &> /dev/null; then
PY_BIN="python"
fi

pip3 install --user tox
tox
"$PY_BIN" -m pip install --user tox
"$PY_BIN" -m tox --parallel --parallel-live "$@"
33 changes: 20 additions & 13 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,32 @@ 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

env:
# useful for scripts & sometimes tests to know
CI: true

jobs:
build:
strategy:
fail-fast: false
matrix:
platform: [ubuntu-latest, macos-latest, windows-latest]
python-version: ['3.7', '3.8', '3.9', '3.10', '3.11']
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'}]

runs-on: ${{ matrix.platform }}

steps:
# ugh https://github.com/actions/toolkit/blob/main/docs/commands.md#path-manipulation
- run: echo "$HOME/.local/bin" >> $GITHUB_PATH

- if: ${{ matrix.platform == 'macos-latest' && matrix.python-version == '3.11' }}
# hmm somehow only seems necessary for 3.11 on osx??
run: echo "$HOME/Library/Python/${{ matrix.python-version }}/bin" >> $GITHUB_PATH

- uses: actions/setup-python@v4
Expand All @@ -41,12 +46,14 @@ jobs:
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 }}

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

- uses: actions/upload-artifact@v3
- if: matrix.platform == 'ubuntu-latest' # no need to compute coverage for other platforms
uses: actions/upload-artifact@v3
with:
name: .coverage.mypy_${{ matrix.platform }}_${{ matrix.python-version }}
path: .coverage.mypy/
Expand All @@ -62,7 +69,7 @@ jobs:

- uses: actions/setup-python@v4
with:
python-version: '3.7'
python-version: '3.8'

- uses: actions/checkout@v3
with:
Expand All @@ -73,12 +80,12 @@ jobs:
if: github.event_name != 'pull_request' && github.event.ref == 'refs/heads/master'
env:
TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD_TEST }}
run: pip3 install --user wheel twine && .ci/release --test
run: pip3 install --user --upgrade build twine && .ci/release --test

- name: 'release to pypi'
# always deploy tags to release pypi
# NOTE: release tags are guarded by on: push: tags on the top
if: github.event_name != 'pull_request' && startsWith(github.event.ref, 'refs/tags')
env:
TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }}
run: pip3 install --user wheel twine && .ci/release
run: pip3 install --user --upgrade build twine && .ci/release
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ doc: cog
## Update files using cog.py
cog: orgparse/__init__.py
orgparse/__init__.py: README.rst
cd orgparse && cog.py -r __init__.py
cd src/orgparse && cog.py -r __init__.py
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
59 changes: 59 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
[project]
dynamic = ["version"] # version is managed by setuptools_scm
name = "orgparse"
description = "orgparse - Emacs org-mode parser in Python"
license = {file = "LICENSE"}
authors = [
{name = "Takafumi Arakaki (@tkf)", email = "[email protected]"},
{name = "Dmitrii Gerasimov (@karlicoss)", email = "[email protected]"},
]
maintainers = [
{name = "Dmitrii Gerasimov (@karlicoss)", email = "[email protected]"},
]
keywords = ["org", "org-mode", "emacs"]
# see: http://pypi.python.org/pypi?%3Aaction=list_classifiers
classifiers = [
"Development Status :: 5 - Production/Stable",
"License :: OSI Approved :: BSD License",
"Topic :: Text Processing :: Markup",
]
# TODO add it back later, perhaps via ast?
# long_description=orgparse.__doc__,

[project.urls]
Homepage = "https://github.com/karlicoss/orgparse"

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


[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
3 changes: 3 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@ addopts =

# otherwise it won't discover doctests
--doctest-modules

# show all test durations (unless they are too short)
--durations=0
54 changes: 0 additions & 54 deletions setup.py

This file was deleted.

2 changes: 0 additions & 2 deletions orgparse/__init__.py → src/orgparse/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,6 @@

from .node import parse_lines, OrgEnv, OrgNode # todo basenode??

__author__ = 'Takafumi Arakaki, Dmitrii Gerasimov'
__license__ = 'BSD License'
__all__ = ["load", "loads", "loadi"]


Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
def load_data(path):
"""Load data from python file"""
ns = {} # type: ignore
exec(Path(path).read_text(), ns)
# read_bytes() and compile hackery to avoid encoding issues (e.g. see 05_tags)
exec(compile(Path(path).read_bytes(), path, 'exec'), ns)
return ns['data']


Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
38 changes: 28 additions & 10 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,39 @@
minversion = 3.7
# relies on the correct version of Python installed
envlist = tests,mypy
# https://github.com/tox-dev/tox/issues/20#issuecomment-247788333
# hack to prevent .tox from crapping to the project directory
toxworkdir={env:TOXWORKDIR_BASE:}{toxinidir}/.tox

[testenv]
passenv = CI,CI_*
# TODO how to get package name from setuptools?
package_name = "orgparse"
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


# note: --use-pep517 here is necessary for tox --parallel flag to work properly
# otherwise it seems that it tries to modify .eggs dir in parallel and it fails
[testenv:tests]
commands =
pip install -e .[testing]
python -m pytest --ignore-glob='**/_py3compat.py' orgparse {posargs}
{envpython} -m pip install --use-pep517 -e .[testing]
# posargs allow test filtering, e.g. tox ... -- -k test_name
{envpython} -m pytest \
--pyargs {[testenv]package_name} \
{posargs}


[testenv:mypy]
commands =
pip install -e .[linting]
python -m mypy --install-types --non-interactive \
orgparse \
# txt report is a bit more convenient to view on CI
--txt-report .coverage.mypy \
--html-report .coverage.mypy \
{posargs}
{envpython} -m pip install --use-pep517 -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}