diff --git a/requirements-dev.txt b/requirements-dev.txt index b4b652b..1a8d501 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -2,15 +2,15 @@ Pygments==2.19.2 SecretStorage==3.3.3 black==24.10.0 -build==1.2.2.post1 -certifi==2025.7.14 +build==1.3.0 +certifi==2025.8.3 cffi==1.17.1 changelet==0.1.0 charset-normalizer==3.4.2 click==8.1.8; python_version<'3.10' click==8.2.1; python_version>='3.10' cmarkgfm==2024.11.20 -coverage==7.10.0 +coverage==7.10.1 cryptography==45.0.5 docutils==0.21.2 id==1.5.0 @@ -31,19 +31,19 @@ pathspec==0.12.1 platformdirs==4.3.8 pluggy==1.6.0 pprintpp==0.4.0 -pycountry-convert==0.7.2 pycountry==24.6.1 +pycountry-convert==0.7.2 pycparser==2.22 pyflakes==3.4.0 pyproject_hooks==1.2.0 +pytest==8.4.1 pytest-cov==6.2.1 pytest-mock==3.14.1 -pytest==8.4.1 pytest_network==0.0.1 readme_renderer==44.0 repoze.lru==0.7 -requests-toolbelt==1.0.0 requests==2.32.4 +requests-toolbelt==1.0.0 rfc3986==2.0.0 rich==14.1.0 semver==3.0.4 diff --git a/requirements-docs.txt b/requirements-docs.txt new file mode 100644 index 0000000..05efa5f --- /dev/null +++ b/requirements-docs.txt @@ -0,0 +1,24 @@ +# DO NOT EDIT THIS FILE DIRECTLY - use ./script/update-requirements to update +Jinja2==3.1.6 +MarkupSafe==3.0.2 +Sphinx==8.2.3 +accessible-pygments==0.0.5 +alabaster==1.0.0 +babel==2.17.0 +beautifulsoup4==4.13.4 +furo==2025.7.19 +imagesize==1.4.1 +mdit-py-plugins==0.4.2 +myst-parser==4.0.1 +roman-numerals-py==3.1.0 +snowballstemmer==3.0.1 +soupsieve==2.7 +sphinx-basic-ng==1.0.0b2 +sphinx-copybutton==0.5.2 +sphinxcontrib-applehelp==2.0.0 +sphinxcontrib-devhelp==2.0.0 +sphinxcontrib-htmlhelp==2.1.0 +sphinxcontrib-jsmath==1.0.1 +sphinxcontrib-qthelp==2.0.0 +sphinxcontrib-serializinghtml==2.0.0 +typing_extensions==4.14.1 diff --git a/script/bootstrap b/script/bootstrap index a7d85e7..90071ac 100755 --- a/script/bootstrap +++ b/script/bootstrap @@ -26,7 +26,7 @@ python -m pip install -U 'pip>=10.0.1' python -m pip install -r requirements.txt if [ "$ENV" != "production" ]; then - python -m pip install -r requirements-dev.txt + python -m pip install -r requirements-dev.txt -r requirements-docs.txt fi if [ -d ".git" ]; then diff --git a/script/update-requirements b/script/update-requirements index c1adc47..870b144 100755 --- a/script/update-requirements +++ b/script/update-requirements @@ -1,70 +1,75 @@ #!/usr/bin/env python3 -import re from os.path import join from subprocess import check_call, check_output -from sys import argv +from sys import argv, stdout from tempfile import TemporaryDirectory - -def print_packages(packages, heading): - print(f'{heading}:') - print(' ', end='') - print('\n '.join(packages)) - - -# would be nice if there was a cleaner way to get this, but I've not found a -# more reliable one. -with open('setup.py') as fh: - match = re.search(r"name='(?P[\w-]+)',", fh.read()) - if not match: - raise Exception('failed to determine our package name') - our_package_name = match.group('pkg') - print(f'our_package_name: {our_package_name}') - with TemporaryDirectory() as tmpdir: check_call(['python3', '-m', 'venv', tmpdir]) + def install_and_list(target): + check_call([join(tmpdir, 'bin', 'pip'), 'install', target]) + frozen = ( + check_output([join(tmpdir, 'bin', 'pip'), 'freeze']) + .decode('utf-8') + .strip() + .split('\n') + ) + # file bit skips ourself + return set(p.split('=', 1)[0] for p in frozen if 'file' not in p) + # base needs - check_call([join(tmpdir, 'bin', 'pip'), 'install', '.']) - frozen = check_output([join(tmpdir, 'bin', 'pip'), 'freeze']) - frozen = set(frozen.decode('utf-8').strip().split('\n')) + frozen = install_and_list('.') + # dev needs + dev_frozen = install_and_list('.[dev]') - frozen + # docs needs + docs_frozen = install_and_list('.[docs]') - dev_frozen - frozen - # dev additions - check_call([join(tmpdir, 'bin', 'pip'), 'install', '.[dev]']) - dev_frozen = check_output([join(tmpdir, 'bin', 'pip'), 'freeze']) - dev_frozen = set(dev_frozen.decode('utf-8').strip().split('\n')) - frozen - -# pip installs the module itself along with deps so we need to get that out of -# our list by finding the thing that was file installed during dev -frozen = sorted([p for p in frozen if not p.startswith(our_package_name)]) -dev_frozen = sorted( - [p for p in dev_frozen if not p.startswith(our_package_name)] -) + # find the installed version for each package + versions = {} + for pv in ( + check_output([join(tmpdir, 'bin', 'pip'), 'freeze']) + .decode('utf-8') + .strip() + .split('\n') + ): + if 'file' in pv: + # skip ourself + continue + p, v = pv.split('==') + versions[p] = (v,) # special handling for click until python 3.9 is gone due to it dropping # support for active versions early -i = [i for i, r in enumerate(dev_frozen) if r.startswith('click==')][0] -dev_frozen = ( - dev_frozen[:i] - + [ - "click==8.1.8; python_version<'3.10'", - f"{dev_frozen[i]}; python_version>='3.10'", - ] - + dev_frozen[i + 1 :] +versions['click'] = ( + "8.1.8; python_version<'3.10'", + f"{versions['click'][0]}; python_version>='3.10'", ) -print_packages(frozen, 'frozen') -print_packages(dev_frozen, 'dev_frozen') -script = argv[0] +def write_packages(fh, packages, header, prefix=''): + fh.write(header) + for p in sorted(packages): + for v in versions[p]: + fh.write(prefix) + fh.write(p) + fh.write('==') + fh.write(v) + fh.write('\n') + + +write_packages(stdout, frozen, header='base\n', prefix=' ') +write_packages(stdout, dev_frozen, header='dev\n', prefix=' ') +write_packages(stdout, docs_frozen, header='docs\n', prefix=' ') + +header = f'# DO NOT EDIT THIS FILE DIRECTLY - use {argv[0]} to update\n' with open('requirements.txt', 'w') as fh: - fh.write(f'# DO NOT EDIT THIS FILE DIRECTLY - use {script} to update\n') - fh.write('\n'.join(frozen)) - fh.write('\n') + write_packages(fh, frozen, header=header) with open('requirements-dev.txt', 'w') as fh: - fh.write(f'# DO NOT EDIT THIS FILE DIRECTLY - use {script} to update\n') - fh.write('\n'.join(dev_frozen)) - fh.write('\n') + write_packages(fh, dev_frozen, header=header) + +with open('requirements-docs.txt', 'w') as fh: + write_packages(fh, docs_frozen, header=header) diff --git a/setup.py b/setup.py index c2ca94a..5827ca7 100644 --- a/setup.py +++ b/setup.py @@ -70,7 +70,13 @@ setup( 'pyflakes>=2.2.0', 'readme_renderer[md]>=26.0', 'twine>=3.4.2', - ) + ), + 'docs': ( + 'Sphinx>=8.2.3', + 'furo>=2024.8.6', + 'myst-parser>=4.0.1', + 'sphinx-copybutton>=0.5.2', + ), }, install_requires=( 'PyYaml>=4.2b1',