diff --git a/.gitignore b/.gitignore index 5c8bfee..2351bda 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,5 @@ /configure~ *.swo *.swp +/test-reports/ +/.tox/ diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md new file mode 100644 index 0000000..93093de --- /dev/null +++ b/DEVELOPMENT.md @@ -0,0 +1,122 @@ +# Development + +> All changes MUST follow the vendor/tiara-gitflow-spec.git and no work MUST be +> started without a TODO issue. + +## Prerequisites + +- Python 3.9+ +- [Pipenv](https://pipenv.pypa.io/) +- [tox](https://tox.wiki/) (installed via Pipenv dev dependencies) +- Node.js (for the `@byteb4rb1e/mime-todo` issue tracker CLI) + +## Setup + +Iniitialize Git submodules: + +```bash +git submodule update --init --remote --recursive +``` + +Install dependencies (includes the package in editable mode): + +```bash +pipenv install --dev +``` + + +## Tooling + +### Package + +The project is packaged as `byteb4rb1e.utils` under a namespace package +layout (`src/byteb4rb1e/utils/`). It is installed in editable mode via +Pipenv. + +Build a distribution: + +```bash +pipenv run dist +``` + +### Testing + +Tests are managed by tox. Test environments are defined in `tox.ini`: + +```bash +# run all test suites +tox + +# run specific environments +tox -e unit-py313 +tox -e lint +tox -e format +``` + +| Environment | Purpose | +|---|---| +| `unit-py3{9-13}` | Unit tests | +| `smoke-py3{9-13}` | Smoke tests | +| `integration-py3{9-13}` | Integration tests | +| `lint` | Type checking (mypy) | +| `format` | Code style (autopep8) | +| `audit` | Dependency audit (pip-audit) | + +### Issue tracker + +Issues are tracked in the `TODO` file using the +[MIME TODO](https://specs.code.tiararodney.com/mime-todo/) format. Use the +`@byteb4rb1e/mime-todo` CLI to interact with it: + +```bash +# list issues +npx @byteb4rb1e/mime-todo list + +# show a specific issue +npx @byteb4rb1e/mime-todo show 3 + +# create an issue +npx @byteb4rb1e/mime-todo create --type feature --title "Title" --plan "Description" --module homeostat +``` + +See [CONTRIBUTING.md](CONTRIBUTING.md) for the full issue lifecycle. + +### Publishing + +Build wheel and source distributions: + +```sh +pipenv run sdist +``` + +Configure publishing options: + +`~/.pypirc` +``` +[distutils] +index-servers = + tiararodney + +[tiararodney] +repository: https://pypi.code.tiararodney.com/root/byteb4rb1e/ +username: +password: +``` + +Publish to pypi.code.tiararodney.com: + +```sh +pipenv run sdist:publish:tiarardoney +``` + + +## Project layout + +``` +src/byteb4rb1e/utils/ # package source +tests/ # test suites (unit/, smoke/, integration/) +vendor/ # vendored specs +dist/ # sdist and wheel build output +DEVELOPMENT.md # this file +TODO # issue tracker (MIME TODO format) +``` diff --git a/src/byteb4rb1e_utils/http/__init__.py b/LICENSE similarity index 100% rename from src/byteb4rb1e_utils/http/__init__.py rename to LICENSE diff --git a/Makefile b/Makefile deleted file mode 100644 index 37439f1..0000000 --- a/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -.PHONY: chore configure - -chore: configure Pipfile.lock requirements-dev.txt - -Pipfile.lock: .venv Pipfile - .venv/bin/pipenv lock - -requirements-dev.txt: .venv Pipfile.lock - .venv/bin/pipenv requirements --dev-only > requirements-dev.txt - -configure: configure.ac - autoconf - -.venv: requirements-dev.txt - python3 -m venv .venv - .venv/bin/python3 -m pip install --upgrade pip - .venv/bin/pip install -r requirements-dev.txt - -test-reports: - .venv/bin/python3 -m unittest discover -v - -build: .venv/bin/pipenv - .venv/bin/pipenv run build - diff --git a/Pipfile b/Pipfile index 89a5cd3..8671f4d 100644 --- a/Pipfile +++ b/Pipfile @@ -4,17 +4,25 @@ verify_ssl = true name = "pypi" [dev-packages] -mypy = "~=1.15.0" -autopep8 = "~=2.3.2" setuptools-scm = "~=8.2.0" -pylint = "~=3.3.6" build = "*" pipenv = "*" -byteb4rb1e-utils = { editable = true, path = '.'} +tox = "*" +twine = "*" +pypi-attestations = "*" +autopep8 = "*" [requires] -python_version = "3.11" +python_version = "3" [scripts] -"build" = "python3 -m build" +"dist" = "python3 -m build" +"dist:attestations" = "python3 -m pypi_attestations sign dist/*" +"dist:publish:tiararodney" = "python3 -m twine upload --sign --repository tiararodney dist/*" +"test" = "tox" +"test:static" = "tox run -m static" +"test:unit" = "tox run -m unit" +"test:integration" = "tox run -m integration" +[packages] +"byteb4rb1e.utils" = {file = ".", editable = true} diff --git a/Pipfile.lock b/Pipfile.lock index 7f78522..d715cea 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,11 +1,11 @@ { "_meta": { "hash": { - "sha256": "4847baa5a13a96f2c3de2a246a0c088806c308426c79d8105387dff1fe1f1e58" + "sha256": "7bf1e5e3285cb7ead9e247720d2abc340a64c17d42127e41745bff3309521b41" }, "pipfile-spec": 6, "requires": { - "python_version": "3.11" + "python_version": "3" }, "sources": [ { @@ -15,15 +15,20 @@ } ] }, - "default": {}, + "default": { + "byteb4rb1e.utils": { + "editable": true, + "file": "." + } + }, "develop": { - "astroid": { + "annotated-types": { "hashes": [ - "sha256:622cc8e3048684aa42c820d9d218978021c3c3d174fb03a9f0d615921744f550", - "sha256:d05bfd0acba96a7bd43e222828b7d9bc1e138aaeb0649707908d3702a9831248" + "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", + "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89" ], - "markers": "python_full_version >= '3.9.0'", - "version": "==3.3.9" + "markers": "python_version >= '3.8'", + "version": "==0.7.0" }, "autopep8": { "hashes": [ @@ -36,24 +41,253 @@ }, "build": { "hashes": [ - "sha256:1d61c0887fa860c01971625baae8bdd338e517b836a2f70dd1f7aa3a6b2fc5b5", - "sha256:b36993e92ca9375a219c99e606a122ff365a760a2d4bba0caa09bd5278b608b7" + "sha256:6a07c1b8eb6f2b311b96fcbdbce5dab5fe637ffda0fd83c9cac622e927501596", + "sha256:f1b91b925aa322be454f8330c6fb48b465da993d1e7e7e6fa35027ec49f3c936" ], "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==1.2.2.post1" + "markers": "python_version >= '3.9'", + "version": "==1.4.0" }, - "byteb4rb1e-utils": { - "editable": true, - "path": "." + "cachetools": { + "hashes": [ + "sha256:0cd042c24377200c1dcd225f8b7b12b0ca53cc2c961b43757e774ebe190fd990", + "sha256:46bc8ebefbe485407621d0a4264b23c080cedd913921bad7ac3ed2f26c183114" + ], + "markers": "python_version >= '3.10'", + "version": "==7.0.5" }, "certifi": { "hashes": [ - "sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6", - "sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3" + "sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa", + "sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7" ], - "markers": "python_version >= '3.6'", - "version": "==2025.4.26" + "markers": "python_version >= '3.7'", + "version": "==2026.2.25" + }, + "cffi": { + "hashes": [ + "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb", + "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b", + "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f", + "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9", + "sha256:0cf2d91ecc3fcc0625c2c530fe004f82c110405f101548512cce44322fa8ac44", + "sha256:0f6084a0ea23d05d20c3edcda20c3d006f9b6f3fefeac38f59262e10cef47ee2", + "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c", + "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75", + "sha256:1cd13c99ce269b3ed80b417dcd591415d3372bcac067009b6e0f59c7d4015e65", + "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e", + "sha256:1f72fb8906754ac8a2cc3f9f5aaa298070652a0ffae577e0ea9bd480dc3c931a", + "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e", + "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25", + "sha256:2081580ebb843f759b9f617314a24ed5738c51d2aee65d31e02f6f7a2b97707a", + "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe", + "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b", + "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91", + "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592", + "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187", + "sha256:2de9a304e27f7596cd03d16f1b7c72219bd944e99cc52b84d0145aefb07cbd3c", + "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1", + "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94", + "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba", + "sha256:3e837e369566884707ddaf85fc1744b47575005c0a229de3327f8f9a20f4efeb", + "sha256:3f4d46d8b35698056ec29bca21546e1551a205058ae1a181d871e278b0b28165", + "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", + "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca", + "sha256:4647afc2f90d1ddd33441e5b0e85b16b12ddec4fca55f0d9671fef036ecca27c", + "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6", + "sha256:53f77cbe57044e88bbd5ed26ac1d0514d2acf0591dd6bb02a3ae37f76811b80c", + "sha256:5eda85d6d1879e692d546a078b44251cdd08dd1cfb98dfb77b670c97cee49ea0", + "sha256:5fed36fccc0612a53f1d4d9a816b50a36702c28a2aa880cb8a122b3466638743", + "sha256:61d028e90346df14fedc3d1e5441df818d095f3b87d286825dfcbd6459b7ef63", + "sha256:66f011380d0e49ed280c789fbd08ff0d40968ee7b665575489afa95c98196ab5", + "sha256:6824f87845e3396029f3820c206e459ccc91760e8fa24422f8b0c3d1731cbec5", + "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4", + "sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d", + "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b", + "sha256:730cacb21e1bdff3ce90babf007d0a0917cc3e6492f336c2f0134101e0944f93", + "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205", + "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27", + "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512", + "sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d", + "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c", + "sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037", + "sha256:8941aaadaf67246224cee8c3803777eed332a19d909b47e29c9842ef1e79ac26", + "sha256:89472c9762729b5ae1ad974b777416bfda4ac5642423fa93bd57a09204712322", + "sha256:8ea985900c5c95ce9db1745f7933eeef5d314f0565b27625d9a10ec9881e1bfb", + "sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c", + "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8", + "sha256:9332088d75dc3241c702d852d4671613136d90fa6881da7d770a483fd05248b4", + "sha256:94698a9c5f91f9d138526b48fe26a199609544591f859c870d477351dc7b2414", + "sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9", + "sha256:9de40a7b0323d889cf8d23d1ef214f565ab154443c42737dfe52ff82cf857664", + "sha256:a05d0c237b3349096d3981b727493e22147f934b20f6f125a3eba8f994bec4a9", + "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775", + "sha256:b18a3ed7d5b3bd8d9ef7a8cb226502c6bf8308df1525e1cc676c3680e7176739", + "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc", + "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062", + "sha256:b4c854ef3adc177950a8dfc81a86f5115d2abd545751a304c5bcf2c2c7283cfe", + "sha256:b882b3df248017dba09d6b16defe9b5c407fe32fc7c65a9c69798e6175601be9", + "sha256:baf5215e0ab74c16e2dd324e8ec067ef59e41125d3eade2b863d294fd5035c92", + "sha256:c649e3a33450ec82378822b3dad03cc228b8f5963c0c12fc3b1e0ab940f768a5", + "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13", + "sha256:c6638687455baf640e37344fe26d37c404db8b80d037c3d29f58fe8d1c3b194d", + "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26", + "sha256:cb527a79772e5ef98fb1d700678fe031e353e765d1ca2d409c92263c6d43e09f", + "sha256:cf364028c016c03078a23b503f02058f1814320a56ad535686f90565636a9495", + "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b", + "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6", + "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c", + "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef", + "sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5", + "sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18", + "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad", + "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3", + "sha256:de8dad4425a6ca6e4e5e297b27b5c824ecc7581910bf9aee86cb6835e6812aa7", + "sha256:e11e82b744887154b182fd3e7e8512418446501191994dbf9c9fc1f32cc8efd5", + "sha256:e6e73b9e02893c764e7e8d5bb5ce277f1a009cd5243f8228f75f842bf937c534", + "sha256:f73b96c41e3b2adedc34a7356e64c8eb96e03a3782b535e043a986276ce12a49", + "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2", + "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5", + "sha256:fc7de24befaeae77ba923797c7c87834c73648a05a4bde34b3b7e5588973a453", + "sha256:fe562eb1a64e67dd297ccc4f5addea2501664954f2692b69a76449ec7913ecbf" + ], + "markers": "python_version >= '3.9'", + "version": "==2.0.0" + }, + "charset-normalizer": { + "hashes": [ + "sha256:06a7e86163334edfc5d20fe104db92fcd666e5a5df0977cb5680a506fe26cc8e", + "sha256:0c173ce3a681f309f31b87125fecec7a5d1347261ea11ebbb856fa6006b23c8c", + "sha256:0e28d62a8fc7a1fa411c43bd65e346f3bce9716dc51b897fbe930c5987b402d5", + "sha256:0e901eb1049fdb80f5bd11ed5ea1e498ec423102f7a9b9e4645d5b8204ff2815", + "sha256:11afb56037cbc4b1555a34dd69151e8e069bee82e613a73bef6e714ce733585f", + "sha256:150b8ce8e830eb7ccb029ec9ca36022f756986aaaa7956aad6d9ec90089338c0", + "sha256:172985e4ff804a7ad08eebec0a1640ece87ba5041d565fff23c8f99c1f389484", + "sha256:197c1a244a274bb016dd8b79204850144ef77fe81c5b797dc389327adb552407", + "sha256:1ae6b62897110aa7c79ea2f5dd38d1abca6db663687c0b1ad9aed6f6bae3d9d6", + "sha256:1cf0a70018692f85172348fe06d3a4b63f94ecb055e13a00c644d368eb82e5b8", + "sha256:1ed80ff870ca6de33f4d953fda4d55654b9a2b340ff39ab32fa3adbcd718f264", + "sha256:22c6f0c2fbc31e76c3b8a86fba1a56eda6166e238c29cdd3d14befdb4a4e4815", + "sha256:231d4da14bcd9301310faf492051bee27df11f2bc7549bc0bb41fef11b82daa2", + "sha256:259695e2ccc253feb2a016303543d691825e920917e31f894ca1a687982b1de4", + "sha256:2a24157fa36980478dd1770b585c0f30d19e18f4fb0c47c13aa568f871718579", + "sha256:2b1a63e8224e401cafe7739f77efd3f9e7f5f2026bda4aead8e59afab537784f", + "sha256:2bd9d128ef93637a5d7a6af25363cf5dec3fa21cf80e68055aad627f280e8afa", + "sha256:2e1d8ca8611099001949d1cdfaefc510cf0f212484fe7c565f735b68c78c3c95", + "sha256:2ef7fedc7a6ecbe99969cd09632516738a97eeb8bd7258bf8a0f23114c057dab", + "sha256:2f7fdd9b6e6c529d6a2501a2d36b240109e78a8ceaef5687cfcfa2bbe671d297", + "sha256:30f445ae60aad5e1f8bdbb3108e39f6fbc09f4ea16c815c66578878325f8f15a", + "sha256:31215157227939b4fb3d740cd23fe27be0439afef67b785a1eb78a3ae69cba9e", + "sha256:34315ff4fc374b285ad7f4a0bf7dcbfe769e1b104230d40f49f700d4ab6bbd84", + "sha256:3516bbb8d42169de9e61b8520cbeeeb716f12f4ecfe3fd30a9919aa16c806ca8", + "sha256:3778fd7d7cd04ae8f54651f4a7a0bd6e39a0cf20f801720a4c21d80e9b7ad6b0", + "sha256:39f5068d35621da2881271e5c3205125cc456f54e9030d3f723288c873a71bf9", + "sha256:404a1e552cf5b675a87f0651f8b79f5f1e6fd100ee88dc612f89aa16abd4486f", + "sha256:419a9d91bd238052642a51938af8ac05da5b3343becde08d5cdeab9046df9ee1", + "sha256:423fb7e748a08f854a08a222b983f4df1912b1daedce51a72bd24fe8f26a1843", + "sha256:4482481cb0572180b6fd976a4d5c72a30263e98564da68b86ec91f0fe35e8565", + "sha256:461598cd852bfa5a61b09cae2b1c02e2efcd166ee5516e243d540ac24bfa68a7", + "sha256:47955475ac79cc504ef2704b192364e51d0d473ad452caedd0002605f780101c", + "sha256:48696db7f18afb80a068821504296eb0787d9ce239b91ca15059d1d3eaacf13b", + "sha256:4be9f4830ba8741527693848403e2c457c16e499100963ec711b1c6f2049b7c7", + "sha256:4d1d02209e06550bdaef34af58e041ad71b88e624f5d825519da3a3308e22687", + "sha256:4f41da960b196ea355357285ad1316a00099f22d0929fe168343b99b254729c9", + "sha256:517ad0e93394ac532745129ceabdf2696b609ec9f87863d337140317ebce1c14", + "sha256:51fb3c322c81d20567019778cb5a4a6f2dc1c200b886bc0d636238e364848c89", + "sha256:5273b9f0b5835ff0350c0828faea623c68bfa65b792720c453e22b25cc72930f", + "sha256:530d548084c4a9f7a16ed4a294d459b4f229db50df689bfe92027452452943a0", + "sha256:530e8cebeea0d76bdcf93357aa5e41336f48c3dc709ac52da2bb167c5b8271d9", + "sha256:54fae94be3d75f3e573c9a1b5402dc593de19377013c9a0e4285e3d402dd3a2a", + "sha256:572d7c822caf521f0525ba1bce1a622a0b85cf47ffbdae6c9c19e3b5ac3c4389", + "sha256:58c948d0d086229efc484fe2f30c2d382c86720f55cd9bc33591774348ad44e0", + "sha256:5d11595abf8dd942a77883a39d81433739b287b6aa71620f15164f8096221b30", + "sha256:5f8ddd609f9e1af8c7bd6e2aca279c931aefecd148a14402d4e368f3171769fd", + "sha256:5feb91325bbceade6afab43eb3b508c63ee53579fe896c77137ded51c6b6958e", + "sha256:60c74963d8350241a79cb8feea80e54d518f72c26db618862a8f53e5023deaf9", + "sha256:613f19aa6e082cf96e17e3ffd89383343d0d589abda756b7764cf78361fd41dc", + "sha256:659a1e1b500fac8f2779dd9e1570464e012f43e580371470b45277a27baa7532", + "sha256:695f5c2823691a25f17bc5d5ffe79fa90972cc34b002ac6c843bb8a1720e950d", + "sha256:69dd852c2f0ad631b8b60cfbe25a28c0058a894de5abb566619c205ce0550eae", + "sha256:6cceb5473417d28edd20c6c984ab6fee6c6267d38d906823ebfe20b03d607dc2", + "sha256:71be7e0e01753a89cf024abf7ecb6bca2c81738ead80d43004d9b5e3f1244e64", + "sha256:74119174722c4349af9708993118581686f343adc1c8c9c007d59be90d077f3f", + "sha256:74a2e659c7ecbc73562e2a15e05039f1e22c75b7c7618b4b574a3ea9118d1557", + "sha256:7504e9b7dc05f99a9bbb4525c67a2c155073b44d720470a148b34166a69c054e", + "sha256:79090741d842f564b1b2827c0b82d846405b744d31e84f18d7a7b41c20e473ff", + "sha256:7a6967aaf043bceabab5412ed6bd6bd26603dae84d5cb75bf8d9a74a4959d398", + "sha256:7bda6eebafd42133efdca535b04ccb338ab29467b3f7bf79569883676fc628db", + "sha256:7edbed096e4a4798710ed6bc75dcaa2a21b68b6c356553ac4823c3658d53743a", + "sha256:7f9019c9cb613f084481bd6a100b12e1547cf2efe362d873c2e31e4035a6fa43", + "sha256:802168e03fba8bbc5ce0d866d589e4b1ca751d06edee69f7f3a19c5a9fe6b597", + "sha256:80d0a5615143c0b3225e5e3ef22c8d5d51f3f72ce0ea6fb84c943546c7b25b6c", + "sha256:82060f995ab5003a2d6e0f4ad29065b7672b6593c8c63559beefe5b443242c3e", + "sha256:836ab36280f21fc1a03c99cd05c6b7af70d2697e374c7af0b61ed271401a72a2", + "sha256:8761ac29b6c81574724322a554605608a9960769ea83d2c73e396f3df896ad54", + "sha256:87725cfb1a4f1f8c2fc9890ae2f42094120f4b44db9360be5d99a4c6b0e03a9e", + "sha256:899d28f422116b08be5118ef350c292b36fc15ec2daeb9ea987c89281c7bb5c4", + "sha256:8bc5f0687d796c05b1e28ab0d38a50e6309906ee09375dd3aff6a9c09dd6e8f4", + "sha256:8bea55c4eef25b0b19a0337dc4e3f9a15b00d569c77211fa8cde38684f234fb7", + "sha256:8e5a94886bedca0f9b78fecd6afb6629142fd2605aa70a125d49f4edc6037ee6", + "sha256:90ca27cd8da8118b18a52d5f547859cc1f8354a00cd1e8e5120df3e30d6279e5", + "sha256:92734d4d8d187a354a556626c221cd1a892a4e0802ccb2af432a1d85ec012194", + "sha256:947cf925bc916d90adba35a64c82aace04fa39b46b52d4630ece166655905a69", + "sha256:95b52c68d64c1878818687a473a10547b3292e82b6f6fe483808fb1468e2f52f", + "sha256:97d0235baafca5f2b09cf332cc275f021e694e8362c6bb9c96fc9a0eb74fc316", + "sha256:9ca4c0b502ab399ef89248a2c84c54954f77a070f28e546a85e91da627d1301e", + "sha256:9cc4fc6c196d6a8b76629a70ddfcd4635a6898756e2d9cac5565cf0654605d73", + "sha256:9cc6e6d9e571d2f863fa77700701dae73ed5f78881efc8b3f9a4398772ff53e8", + "sha256:a056d1ad2633548ca18ffa2f85c202cfb48b68615129143915b8dc72a806a923", + "sha256:a26611d9987b230566f24a0a125f17fe0de6a6aff9f25c9f564aaa2721a5fb88", + "sha256:a4474d924a47185a06411e0064b803c68be044be2d60e50e8bddcc2649957c1f", + "sha256:a4ea868bc28109052790eb2b52a9ab33f3aa7adc02f96673526ff47419490e21", + "sha256:a9e68c9d88823b274cf1e72f28cb5dc89c990edf430b0bfd3e2fb0785bfeabf4", + "sha256:aa9cccf4a44b9b62d8ba8b4dd06c649ba683e4bf04eea606d2e94cfc2d6ff4d6", + "sha256:ab30e5e3e706e3063bc6de96b118688cb10396b70bb9864a430f67df98c61ecc", + "sha256:ac2393c73378fea4e52aa56285a3d64be50f1a12395afef9cce47772f60334c2", + "sha256:ad8faf8df23f0378c6d527d8b0b15ea4a2e23c89376877c598c4870d1b2c7866", + "sha256:b35b200d6a71b9839a46b9b7fff66b6638bb52fc9658aa58796b0326595d3021", + "sha256:b3694e3f87f8ac7ce279d4355645b3c878d24d1424581b46282f24b92f5a4ae2", + "sha256:b4ff1d35e8c5bd078be89349b6f3a845128e685e751b6ea1169cf2160b344c4d", + "sha256:bbc8c8650c6e51041ad1be191742b8b421d05bbd3410f43fa2a00c8db87678e8", + "sha256:bc72863f4d9aba2e8fd9085e63548a324ba706d2ea2c83b260da08a59b9482de", + "sha256:bf625105bb9eef28a56a943fec8c8a98aeb80e7d7db99bd3c388137e6eb2d237", + "sha256:c2274ca724536f173122f36c98ce188fd24ce3dad886ec2b7af859518ce008a4", + "sha256:c45a03a4c69820a399f1dda9e1d8fbf3562eda46e7720458180302021b08f778", + "sha256:c8ae56368f8cc97c7e40a7ee18e1cedaf8e780cd8bc5ed5ac8b81f238614facb", + "sha256:c907cdc8109f6c619e6254212e794d6548373cc40e1ec75e6e3823d9135d29cc", + "sha256:ca0276464d148c72defa8bb4390cce01b4a0e425f3b50d1435aa6d7a18107602", + "sha256:cd5e2801c89992ed8c0a3f0293ae83c159a60d9a5d685005383ef4caca77f2c4", + "sha256:d08ec48f0a1c48d75d0356cea971921848fb620fdeba805b28f937e90691209f", + "sha256:d1a2ee9c1499fc8f86f4521f27a973c914b211ffa87322f4ee33bb35392da2c5", + "sha256:d5f5d1e9def3405f60e3ca8232d56f35c98fb7bf581efcc60051ebf53cb8b611", + "sha256:d60377dce4511655582e300dc1e5a5f24ba0cb229005a1d5c8d0cb72bb758ab8", + "sha256:d73beaac5e90173ac3deb9928a74763a6d230f494e4bfb422c217a0ad8e629bf", + "sha256:d7de2637729c67d67cf87614b566626057e95c303bc0a55ffe391f5205e7003d", + "sha256:dad6e0f2e481fffdcf776d10ebee25e0ef89f16d691f1e5dee4b586375fdc64b", + "sha256:dda86aba335c902b6149a02a55b38e96287157e609200811837678214ba2b1db", + "sha256:df01808ee470038c3f8dc4f48620df7225c49c2d6639e38f96e6d6ac6e6f7b0e", + "sha256:e1f6e2f00a6b8edb562826e4632e26d063ac10307e80f7461f7de3ad8ef3f077", + "sha256:e25369dc110d58ddf29b949377a93e0716d72a24f62bad72b2b39f155949c1fd", + "sha256:e3c701e954abf6fc03a49f7c579cc80c2c6cc52525340ca3186c41d3f33482ef", + "sha256:e5bcc1a1ae744e0bb59641171ae53743760130600da8db48cbb6e4918e186e4e", + "sha256:e68c14b04827dd76dcbd1aeea9e604e3e4b78322d8faf2f8132c7138efa340a8", + "sha256:e8aeb10fcbe92767f0fa69ad5a72deca50d0dca07fbde97848997d778a50c9fe", + "sha256:e985a16ff513596f217cee86c21371b8cd011c0f6f056d0920aa2d926c544058", + "sha256:ecbbd45615a6885fe3240eb9db73b9e62518b611850fdf8ab08bd56de7ad2b17", + "sha256:ee4ec14bc1680d6b0afab9aea2ef27e26d2024f18b24a2d7155a52b60da7e833", + "sha256:ef5960d965e67165d75b7c7ffc60a83ec5abfc5c11b764ec13ea54fbef8b4421", + "sha256:f0cdaecd4c953bfae0b6bb64910aaaca5a424ad9c72d85cb88417bb9814f7550", + "sha256:f1ce721c8a7dfec21fcbdfe04e8f68174183cf4e8188e0645e92aa23985c57ff", + "sha256:f50498891691e0864dc3da965f340fada0771f6142a378083dc4608f4ea513e2", + "sha256:f5ea69428fa1b49573eef0cc44a1d43bebd45ad0c611eb7d7eac760c7ae771bc", + "sha256:f61aa92e4aad0be58eb6eb4e0c21acf32cf8065f4b2cae5665da756c4ceef982", + "sha256:f6e4333fb15c83f7d1482a76d45a0818897b3d33f00efd215528ff7c51b8e35d", + "sha256:f820f24b09e3e779fe84c3c456cb4108a7aa639b0d1f02c28046e11bfcd088ed", + "sha256:f98059e4fcd3e3e4e2d632b7cf81c2faae96c43c60b569e9c621468082f1d104", + "sha256:fcce033e4021347d80ed9c66dcf1e7b1546319834b74445f561d2e2221de5659" + ], + "markers": "python_version >= '3.7'", + "version": "==3.4.6" }, "colorama": { "hashes": [ @@ -63,133 +297,448 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'", "version": "==0.4.6" }, - "dill": { + "cryptography": { "hashes": [ - "sha256:0633f1d2df477324f53a895b02c901fb961bdbf65a17122586ea7019292cbcf0", - "sha256:44f54bf6412c2c8464c14e8243eb163690a9800dbe2c367330883b19c7561049" + "sha256:02f547fce831f5096c9a567fd41bc12ca8f11df260959ecc7c3202555cc47a72", + "sha256:039917b0dc418bb9f6edce8a906572d69e74bd330b0b3fea4f79dab7f8ddd235", + "sha256:1abfdb89b41c3be0365328a410baa9df3ff8a9110fb75e7b52e66803ddabc9a9", + "sha256:2ae6971afd6246710480e3f15824ed3029a60fc16991db250034efd0b9fb4356", + "sha256:2b7a67c9cd56372f3249b39699f2ad479f6991e62ea15800973b956f4b73e257", + "sha256:351695ada9ea9618b3500b490ad54c739860883df6c1f555e088eaf25b1bbaad", + "sha256:38946c54b16c885c72c4f59846be9743d699eee2b69b6988e0a00a01f46a61a4", + "sha256:3b4995dc971c9fb83c25aa44cf45f02ba86f71ee600d81091c2f0cbae116b06c", + "sha256:3ce58ba46e1bc2aac4f7d9290223cead56743fa6ab94a5d53292ffaac6a91614", + "sha256:3ee190460e2fbe447175cda91b88b84ae8322a104fc27766ad09428754a618ed", + "sha256:4108d4c09fbbf2789d0c926eb4152ae1760d5a2d97612b92d508d96c861e4d31", + "sha256:420d0e909050490d04359e7fdb5ed7e667ca5c3c402b809ae2563d7e66a92229", + "sha256:47fb8a66058b80e509c47118ef8a75d14c455e81ac369050f20ba0d23e77fee0", + "sha256:4c3341037c136030cb46e4b1e17b7418ea4cbd9dd207e4a6f3b2b24e0d4ac731", + "sha256:4d7e3d356b8cd4ea5aff04f129d5f66ebdc7b6f8eae802b93739ed520c47c79b", + "sha256:4d8ae8659ab18c65ced284993c2265910f6c9e650189d4e3f68445ef82a810e4", + "sha256:4e817a8920bfbcff8940ecfd60f23d01836408242b30f1a708d93198393a80b4", + "sha256:50bfb6925eff619c9c023b967d5b77a54e04256c4281b0e21336a130cd7fc263", + "sha256:556e106ee01aa13484ce9b0239bca667be5004efb0aabbed28d353df86445595", + "sha256:582f5fcd2afa31622f317f80426a027f30dc792e9c80ffee87b993200ea115f1", + "sha256:5be7bf2fb40769e05739dd0046e7b26f9d4670badc7b032d6ce4db64dddc0678", + "sha256:60ee7e19e95104d4c03871d7d7dfb3d22ef8a9b9c6778c94e1c8fcc8365afd48", + "sha256:61aa400dce22cb001a98014f647dc21cda08f7915ceb95df0c9eaf84b4b6af76", + "sha256:68f68d13f2e1cb95163fa3b4db4bf9a159a418f5f6e7242564fc75fcae667fd0", + "sha256:7d1f30a86d2757199cb2d56e48cce14deddf1f9c95f1ef1b64ee91ea43fe2e18", + "sha256:7d731d4b107030987fd61a7f8ab512b25b53cef8f233a97379ede116f30eb67d", + "sha256:803812e111e75d1aa73690d2facc295eaefd4439be1023fefc4995eaea2af90d", + "sha256:80a8d7bfdf38f87ca30a5391c0c9ce4ed2926918e017c29ddf643d0ed2778ea1", + "sha256:8293f3dea7fc929ef7240796ba231413afa7b68ce38fd21da2995549f5961981", + "sha256:8456928655f856c6e1533ff59d5be76578a7157224dbd9ce6872f25055ab9ab7", + "sha256:890bcb4abd5a2d3f852196437129eb3667d62630333aacc13dfd470fad3aaa82", + "sha256:94a76daa32eb78d61339aff7952ea819b1734b46f73646a07decb40e5b3448e2", + "sha256:9f16fbdf4da055efb21c22d81b89f155f02ba420558db21288b3d0035bafd5f4", + "sha256:a3d1fae9863299076f05cb8a778c467578262fae09f9dc0ee9b12eb4268ce663", + "sha256:a3d507bb6a513ca96ba84443226af944b0f7f47dcc9a399d110cd6146481d24c", + "sha256:abace499247268e3757271b2f1e244b36b06f8515cf27c4d49468fc9eb16e93d", + "sha256:ba2a27ff02f48193fc4daeadf8ad2590516fa3d0adeeb34336b96f7fa64c1e3a", + "sha256:bc84e875994c3b445871ea7181d424588171efec3e185dced958dad9e001950a", + "sha256:bfd56bb4b37ed4f330b82402f6f435845a5f5648edf1ad497da51a8452d5d62d", + "sha256:c18ff11e86df2e28854939acde2d003f7984f721eba450b56a200ad90eeb0e6b", + "sha256:c3bcce8521d785d510b2aad26ae2c966092b7daa8f45dd8f44734a104dc0bc1a", + "sha256:c4143987a42a2397f2fc3b4d7e3a7d313fbe684f67ff443999e803dd75a76826", + "sha256:c69fd885df7d089548a42d5ec05be26050ebcd2283d89b3d30676eb32ff87dee", + "sha256:ced80795227d70549a411a4ab66e8ce307899fad2220ce5ab2f296e687eacde9", + "sha256:d66e421495fdb797610a08f43b05269e0a5ea7f5e652a89bfd5a7d3c1dee3648", + "sha256:d861ee9e76ace6cf36a6a89b959ec08e7bc2493ee39d07ffe5acb23ef46d27da", + "sha256:e9251e3be159d1020c4030bd2e5f84d6a43fe54b6c19c12f51cde9542a2817b2", + "sha256:f145bba11b878005c496e93e257c1e88f154d278d2638e6450d17e0f31e558d2", + "sha256:fe346b143ff9685e40192a4960938545c699054ba11d4f9029f94751e3f71d87" ], - "markers": "python_version >= '3.8'", - "version": "==0.4.0" + "markers": "python_version >= '3.8' and python_full_version not in '3.9.0, 3.9.1'", + "version": "==46.0.5" }, "distlib": { "hashes": [ - "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87", - "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403" + "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16", + "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d" ], - "version": "==0.3.9" + "version": "==0.4.0" + }, + "dnspython": { + "hashes": [ + "sha256:01d9bbc4a2d76bf0db7c1f729812ded6d912bd318d3b1cf81d30c0f845dbf3af", + "sha256:181d3c6996452cb1189c4046c61599b84a5a86e099562ffde77d26984ff26d0f" + ], + "markers": "python_version >= '3.10'", + "version": "==2.8.0" + }, + "docutils": { + "hashes": [ + "sha256:4db53b1fde9abecbb74d91230d32ab626d94f6badfc575d6db9194a49df29968", + "sha256:d0013f540772d1420576855455d050a2180186c91c15779301ac2ccb3eeb68de" + ], + "markers": "python_version >= '3.9'", + "version": "==0.22.4" + }, + "email-validator": { + "hashes": [ + "sha256:80f13f623413e6b197ae73bb10bf4eb0908faf509ad8362c5edeb0be7fd450b4", + "sha256:9fc05c37f2f6cf439ff414f8fc46d917929974a82244c20eb10231ba60c54426" + ], + "markers": "python_version >= '3.8'", + "version": "==2.3.0" }, "filelock": { "hashes": [ - "sha256:adbc88eabb99d2fec8c9c1b229b171f18afa655400173ddc653d5d01501fb9f2", - "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de" + "sha256:b64ece2b38f4ca29dd3e810287aa8c48182bbecd1ae6e9ae126c9b35f1382694", + "sha256:ca8afb0da15f229774c9ad1b455ed96e85a81373065fb10446672f64444ddf70" + ], + "markers": "python_version >= '3.10'", + "version": "==3.25.2" + }, + "id": { + "hashes": [ + "sha256:d0732d624fb46fd4e7bc4e5152f00214450953b9e772c182c1c22964def1a069", + "sha256:f5ec41ed2629a508f5d0988eda142e190c9c6da971100612c4de9ad9f9b237ca" ], "markers": "python_version >= '3.9'", - "version": "==3.18.0" + "version": "==1.6.1" }, - "isort": { + "idna": { "hashes": [ - "sha256:1cb5df28dfbc742e490c5e41bad6da41b805b0a8be7bc93cd0fb2a8a890ac450", - "sha256:2dc5d7f65c9678d94c88dfc29161a320eec67328bc97aad576874cb4be1e9615" - ], - "markers": "python_full_version >= '3.9.0'", - "version": "==6.0.1" - }, - "mccabe": { - "hashes": [ - "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325", - "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e" - ], - "markers": "python_version >= '3.6'", - "version": "==0.7.0" - }, - "mypy": { - "hashes": [ - "sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e", - "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22", - "sha256:1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f", - "sha256:1fbb8da62dc352133d7d7ca90ed2fb0e9d42bb1a32724c287d3c76c58cbaa9c2", - "sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f", - "sha256:2e2c2e6d3593f6451b18588848e66260ff62ccca522dd231cd4dd59b0160668b", - "sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5", - "sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f", - "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43", - "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e", - "sha256:5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c", - "sha256:6983aae8b2f653e098edb77f893f7b6aca69f6cffb19b2cc7443f23cce5f4828", - "sha256:712e962a6357634fef20412699a3655c610110e01cdaa6180acec7fc9f8513ba", - "sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee", - "sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d", - "sha256:8f8722560a14cde92fdb1e31597760dc35f9f5524cce17836c0d22841830fd5b", - "sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445", - "sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e", - "sha256:979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13", - "sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5", - "sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd", - "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf", - "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357", - "sha256:be68172e9fd9ad8fb876c6389f16d1c1b5f100ffa779f77b1fb2176fcc9ab95b", - "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036", - "sha256:c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559", - "sha256:c7be1e46525adfa0d97681432ee9fcd61a3964c2446795714699a998d193f1a3", - "sha256:c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f", - "sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464", - "sha256:d10d994b41fb3497719bbf866f227b3489048ea4bbbb5015357db306249f7980", - "sha256:e601a7fa172c2131bff456bb3ee08a88360760d0d2f8cbd7a75a65497e2df078", - "sha256:f95579473af29ab73a10bada2f9722856792a36ec5af5399b653aa28360290a5" - ], - "index": "pypi", - "markers": "python_version >= '3.9'", - "version": "==1.15.0" - }, - "mypy-extensions": { - "hashes": [ - "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", - "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558" + "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", + "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902" ], "markers": "python_version >= '3.8'", - "version": "==1.1.0" + "version": "==3.11" + }, + "jaraco.classes": { + "hashes": [ + "sha256:47a024b51d0239c0dd8c8540c6c7f484be3b8fcf0b2d85c13825780d3b3f3acd", + "sha256:f662826b6bed8cace05e7ff873ce0f9283b5c924470fe664fff1c2f00f581790" + ], + "markers": "python_version >= '3.8'", + "version": "==3.4.0" + }, + "jaraco.context": { + "hashes": [ + "sha256:bf8150b79a2d5d91ae48629d8b427a8f7ba0e1097dd6202a9059f29a36379535", + "sha256:f1a6c9d391e661cc5b8d39861ff077a7dc24dc23833ccee564b234b81c82dfe3" + ], + "markers": "python_version >= '3.10'", + "version": "==6.1.2" + }, + "jaraco.functools": { + "hashes": [ + "sha256:9eec1e36f45c818d9bf307c8948eb03b2b56cd44087b3cdc989abca1f20b9176", + "sha256:da21933b0417b89515562656547a77b4931f98176eb173644c0d35032a33d6bb" + ], + "markers": "python_version >= '3.9'", + "version": "==4.4.0" + }, + "jeepney": { + "hashes": [ + "sha256:97e5714520c16fc0a45695e5365a2e11b81ea79bba796e26f9f1d178cb182683", + "sha256:cf0e9e845622b81e4a28df94c40345400256ec608d0e55bb8a3feaa9163f5732" + ], + "markers": "python_version >= '3.7'", + "version": "==0.9.0" + }, + "keyring": { + "hashes": [ + "sha256:be4a0b195f149690c166e850609a477c532ddbfbaed96a404d4e43f8d5e2689f", + "sha256:fe01bd85eb3f8fb3dd0405defdeac9a5b4f6f0439edbb3149577f244a2e8245b" + ], + "markers": "python_version >= '3.9'", + "version": "==25.7.0" + }, + "markdown-it-py": { + "hashes": [ + "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147", + "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3" + ], + "markers": "python_version >= '3.10'", + "version": "==4.0.0" + }, + "mdurl": { + "hashes": [ + "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", + "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba" + ], + "markers": "python_version >= '3.7'", + "version": "==0.1.2" + }, + "more-itertools": { + "hashes": [ + "sha256:52d4362373dcf7c52546bc4af9a86ee7c4579df9a8dc268be0a2f949d376cc9b", + "sha256:f638ddf8a1a0d134181275fb5d58b086ead7c6a72429ad725c67503f13ba30bd" + ], + "markers": "python_version >= '3.9'", + "version": "==10.8.0" + }, + "nh3": { + "hashes": [ + "sha256:0d5eb734a78ac364af1797fef718340a373f626a9ff6b4fb0b4badf7927e7b81", + "sha256:185ed41b88c910b9ca8edc89ca3b4be688a12cb9de129d84befa2f74a0039fee", + "sha256:1ef87f8e916321a88b45f2d597f29bd56e560ed4568a50f0f1305afab86b7189", + "sha256:21a63ccb18ddad3f784bb775955839b8b80e347e597726f01e43ca1abcc5c808", + "sha256:21b058cd20d9f0919421a820a2843fdb5e1749c0bf57a6247ab8f4ba6723c9fc", + "sha256:24769a428e9e971e4ccfb24628f83aaa7dc3c8b41b130c8ddc1835fa1c924489", + "sha256:2efd17c0355d04d39e6d79122b42662277ac10a17ea48831d90b46e5ef7e4fc0", + "sha256:3a62b8ae7c235481715055222e54c682422d0495a5c73326807d4e44c5d14691", + "sha256:45fe0d6a607264910daec30360c8a3b5b1500fd832d21b2da608256287bcb92d", + "sha256:4c730617bdc15d7092dcc0469dc2826b914c8f874996d105b4bc3842a41c1cd9", + "sha256:52e973cb742e95b9ae1b35822ce23992428750f4b46b619fe86eba4205255b30", + "sha256:5a4b2c1f3e6f3cbe7048e17f4fefad3f8d3e14cc0fd08fb8599e0d5653f6b181", + "sha256:5bc1d4b30ba1ba896669d944b6003630592665974bd11a3dc2f661bde92798a7", + "sha256:90126a834c18af03bfd6ff9a027bfa6bbf0e238527bc780a24de6bd7cc1041e2", + "sha256:92a958e6f6d0100e025a5686aafd67e3c98eac67495728f8bb64fbeb3e474493", + "sha256:9ed40cf8449a59a03aa465114fedce1ff7ac52561688811d047917cc878b19ca", + "sha256:a446eae598987f49ee97ac2f18eafcce4e62e7574bd1eb23782e4702e54e217d", + "sha256:b50c3770299fb2a7c1113751501e8878d525d15160a4c05194d7fe62b758aad8", + "sha256:b7a18ee057761e455d58b9d31445c3e4b2594cff4ddb84d2e331c011ef46f462", + "sha256:b838e619f483531483d26d889438e53a880510e832d2aafe73f93b7b1ac2bce2", + "sha256:e8ee96156f7dfc6e30ecda650e480c5ae0a7d38f0c6fafc3c1c655e2500421d9", + "sha256:e974850b131fdffa75e7ad8e0d9c7a855b96227b093417fdf1bd61656e530f37", + "sha256:e98fa3dbfd54e25487e36ba500bc29bca3a4cab4ffba18cfb1a35a2d02624297", + "sha256:f433a2dd66545aad4a720ad1b2150edcdca75bfff6f4e6f378ade1ec138d5e77", + "sha256:f4400a73c2a62859e769f9d36d1b5a7a5c65c4179d1dddd2f6f3095b2db0cbfc", + "sha256:f508ddd4e2433fdcb78c790fc2d24e3a349ba775e5fa904af89891321d4844a3", + "sha256:fc305a2264868ec8fa16548296f803d8fd9c1fa66cd28b88b605b1bd06667c0b" + ], + "markers": "python_version >= '3.8'", + "version": "==0.3.3" }, "packaging": { "hashes": [ - "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", - "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f" + "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4", + "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529" ], "markers": "python_version >= '3.8'", - "version": "==25.0" + "version": "==26.0" }, "pipenv": { "hashes": [ - "sha256:85d42e13da78f27f0213c998dba9a59f3ba6a6fe9e420b75b561acc344f021ad", - "sha256:f26dc0352f3fb167c3897a66a5d8c9ab81dd52a836a48630712e1e5a06840ebf" + "sha256:cd2858095181578ec17451f3ff02b8f74eb9038013ddbbc54228c5f0611fa3da", + "sha256:ddba48a3f9a27e6330b391180ba078354d4d8de480bbe49e7432d6c8ead5bbd7" ], "index": "pypi", - "markers": "python_version >= '3.9'", - "version": "==2025.0.2" + "markers": "python_version >= '3.10'", + "version": "==2026.2.1" }, "platformdirs": { "hashes": [ - "sha256:a03875334331946f13c549dbd8f4bac7a13a50a895a0eb1e8c6a8ace80d40a94", - "sha256:eb437d586b6a0986388f0d6f74aa0cde27b48d0e3d66843640bfb6bdcdb6e351" + "sha256:1ec356301b7dc906d83f371c8f487070e99d3ccf9e501686456394622a01a934", + "sha256:68a9a4619a666ea6439f2ff250c12a853cd1cbd5158d258bd824a7df6be2f868" + ], + "markers": "python_version >= '3.10'", + "version": "==4.9.4" + }, + "pluggy": { + "hashes": [ + "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", + "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746" ], "markers": "python_version >= '3.9'", - "version": "==4.3.7" + "version": "==1.6.0" + }, + "pyasn1": { + "hashes": [ + "sha256:697a8ecd6d98891189184ca1fa05d1bb00e2f84b5977c481452050549c8a72cf", + "sha256:a80184d120f0864a52a073acc6fc642847d0be408e7c7252f31390c0f4eadcde" + ], + "markers": "python_version >= '3.8'", + "version": "==0.6.3" }, "pycodestyle": { "hashes": [ - "sha256:35863c5974a271c7a726ed228a14a4f6daf49df369d8c50cd9a6f58a5e143ba9", - "sha256:c8415bf09abe81d9c7f872502a6eee881fbe85d8763dd5b9924bb0a01d67efae" + "sha256:c4b5b517d278089ff9d0abdec919cd97262a3367449ea1c8b49b91529167b783", + "sha256:dd6bf7cb4ee77f8e016f9c8e74a35ddd9f67e1d5fd4184d86c3b98e07099f42d" ], "markers": "python_version >= '3.9'", - "version": "==2.13.0" + "version": "==2.14.0" }, - "pylint": { + "pycparser": { "hashes": [ - "sha256:8b7c2d3e86ae3f94fb27703d521dd0b9b6b378775991f504d7c3a6275aa0a6a6", - "sha256:b634a041aac33706d56a0d217e6587228c66427e20ec21a019bc4cdee48c040a" + "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", + "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992" + ], + "markers": "python_version >= '3.10'", + "version": "==3.0" + }, + "pydantic": { + "extras": [ + "email" + ], + "hashes": [ + "sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49", + "sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d" + ], + "markers": "python_version >= '3.9'", + "version": "==2.12.5" + }, + "pydantic-core": { + "hashes": [ + "sha256:0177272f88ab8312479336e1d777f6b124537d47f2123f89cb37e0accea97f90", + "sha256:01a3d0ab748ee531f4ea6c3e48ad9dac84ddba4b0d82291f87248f2f9de8d740", + "sha256:0384e2e1021894b1ff5a786dbf94771e2986ebe2869533874d7e43bc79c6f504", + "sha256:03b77d184b9eb40240ae9fd676ca364ce1085f203e1b1256f8ab9984dca80a84", + "sha256:03ca43e12fab6023fc79d28ca6b39b05f794ad08ec2feccc59a339b02f2b3d33", + "sha256:05a2c8852530ad2812cb7914dc61a1125dc4e06252ee98e5638a12da6cc6fb6c", + "sha256:070259a8818988b9a84a449a2a7337c7f430a22acc0859c6b110aa7212a6d9c0", + "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e", + "sha256:0cbaad15cb0c90aa221d43c00e77bb33c93e8d36e0bf74760cd00e732d10a6a0", + "sha256:100baa204bb412b74fe285fb0f3a385256dad1d1879f0a5cb1499ed2e83d132a", + "sha256:112e305c3314f40c93998e567879e887a3160bb8689ef3d2c04b6cc62c33ac34", + "sha256:16f80f7abe3351f8ea6858914ddc8c77e02578544a0ebc15b4c2e1a0e813b0b2", + "sha256:1746d4a3d9a794cacae06a5eaaccb4b8643a131d45fbc9af23e353dc0a5ba5c3", + "sha256:1962293292865bca8e54702b08a4f26da73adc83dd1fcf26fbc875b35d81c815", + "sha256:1d1d9764366c73f996edd17abb6d9d7649a7eb690006ab6adbda117717099b14", + "sha256:1f8d33a7f4d5a7889e60dc39856d76d09333d8a6ed0f5f1190635cbec70ec4ba", + "sha256:22f0fb8c1c583a3b6f24df2470833b40207e907b90c928cc8d3594b76f874375", + "sha256:239edca560d05757817c13dc17c50766136d21f7cd0fac50295499ae24f90fdf", + "sha256:242a206cd0318f95cd21bdacff3fcc3aab23e79bba5cac3db5a841c9ef9c6963", + "sha256:25e1c2af0fce638d5f1988b686f3b3ea8cd7de5f244ca147c777769e798a9cd1", + "sha256:266fb4cbf5e3cbd0b53669a6d1b039c45e3ce651fd5442eff4d07c2cc8d66808", + "sha256:2782c870e99878c634505236d81e5443092fba820f0373997ff75f90f68cd553", + "sha256:287dad91cfb551c363dc62899a80e9e14da1f0e2b6ebde82c806612ca2a13ef1", + "sha256:29452c56df2ed968d18d7e21f4ab0ac55e71dc59524872f6fc57dcf4a3249ed2", + "sha256:299e0a22e7ae2b85c1a57f104538b2656e8ab1873511fd718a1c1c6f149b77b5", + "sha256:2a5e06546e19f24c6a96a129142a75cee553cc018ffee48a460059b1185f4470", + "sha256:2b761d210c9ea91feda40d25b4efe82a1707da2ef62901466a42492c028553a2", + "sha256:2c010c6ded393148374c0f6f0bf89d206bf3217f201faa0635dcd56bd1520f6b", + "sha256:2ff4321e56e879ee8d2a879501c8e469414d948f4aba74a2d4593184eb326660", + "sha256:3006c3dd9ba34b0c094c544c6006cc79e87d8612999f1a5d43b769b89181f23c", + "sha256:33cb885e759a705b426baada1fe68cbb0a2e68e34c5d0d0289a364cf01709093", + "sha256:346285d28e4c8017da95144c7f3acd42740d637ff41946af5ce6e5e420502dd5", + "sha256:34a64bc3441dc1213096a20fe27e8e128bd3ff89921706e83c0b1ac971276594", + "sha256:35b44f37a3199f771c3eaa53051bc8a70cd7b54f333531c59e29fd4db5d15008", + "sha256:378bec5c66998815d224c9ca994f1e14c0c21cb95d2f52b6021cc0b2a58f2a5a", + "sha256:3f37a19d7ebcdd20b96485056ba9e8b304e27d9904d233d7b1015db320e51f0a", + "sha256:3f84d5c1b4ab906093bdc1ff10484838aca54ef08de4afa9de0f5f14d69639cd", + "sha256:4009935984bd36bd2c774e13f9a09563ce8de4abaa7226f5108262fa3e637284", + "sha256:406bf18d345822d6c21366031003612b9c77b3e29ffdb0f612367352aab7d586", + "sha256:4819fa52133c9aa3c387b3328f25c1facc356491e6135b459f1de698ff64d869", + "sha256:482c982f814460eabe1d3bb0adfdc583387bd4691ef00b90575ca0d2b6fe2294", + "sha256:4bc36bbc0b7584de96561184ad7f012478987882ebf9f9c389b23f432ea3d90f", + "sha256:506d766a8727beef16b7adaeb8ee6217c64fc813646b424d0804d67c16eddb66", + "sha256:56121965f7a4dc965bff783d70b907ddf3d57f6eba29b6d2e5dabfaf07799c51", + "sha256:58133647260ea01e4d0500089a8c4f07bd7aa6ce109682b1426394988d8aaacc", + "sha256:5921a4d3ca3aee735d9fd163808f5e8dd6c6972101e4adbda9a4667908849b97", + "sha256:5a4e67afbc95fa5c34cf27d9089bca7fcab4e51e57278d710320a70b956d1b9a", + "sha256:5cb1b2f9742240e4bb26b652a5aeb840aa4b417c7748b6f8387927bc6e45e40d", + "sha256:62de39db01b8d593e45871af2af9e497295db8d73b085f6bfd0b18c83c70a8f9", + "sha256:634e8609e89ceecea15e2d61bc9ac3718caaaa71963717bf3c8f38bfde64242c", + "sha256:63510af5e38f8955b8ee5687740d6ebf7c2a0886d15a6d65c32814613681bc07", + "sha256:650ae77860b45cfa6e2cdafc42618ceafab3a2d9a3811fcfbd3bbf8ac3c40d36", + "sha256:6561e94ba9dacc9c61bce40e2d6bdc3bfaa0259d3ff36ace3b1e6901936d2e3e", + "sha256:65840751b72fbfd82c3c640cff9284545342a4f1eb1586ad0636955b261b0b05", + "sha256:6cb58b9c66f7e4179a2d5e0f849c48eff5c1fca560994d6eb6543abf955a149e", + "sha256:6f52298fbd394f9ed112d56f3d11aabd0d5bd27beb3084cc3d8ad069483b8941", + "sha256:707625ef0983fcfb461acfaf14de2067c5942c6bb0f3b4c99158bed6fedd3cf3", + "sha256:72f6c8b11857a856bcfa48c86f5368439f74453563f951e473514579d44aa612", + "sha256:753e230374206729bf0a807954bcc6c150d3743928a73faffee51ac6557a03c3", + "sha256:76d0819de158cd855d1cbb8fcafdf6f5cf1eb8e470abe056d5d161106e38062b", + "sha256:76ee27c6e9c7f16f47db7a94157112a2f3a00e958bc626e2f4ee8bec5c328fbe", + "sha256:77b63866ca88d804225eaa4af3e664c5faf3568cea95360d21f4725ab6e07146", + "sha256:79ec52ec461e99e13791ec6508c722742ad745571f234ea6255bed38c6480f11", + "sha256:7b93a4d08587e2b7e7882de461e82b6ed76d9026ce91ca7915e740ecc7855f60", + "sha256:7da7087d756b19037bc2c06edc6c170eeef3c3bafcb8f532ff17d64dc427adfd", + "sha256:7f3bf998340c6d4b0c9a2f02d6a400e51f123b59565d74dc60d252ce888c260b", + "sha256:80aa89cad80b32a912a65332f64a4450ed00966111b6615ca6816153d3585a8c", + "sha256:8566def80554c3faa0e65ac30ab0932b9e3a5cd7f8323764303d468e5c37595a", + "sha256:873e0d5b4fb9b89ef7c2d2a963ea7d02879d9da0da8d9d4933dee8ee86a8b460", + "sha256:88942d3a3dff3afc8288c21e565e476fc278902ae4d6d134f1eeda118cc830b1", + "sha256:8bfeaf8735be79f225f3fefab7f941c712aaca36f1128c9d7e2352ee1aa87bdf", + "sha256:8e7c86f27c585ef37c35e56a96363ab8de4e549a95512445b85c96d3e2f7c1bf", + "sha256:915c3d10f81bec3a74fbd4faebe8391013ba61e5a1a8d48c4455b923bdda7858", + "sha256:93e8740d7503eb008aa2df04d3b9735f845d43ae845e6dcd2be0b55a2da43cd2", + "sha256:941103c9be18ac8daf7b7adca8228f8ed6bb7a1849020f643b3a14d15b1924d9", + "sha256:97aeba56665b4c3235a0e52b2c2f5ae9cd071b8a8310ad27bddb3f7fb30e9aa2", + "sha256:a39455728aabd58ceabb03c90e12f71fd30fa69615760a075b9fec596456ccc3", + "sha256:a3a52f6156e73e7ccb0f8cced536adccb7042be67cb45f9562e12b319c119da6", + "sha256:a668ce24de96165bb239160b3d854943128f4334822900534f2fe947930e5770", + "sha256:a75dafbf87d6276ddc5b2bf6fae5254e3d0876b626eb24969a574fff9149ee5d", + "sha256:aabf5777b5c8ca26f7824cb4a120a740c9588ed58df9b2d196ce92fba42ff8dc", + "sha256:aec5cf2fd867b4ff45b9959f8b20ea3993fc93e63c7363fe6851424c8a7e7c23", + "sha256:b2379fa7ed44ddecb5bfe4e48577d752db9fc10be00a6b7446e9663ba143de26", + "sha256:b4ececa40ac28afa90871c2cc2b9ffd2ff0bf749380fbdf57d165fd23da353aa", + "sha256:b5819cd790dbf0c5eb9f82c73c16b39a65dd6dd4d1439dcdea7816ec9adddab8", + "sha256:b74557b16e390ec12dca509bce9264c3bbd128f8a2c376eaa68003d7f327276d", + "sha256:b80aa5095cd3109962a298ce14110ae16b8c1aece8b72f9dafe81cf597ad80b3", + "sha256:b93590ae81f7010dbe380cdeab6f515902ebcbefe0b9327cc4804d74e93ae69d", + "sha256:b96d5f26b05d03cc60f11a7761a5ded1741da411e7fe0909e27a5e6a0cb7b034", + "sha256:bd3d54f38609ff308209bd43acea66061494157703364ae40c951f83ba99a1a9", + "sha256:bfea2a5f0b4d8d43adf9d7b8bf019fb46fdd10a2e5cde477fbcb9d1fa08c68e1", + "sha256:c007fe8a43d43b3969e8469004e9845944f1a80e6acd47c150856bb87f230c56", + "sha256:c1df3d34aced70add6f867a8cf413e299177e0c22660cc767218373d0779487b", + "sha256:c23e27686783f60290e36827f9c626e63154b82b116d7fe9adba1fda36da706c", + "sha256:c8d8b4eb992936023be7dee581270af5c6e0697a8559895f527f5b7105ecd36a", + "sha256:c9e19dd6e28fdcaa5a1de679aec4141f691023916427ef9bae8584f9c2fb3b0e", + "sha256:d0d2568a8c11bf8225044aa94409e21da0cb09dcdafe9ecd10250b2baad531a9", + "sha256:d38548150c39b74aeeb0ce8ee1d8e82696f4a4e16ddc6de7b1d8823f7de4b9b5", + "sha256:d3a978c4f57a597908b7e697229d996d77a6d3c94901e9edee593adada95ce1a", + "sha256:d5160812ea7a8a2ffbe233d8da666880cad0cbaf5d4de74ae15c313213d62556", + "sha256:dc799088c08fa04e43144b164feb0c13f9a0bc40503f8df3e9fde58a3c0c101e", + "sha256:df3959765b553b9440adfd3c795617c352154e497a4eaf3752555cfb5da8fc49", + "sha256:dfa8a0c812ac681395907e71e1274819dec685fec28273a28905df579ef137e2", + "sha256:e25c479382d26a2a41b7ebea1043564a937db462816ea07afa8a44c0866d52f9", + "sha256:e4f4a984405e91527a0d62649ee21138f8e3d0ef103be488c1dc11a80d7f184b", + "sha256:e536c98a7626a98feb2d3eaf75944ef6f3dbee447e1f841eae16f2f0a72d8ddc", + "sha256:e56ba91f47764cc14f1daacd723e3e82d1a89d783f0f5afe9c364b8bb491ccdb", + "sha256:e672ba74fbc2dc8eea59fb6d4aed6845e6905fc2a8afe93175d94a83ba2a01a0", + "sha256:e7b576130c69225432866fe2f4a469a85a54ade141d96fd396dffcf607b558f8", + "sha256:e8465ab91a4bd96d36dde3263f06caa6a8a6019e4113f24dc753d79a8b3a3f82", + "sha256:e96cea19e34778f8d59fe40775a7a574d95816eb150850a85a7a4c8f4b94ac69", + "sha256:ece5c59f0ce7d001e017643d8d24da587ea1f74f6993467d85ae8a5ef9d4f42b", + "sha256:eceb81a8d74f9267ef4081e246ffd6d129da5d87e37a77c9bde550cb04870c1c", + "sha256:ed2e99c456e3fadd05c991f8f437ef902e00eedf34320ba2b0842bd1c3ca3a75", + "sha256:f0cd744688278965817fd0839c4a4116add48d23890d468bc436f78beb28abf5", + "sha256:f14f8f046c14563f8eb3f45f499cc658ab8d10072961e07225e507adb700e93f", + "sha256:f15489ba13d61f670dcc96772e733aad1a6f9c429cc27574c6cdaed82d0146ad", + "sha256:f31d95a179f8d64d90f6831d71fa93290893a33148d890ba15de25642c5d075b", + "sha256:f41a7489d32336dbf2199c8c0a215390a751c5b014c2c1c5366e817202e9cdf7", + "sha256:f41eb9797986d6ebac5e8edff36d5cef9de40def462311b3eb3eeded1431e425", + "sha256:f547144f2966e1e16ae626d8ce72b4cfa0caedc7fa28052001c94fb2fcaa1c52" + ], + "markers": "python_version >= '3.9'", + "version": "==2.41.5" + }, + "pygments": { + "hashes": [ + "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", + "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b" + ], + "markers": "python_version >= '3.8'", + "version": "==2.19.2" + }, + "pyjwt": { + "hashes": [ + "sha256:28ca37c070cad8ba8cd9790cd940535d40274d22f80ab87f3ac6a713e6e8454c", + "sha256:c74a7a2adf861c04d002db713dd85f84beb242228e671280bf709d765b03672b" + ], + "markers": "python_version >= '3.9'", + "version": "==2.12.1" + }, + "pyopenssl": { + "hashes": [ + "sha256:df94d28498848b98cc1c0ffb8ef1e71e40210d3b0a8064c9d29571ed2904bf81", + "sha256:f293934e52936f2e3413b89c6ce36df66a0b34ae1ea3a053b8c5020ff2f513fc" + ], + "markers": "python_version >= '3.8'", + "version": "==26.0.0" + }, + "pypi-attestations": { + "hashes": [ + "sha256:278a28d741b57d62973c00d453ec9b9bb30456464d69296c6780474cd0bf098e", + "sha256:2daf3ec46ff4c7123184ec892852b4d4599b78128f01f742a44406a73200c5df" ], "index": "pypi", - "markers": "python_full_version >= '3.9.0'", - "version": "==3.3.6" + "markers": "python_version >= '3.10'", + "version": "==0.0.29" + }, + "pyproject-api": { + "hashes": [ + "sha256:40c6f2d82eebdc4afee61c773ed208c04c19db4c4a60d97f8d7be3ebc0bbb330", + "sha256:8757c41a79c0f4ab71b99abed52b97ecf66bd20b04fa59da43b5840bac105a09" + ], + "markers": "python_version >= '3.10'", + "version": "==1.10.0" }, "pyproject-hooks": { "hashes": [ @@ -199,13 +748,104 @@ "markers": "python_version >= '3.7'", "version": "==1.2.0" }, - "setuptools": { + "python-discovery": { "hashes": [ - "sha256:a65cffc4fb86167e3020b3ef58e08226baad8b29a3b34ce2c9d07e901bac481d", - "sha256:ec8308eb180b2312062b1c5523204acf872cd8b0a9e6c2ae76431b22bc4065d7" + "sha256:1e108f1bbe2ed0ef089823d28805d5ad32be8e734b86a5f212bf89b71c266e4a", + "sha256:7d33e350704818b09e3da2bd419d37e21e7c30db6e0977bb438916e06b41b5b1" + ], + "markers": "python_version >= '3.8'", + "version": "==1.2.0" + }, + "readme-renderer": { + "hashes": [ + "sha256:2fbca89b81a08526aadf1357a8c2ae889ec05fb03f5da67f9769c9a592166151", + "sha256:8712034eabbfa6805cacf1402b4eeb2a73028f72d1166d6f5cb7f9c047c5d1e1" ], "markers": "python_version >= '3.9'", - "version": "==80.3.0" + "version": "==44.0" + }, + "requests": { + "hashes": [ + "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", + "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf" + ], + "markers": "python_version >= '3.9'", + "version": "==2.32.5" + }, + "requests-toolbelt": { + "hashes": [ + "sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6", + "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.0.0" + }, + "rfc3161-client": { + "hashes": [ + "sha256:078e4bbf0770ddc472e2ca96cf1e23efd0c313e6682b4c2c9765e1fdf09f55a3", + "sha256:09c47582ecea2ca4a3debf8a1eda775cc3d5ae1379da40272cc065d32e639a7a", + "sha256:3106f3361a5a36789f43d2700e5678c847a9d3460a23f455f4c20cd39314c557", + "sha256:31b6ee79f15b93d90952efd0395bb3f5ebf07941469c5c6eb32f9b64312cda6e", + "sha256:61c04b4953453e5c26a1949c20adac415b65cd062dab0960574d6c36240222d2", + "sha256:8a54fdb2f9e64481272b89137a7b71403cf1d30f5505c2e0c15a47a1cc100264", + "sha256:8fb34470e867a29cc15dc4987ea14f19d3bd25c863e132b6f75dca583e2cc67e", + "sha256:9c53a6711bab0c3f77dc9cf1e2fd750da475ff7abbc40ffe0333d8c518a8a9c8", + "sha256:ae440461a310ae097417afe536d9d22fd71c95fbc9d21db3561b2707bed0aff0", + "sha256:d31d30e354d2349ae8483ce811ef61498a3780daf8622c0b79d8cd44d271b46b", + "sha256:d9ed8e597d0ee7387da1945e1583c4516b26f133770b3956e079606e2d90b69c", + "sha256:e904430e27e75a5a379fc4aac09bd60ba5f4b48054f0481b2fb417297e404047", + "sha256:f1a2e32e2a053455cee1ff9b325b88dbc7c66c8882dde60962add92f572df5c5" + ], + "markers": "python_version >= '3.9'", + "version": "==1.0.5" + }, + "rfc3986": { + "hashes": [ + "sha256:50b1502b60e289cb37883f3dfd34532b8873c7de9f49bb546641ce9cbd256ebd", + "sha256:97aacf9dbd4bfd829baad6e6309fa6573aaf1be3f6fa735c8ab05e46cecb261c" + ], + "markers": "python_version >= '3.7'", + "version": "==2.0.0" + }, + "rfc8785": { + "hashes": [ + "sha256:520d690b448ecf0703691c76e1a34a24ddcd4fc5bc41d589cb7c58ec651bcd48", + "sha256:e545841329fe0eee4f6a3b44e7034343100c12b4ec566dc06ca9735681deb4da" + ], + "markers": "python_version >= '3.8'", + "version": "==0.1.4" + }, + "rich": { + "hashes": [ + "sha256:793431c1f8619afa7d3b52b2cdec859562b950ea0d4b6b505397612db8d5362d", + "sha256:b8daa0b9e4eef54dd8cf7c86c03713f53241884e814f4e2f5fb342fe520f639b" + ], + "markers": "python_full_version >= '3.8.0'", + "version": "==14.3.3" + }, + "secretstorage": { + "hashes": [ + "sha256:0ce65888c0725fcb2c5bc0fdb8e5438eece02c523557ea40ce0703c266248137", + "sha256:f04b8e4689cbce351744d5537bf6b1329c6fc68f91fa666f60a380edddcd11be" + ], + "markers": "python_version >= '3.10'", + "version": "==3.5.0" + }, + "securesystemslib": { + "hashes": [ + "sha256:2e5414bbdde33155a91805b295cbedc4ae3f12b48dccc63e1089093537f43c81", + "sha256:ca915f4b88209bb5450ac05426b859d74b7cd1421cafcf73b8dd3418a0b17486" + ], + "markers": "python_version ~= '3.8'", + "version": "==1.3.1" + }, + "setuptools": { + "hashes": [ + "sha256:7d872682c5d01cfde07da7bccc7b65469d3dca203318515ada1de5eda35efbf9", + "sha256:a59e362652f08dcd477c78bb6e7bd9d80a7995bc73ce773050228a348ce2e5bb" + ], + "markers": "python_version >= '3.9'", + "version": "==82.0.1" }, "setuptools-scm": { "hashes": [ @@ -216,29 +856,95 @@ "markers": "python_version >= '3.8'", "version": "==8.2.0" }, - "tomlkit": { + "sigstore": { "hashes": [ - "sha256:7a974427f6e119197f670fbbbeae7bef749a6c14e793db934baefc1b5f03efde", - "sha256:fff5fe59a87295b278abd31bec92c15d9bc4a06885ab12bcea52c71119392e79" + "sha256:bdbb49a42fd5f0ea6765919adb42ccee7254c482330764d0842eec4e11ad78d7", + "sha256:ed2e0f50aae85148a8aa4fc0f57c298927fce430ad1f988f38611ce90c85829f" + ], + "markers": "python_version >= '3.10'", + "version": "==4.2.0" + }, + "sigstore-models": { + "hashes": [ + "sha256:5201a68f4d7d0f8bec1e2f4378eb646b084c52609a4e31db8c385095fff68b2e", + "sha256:c766c09470c2a7e8a4a333c893f07e2001c56a3ff1757b1a246119f53169a849" + ], + "markers": "python_version >= '3.10'", + "version": "==0.0.6" + }, + "sigstore-rekor-types": { + "hashes": [ + "sha256:19aef25433218ebf9975a1e8b523cc84aaf3cd395ad39a30523b083ea7917ec5", + "sha256:b62bf38c5b1a62bc0d7fe0ee51a0709e49311d137c7880c329882a8f4b2d1d78" ], "markers": "python_version >= '3.8'", - "version": "==0.13.2" + "version": "==0.0.18" + }, + "tomli-w": { + "hashes": [ + "sha256:188306098d013b691fcadc011abd66727d3c414c571bb01b1a174ba8c983cf90", + "sha256:2dd14fac5a47c27be9cd4c976af5a12d87fb1f0b4512f81d69cce3b35ae25021" + ], + "markers": "python_version >= '3.9'", + "version": "==1.2.0" + }, + "tox": { + "hashes": [ + "sha256:5e788a512bfe6f7447e0c8d7c1b666eb2e56e5e676c65717490423bec37d1a07", + "sha256:c745641de6cc4f19d066bd9f98c1c25f7affb005b381b7f3694a1f142ea0946b" + ], + "index": "pypi", + "markers": "python_version >= '3.10'", + "version": "==4.50.3" + }, + "tuf": { + "hashes": [ + "sha256:458f663a233d95cc76dde0e1a3d01796516a05ce2781fefafebe037f7729601a", + "sha256:9eed0f7888c5fff45dc62164ff243a05d47fb8a3208035eb268974287e0aee8d" + ], + "markers": "python_version >= '3.8'", + "version": "==6.0.0" + }, + "twine": { + "hashes": [ + "sha256:418ebf08ccda9a8caaebe414433b0ba5e25eb5e4a927667122fbe8f829f985d8", + "sha256:e5ed0d2fd70c9959770dce51c8f39c8945c574e18173a7b81802dab51b4b75cf" + ], + "index": "pypi", + "markers": "python_version >= '3.9'", + "version": "==6.2.0" }, "typing-extensions": { "hashes": [ - "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c", - "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef" + "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", + "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548" ], - "markers": "python_version >= '3.8'", - "version": "==4.13.2" + "markers": "python_version >= '3.9'", + "version": "==4.15.0" + }, + "typing-inspection": { + "hashes": [ + "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", + "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464" + ], + "markers": "python_version >= '3.9'", + "version": "==0.4.2" + }, + "urllib3": { + "hashes": [ + "sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed", + "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4" + ], + "markers": "python_version >= '3.9'", + "version": "==2.6.3" }, "virtualenv": { "hashes": [ - "sha256:800863162bcaa5450a6e4d721049730e7f2dae07720e0902b0e4040bd6f9ada8", - "sha256:e34302959180fca3af42d1800df014b35019490b119eba981af27f2fa486e5d6" + "sha256:1720dc3a62ef5b443092e3f499228599045d7fea4c79199770499df8becf9098", + "sha256:1bd755b504931164a5a496d217c014d098426cddc79363ad66ac78125f9d908f" ], "markers": "python_version >= '3.8'", - "version": "==20.30.0" + "version": "==21.2.0" } } } diff --git a/TODO b/TODO index dd4cd66..e747197 100644 --- a/TODO +++ b/TODO @@ -30,7 +30,7 @@ preserve Git diffing. ID: [ISSUE-NUMBER] Type: [feature/bugfix/hotfix] Title: [Short title] -Status: [open/in-progress/done] +Status: [open/in-progress/done/hold/cancelled] Priority: [low/medium/high] Created: [YYYY-MM-DD] Description: [Detailed explanation] @@ -50,7 +50,7 @@ Description: [Detailed explanation] ID: 1 Type: feature Title: implement KMP algorithm for string searching -Status: in-progress +Status: hold Priority: high Created: 2025-05-03 Description: Implement the Knuth-Morris-Pratt algorithm for string searching. @@ -79,3 +79,165 @@ Description: move the unit test suites to a unit/ subdirectory so that integration tests and benchmarks can be cleanly separated --- + +ID: 4 +Type: feature +Title: implement Rabin-Karp rolling hash algorithm +Status: done +Priority: high +Created: 2025-05-05 +Description: After testing a couple of string search algorithms, I've ditched + the idea of using KMP as my use-case gives no advantage compared to + naive searching. In addition I've came upon the challenge that many + string search algorithms are optimized for search on a linear + buffer, which in my case is not applicable as the implementation + the search algorithm is for uses a circular buffer. Rabin-Karp + seemed promising. I've come up with a different approach though, + which is still based on rolling hashes, therefore, as a base, I + need an implementation of the original Rabin-Karp rolling hash + algorithm + +--- + +ID: 5 +Type: feature +Title: implement chunked rolling hash algorithm +Status: in-progress +Priority: high +Created: 2025-05-05 +Description: Implement my custom algorithm for doing rolling hash string search + against a fixed length ring buffer + +--- + +ID: 6 +Type: feature +Title: implement importlib.resources handler for urllib +Status: done +Priority: high +Created: 2025-06-20 +Description: A handler that can be registered with an urllib.request + OpenerDirector to open importlib.resources package files. + +--- + +ID: 7 +Type: feature +Title: setup advanced testing environment +Status: done +Priority: high +Created: 2025-06-20 +Description: copy the testing environment setup from + byteb4rb1e.sphinxcontrib.ext + +--- + +ID: 8 +Type: bugfix +Title: rename package +Status: done +Priority: high +Created: 2025-06-20 +Description: use dot namespaces to make the package a little more elegant + +--- + +ID: 9 +Type: bugfix +Title: fix LICENSE reference +Status: done +Priority: high +Created: 2025-06-20 +Description: license specification is no longer a trove classifier in + pyproject.toml, hence the reference to LICENSE must be changed + +--- + +ID: 10 +Type: feature +Title: pytest current test context fixtures +Status: done +Priority: high +Created: 2025-06-20 +Description: add fixtures for doing things in relation to the active testing + context + +--- + +ID: 11 +Type: bugfix +Title: move testing utils out of utils +Status: done +Priority: high +Created: 2025-06-20 +Description: to shorten the namespace and also indicate that testing utilities + are different from regular utilities + +--- + +ID: 12 +Type: feature +Title: simplify testing.fixtures.mock_pkg +Status: done +Priority: high +Created: 2025-06-21 +Description: Only bootstrap a package mock with the minimum requirements for a + Python module and let the consumer handle the directory layout. + +--- + +ID: 13 +Type: bugfix +Title: fix unit tests for urllib PkgHandler +Status: done +Priority: high +Created: 2025-06-21 +Description: change of issue 12 wasn't properly reflected in urllib PkgHandler + unit tests + +--- + +ID: 14 +Type: feature +Title: add compression support for urllib PkgHandler +Status: done +Priority: high +Created: 2025-06-21 +Description: with a proper content-type of the PkgHandler addinfourl object, a + consumer can determine whether the file is compressed or not. + +--- + +ID: 15 +Type: bugfix +Title: modularize module containers +Status: open +Priority: high +Created: 2025-06-28 +Description: Even though importlib can find submodules through traversing paths + instead of relying on __init__.py for every ancestor module, this + is not supported by some modules like sphinx.ext.autosummary + +--- + +ID: 16 +Type: feature +Title: SQL-aware dataclass +Status: in-progress +Priority: low +Created: 2025-12-31 +Description: A dataclass that transparently maps onto an SQL datastore, with + command generation for syncing data between data class and store + +--- + +ID: 17 +Type: feature +Title: recursive-descent HTML (DOM) parser +Status: in-progress +Priority: high +Created: 2025-12-31 +Description: Extend the built-in event-driven parser to be modeled after DOM + recursive-descent HTML parser + +--- diff --git a/configure b/configure deleted file mode 100644 index ade147c..0000000 --- a/configure +++ /dev/null @@ -1,2663 +0,0 @@ -#! /bin/sh -# Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.72. -# -# -# Copyright (C) 1992-1996, 1998-2017, 2020-2023 Free Software Foundation, -# Inc. -# -# -# This configure script is free software; the Free Software Foundation -# gives unlimited permission to copy, distribute and modify it. -## -------------------- ## -## M4sh Initialization. ## -## -------------------- ## - -# Be more Bourne compatible -DUALCASE=1; export DUALCASE # for MKS sh -if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 -then : - emulate sh - NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else case e in #( - e) case `(set -o) 2>/dev/null` in #( - *posix*) : - set -o posix ;; #( - *) : - ;; -esac ;; -esac -fi - - - -# Reset variables that may have inherited troublesome values from -# the environment. - -# IFS needs to be set, to space, tab, and newline, in precisely that order. -# (If _AS_PATH_WALK were called with IFS unset, it would have the -# side effect of setting IFS to empty, thus disabling word splitting.) -# Quoting is to prevent editors from complaining about space-tab. -as_nl=' -' -export as_nl -IFS=" "" $as_nl" - -PS1='$ ' -PS2='> ' -PS4='+ ' - -# Ensure predictable behavior from utilities with locale-dependent output. -LC_ALL=C -export LC_ALL -LANGUAGE=C -export LANGUAGE - -# We cannot yet rely on "unset" to work, but we need these variables -# to be unset--not just set to an empty or harmless value--now, to -# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct -# also avoids known problems related to "unset" and subshell syntax -# in other old shells (e.g. bash 2.01 and pdksh 5.2.14). -for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH -do eval test \${$as_var+y} \ - && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : -done - -# Ensure that fds 0, 1, and 2 are open. -if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi -if (exec 3>&2) ; then :; else exec 2>/dev/null; fi - -# The user is always right. -if ${PATH_SEPARATOR+false} :; then - PATH_SEPARATOR=: - (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { - (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || - PATH_SEPARATOR=';' - } -fi - - -# Find who we are. Look in the path if we contain no directory separator. -as_myself= -case $0 in #(( - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac - test -r "$as_dir$0" && as_myself=$as_dir$0 && break - done -IFS=$as_save_IFS - - ;; -esac -# We did not find ourselves, most probably we were run as 'sh COMMAND' -# in which case we are not to be found in the path. -if test "x$as_myself" = x; then - as_myself=$0 -fi -if test ! -f "$as_myself"; then - printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 - exit 1 -fi - - -# Use a proper internal environment variable to ensure we don't fall - # into an infinite loop, continuously re-executing ourselves. - if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then - _as_can_reexec=no; export _as_can_reexec; - # We cannot yet assume a decent shell, so we have to provide a -# neutralization value for shells without unset; and this also -# works around shells that cannot unset nonexistent variables. -# Preserve -v and -x to the replacement shell. -BASH_ENV=/dev/null -ENV=/dev/null -(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV -case $- in # (((( - *v*x* | *x*v* ) as_opts=-vx ;; - *v* ) as_opts=-v ;; - *x* ) as_opts=-x ;; - * ) as_opts= ;; -esac -exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} -# Admittedly, this is quite paranoid, since all the known shells bail -# out after a failed 'exec'. -printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 -exit 255 - fi - # We don't want this to propagate to other subprocesses. - { _as_can_reexec=; unset _as_can_reexec;} -if test "x$CONFIG_SHELL" = x; then - as_bourne_compatible="if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 -then : - emulate sh - NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which - # is contrary to our usage. Disable this feature. - alias -g '\${1+\"\$@\"}'='\"\$@\"' - setopt NO_GLOB_SUBST -else case e in #( - e) case \`(set -o) 2>/dev/null\` in #( - *posix*) : - set -o posix ;; #( - *) : - ;; -esac ;; -esac -fi -" - as_required="as_fn_return () { (exit \$1); } -as_fn_success () { as_fn_return 0; } -as_fn_failure () { as_fn_return 1; } -as_fn_ret_success () { return 0; } -as_fn_ret_failure () { return 1; } - -exitcode=0 -as_fn_success || { exitcode=1; echo as_fn_success failed.; } -as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } -as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } -as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } -if ( set x; as_fn_ret_success y && test x = \"\$1\" ) -then : - -else case e in #( - e) exitcode=1; echo positional parameters were not saved. ;; -esac -fi -test x\$exitcode = x0 || exit 1 -blah=\$(echo \$(echo blah)) -test x\"\$blah\" = xblah || exit 1 -test -x / || exit 1" - as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO - as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO - eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && - test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1" - if (eval "$as_required") 2>/dev/null -then : - as_have_required=yes -else case e in #( - e) as_have_required=no ;; -esac -fi - if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null -then : - -else case e in #( - e) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -as_found=false -for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH -do - IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac - as_found=: - case $as_dir in #( - /*) - for as_base in sh bash ksh sh5; do - # Try only shells that exist, to save several forks. - as_shell=$as_dir$as_base - if { test -f "$as_shell" || test -f "$as_shell.exe"; } && - as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null -then : - CONFIG_SHELL=$as_shell as_have_required=yes - if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null -then : - break 2 -fi -fi - done;; - esac - as_found=false -done -IFS=$as_save_IFS -if $as_found -then : - -else case e in #( - e) if { test -f "$SHELL" || test -f "$SHELL.exe"; } && - as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null -then : - CONFIG_SHELL=$SHELL as_have_required=yes -fi ;; -esac -fi - - - if test "x$CONFIG_SHELL" != x -then : - export CONFIG_SHELL - # We cannot yet assume a decent shell, so we have to provide a -# neutralization value for shells without unset; and this also -# works around shells that cannot unset nonexistent variables. -# Preserve -v and -x to the replacement shell. -BASH_ENV=/dev/null -ENV=/dev/null -(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV -case $- in # (((( - *v*x* | *x*v* ) as_opts=-vx ;; - *v* ) as_opts=-v ;; - *x* ) as_opts=-x ;; - * ) as_opts= ;; -esac -exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} -# Admittedly, this is quite paranoid, since all the known shells bail -# out after a failed 'exec'. -printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 -exit 255 -fi - - if test x$as_have_required = xno -then : - printf "%s\n" "$0: This script requires a shell more modern than all" - printf "%s\n" "$0: the shells that I found on your system." - if test ${ZSH_VERSION+y} ; then - printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should" - printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later." - else - printf "%s\n" "$0: Please tell bug-autoconf@gnu.org about your system, -$0: including any error possibly output before this -$0: message. Then install a modern shell, or manually run -$0: the script under such a shell if you do have one." - fi - exit 1 -fi ;; -esac -fi -fi -SHELL=${CONFIG_SHELL-/bin/sh} -export SHELL -# Unset more variables known to interfere with behavior of common tools. -CLICOLOR_FORCE= GREP_OPTIONS= -unset CLICOLOR_FORCE GREP_OPTIONS - -## --------------------- ## -## M4sh Shell Functions. ## -## --------------------- ## -# as_fn_unset VAR -# --------------- -# Portably unset VAR. -as_fn_unset () -{ - { eval $1=; unset $1;} -} -as_unset=as_fn_unset - - -# as_fn_set_status STATUS -# ----------------------- -# Set $? to STATUS, without forking. -as_fn_set_status () -{ - return $1 -} # as_fn_set_status - -# as_fn_exit STATUS -# ----------------- -# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. -as_fn_exit () -{ - set +e - as_fn_set_status $1 - exit $1 -} # as_fn_exit - -# as_fn_mkdir_p -# ------------- -# Create "$as_dir" as a directory, including parents if necessary. -as_fn_mkdir_p () -{ - - case $as_dir in #( - -*) as_dir=./$as_dir;; - esac - test -d "$as_dir" || eval $as_mkdir_p || { - as_dirs= - while :; do - case $as_dir in #( - *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( - *) as_qdir=$as_dir;; - esac - as_dirs="'$as_qdir' $as_dirs" - as_dir=`$as_dirname -- "$as_dir" || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || -printf "%s\n" X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - test -d "$as_dir" && break - done - test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" - - -} # as_fn_mkdir_p - -# as_fn_executable_p FILE -# ----------------------- -# Test if FILE is an executable regular file. -as_fn_executable_p () -{ - test -f "$1" && test -x "$1" -} # as_fn_executable_p -# as_fn_append VAR VALUE -# ---------------------- -# Append the text in VALUE to the end of the definition contained in VAR. Take -# advantage of any shell optimizations that allow amortized linear growth over -# repeated appends, instead of the typical quadratic growth present in naive -# implementations. -if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null -then : - eval 'as_fn_append () - { - eval $1+=\$2 - }' -else case e in #( - e) as_fn_append () - { - eval $1=\$$1\$2 - } ;; -esac -fi # as_fn_append - -# as_fn_arith ARG... -# ------------------ -# Perform arithmetic evaluation on the ARGs, and store the result in the -# global $as_val. Take advantage of shells that can avoid forks. The arguments -# must be portable across $(()) and expr. -if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null -then : - eval 'as_fn_arith () - { - as_val=$(( $* )) - }' -else case e in #( - e) as_fn_arith () - { - as_val=`expr "$@" || test $? -eq 1` - } ;; -esac -fi # as_fn_arith - - -# as_fn_error STATUS ERROR [LINENO LOG_FD] -# ---------------------------------------- -# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are -# provided, also output the error to LOG_FD, referencing LINENO. Then exit the -# script with STATUS, using 1 if that was 0. -as_fn_error () -{ - as_status=$1; test $as_status -eq 0 && as_status=1 - if test "$4"; then - as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 - fi - printf "%s\n" "$as_me: error: $2" >&2 - as_fn_exit $as_status -} # as_fn_error - -if expr a : '\(a\)' >/dev/null 2>&1 && - test "X`expr 00001 : '.*\(...\)'`" = X001; then - as_expr=expr -else - as_expr=false -fi - -if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then - as_basename=basename -else - as_basename=false -fi - -if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then - as_dirname=dirname -else - as_dirname=false -fi - -as_me=`$as_basename -- "$0" || -$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| . 2>/dev/null || -printf "%s\n" X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ - s//\1/ - q - } - /^X\/\(\/\/\)$/{ - s//\1/ - q - } - /^X\/\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - - - as_lineno_1=$LINENO as_lineno_1a=$LINENO - as_lineno_2=$LINENO as_lineno_2a=$LINENO - eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && - test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { - # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) - sed -n ' - p - /[$]LINENO/= - ' <$as_myself | - sed ' - t clear - :clear - s/[$]LINENO.*/&-/ - t lineno - b - :lineno - N - :loop - s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ - t loop - s/-\n.*// - ' >$as_me.lineno && - chmod +x "$as_me.lineno" || - { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } - - # If we had to re-execute with $CONFIG_SHELL, we're ensured to have - # already done that, so ensure we don't try to do so again and fall - # in an infinite loop. This has already happened in practice. - _as_can_reexec=no; export _as_can_reexec - # Don't try to exec as it changes $[0], causing all sort of problems - # (the dirname of $[0] is not the place where we might find the - # original and so on. Autoconf is especially sensitive to this). - . "./$as_me.lineno" - # Exit status is that of the last command. - exit -} - - -# Determine whether it's possible to make 'echo' print without a newline. -# These variables are no longer used directly by Autoconf, but are AC_SUBSTed -# for compatibility with existing Makefiles. -ECHO_C= ECHO_N= ECHO_T= -case `echo -n x` in #((((( --n*) - case `echo 'xy\c'` in - *c*) ECHO_T=' ';; # ECHO_T is single tab character. - xy) ECHO_C='\c';; - *) echo `echo ksh88 bug on AIX 6.1` > /dev/null - ECHO_T=' ';; - esac;; -*) - ECHO_N='-n';; -esac - -# For backward compatibility with old third-party macros, we provide -# the shell variables $as_echo and $as_echo_n. New code should use -# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. -as_echo='printf %s\n' -as_echo_n='printf %s' - -rm -f conf$$ conf$$.exe conf$$.file -if test -d conf$$.dir; then - rm -f conf$$.dir/conf$$.file -else - rm -f conf$$.dir - mkdir conf$$.dir 2>/dev/null -fi -if (echo >conf$$.file) 2>/dev/null; then - if ln -s conf$$.file conf$$ 2>/dev/null; then - as_ln_s='ln -s' - # ... but there are two gotchas: - # 1) On MSYS, both 'ln -s file dir' and 'ln file dir' fail. - # 2) DJGPP < 2.04 has no symlinks; 'ln -s' creates a wrapper executable. - # In both cases, we have to default to 'cp -pR'. - ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -pR' - elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln - else - as_ln_s='cp -pR' - fi -else - as_ln_s='cp -pR' -fi -rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file -rmdir conf$$.dir 2>/dev/null - -if mkdir -p . 2>/dev/null; then - as_mkdir_p='mkdir -p "$as_dir"' -else - test -d ./-p && rmdir ./-p - as_mkdir_p=false -fi - -as_test_x='test -x' -as_executable_p=as_fn_executable_p - -# Sed expression to map a string onto a valid CPP name. -as_sed_cpp="y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" -as_tr_cpp="eval sed '$as_sed_cpp'" # deprecated - -# Sed expression to map a string onto a valid variable name. -as_sed_sh="y%*+%pp%;s%[^_$as_cr_alnum]%_%g" -as_tr_sh="eval sed '$as_sed_sh'" # deprecated - - -test -n "$DJDIR" || exec 7<&0 &1 - -# Name of the host. -# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, -# so uname gets run too. -ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` - -# -# Initializations. -# -ac_default_prefix=/usr/local -ac_clean_files= -ac_config_libobj_dir=. -LIBOBJS= -cross_compiling=no -subdirs= -MFLAGS= -MAKEFLAGS= - -# Identity of this package. -PACKAGE_NAME='' -PACKAGE_TARNAME='' -PACKAGE_VERSION='' -PACKAGE_STRING='' -PACKAGE_BUGREPORT='' -PACKAGE_URL='' - -ac_subst_vars='LTLIBOBJS -LIBOBJS -REALPATH -PYTHON3 -GIT -MAKE -target_alias -host_alias -build_alias -LIBS -ECHO_T -ECHO_N -ECHO_C -DEFS -mandir -localedir -libdir -psdir -pdfdir -dvidir -htmldir -infodir -docdir -oldincludedir -includedir -runstatedir -localstatedir -sharedstatedir -sysconfdir -datadir -datarootdir -libexecdir -sbindir -bindir -program_transform_name -prefix -exec_prefix -PACKAGE_URL -PACKAGE_BUGREPORT -PACKAGE_STRING -PACKAGE_VERSION -PACKAGE_TARNAME -PACKAGE_NAME -PATH_SEPARATOR -SHELL' -ac_subst_files='' -ac_user_opts=' -enable_option_checking -' - ac_precious_vars='build_alias -host_alias -target_alias' - - -# Initialize some variables set by options. -ac_init_help= -ac_init_version=false -ac_unrecognized_opts= -ac_unrecognized_sep= -# The variables have the same names as the options, with -# dashes changed to underlines. -cache_file=/dev/null -exec_prefix=NONE -no_create= -no_recursion= -prefix=NONE -program_prefix=NONE -program_suffix=NONE -program_transform_name=s,x,x, -silent= -site= -srcdir= -verbose= -x_includes=NONE -x_libraries=NONE - -# Installation directory options. -# These are left unexpanded so users can "make install exec_prefix=/foo" -# and all the variables that are supposed to be based on exec_prefix -# by default will actually change. -# Use braces instead of parens because sh, perl, etc. also accept them. -# (The list follows the same order as the GNU Coding Standards.) -bindir='${exec_prefix}/bin' -sbindir='${exec_prefix}/sbin' -libexecdir='${exec_prefix}/libexec' -datarootdir='${prefix}/share' -datadir='${datarootdir}' -sysconfdir='${prefix}/etc' -sharedstatedir='${prefix}/com' -localstatedir='${prefix}/var' -runstatedir='${localstatedir}/run' -includedir='${prefix}/include' -oldincludedir='/usr/include' -docdir='${datarootdir}/doc/${PACKAGE}' -infodir='${datarootdir}/info' -htmldir='${docdir}' -dvidir='${docdir}' -pdfdir='${docdir}' -psdir='${docdir}' -libdir='${exec_prefix}/lib' -localedir='${datarootdir}/locale' -mandir='${datarootdir}/man' - -ac_prev= -ac_dashdash= -for ac_option -do - # If the previous option needs an argument, assign it. - if test -n "$ac_prev"; then - eval $ac_prev=\$ac_option - ac_prev= - continue - fi - - case $ac_option in - *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; - *=) ac_optarg= ;; - *) ac_optarg=yes ;; - esac - - case $ac_dashdash$ac_option in - --) - ac_dashdash=yes ;; - - -bindir | --bindir | --bindi | --bind | --bin | --bi) - ac_prev=bindir ;; - -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) - bindir=$ac_optarg ;; - - -build | --build | --buil | --bui | --bu) - ac_prev=build_alias ;; - -build=* | --build=* | --buil=* | --bui=* | --bu=*) - build_alias=$ac_optarg ;; - - -cache-file | --cache-file | --cache-fil | --cache-fi \ - | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) - ac_prev=cache_file ;; - -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ - | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) - cache_file=$ac_optarg ;; - - --config-cache | -C) - cache_file=config.cache ;; - - -datadir | --datadir | --datadi | --datad) - ac_prev=datadir ;; - -datadir=* | --datadir=* | --datadi=* | --datad=*) - datadir=$ac_optarg ;; - - -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ - | --dataroo | --dataro | --datar) - ac_prev=datarootdir ;; - -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ - | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) - datarootdir=$ac_optarg ;; - - -disable-* | --disable-*) - ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid feature name: '$ac_useropt'" - ac_useropt_orig=$ac_useropt - ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"enable_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval enable_$ac_useropt=no ;; - - -docdir | --docdir | --docdi | --doc | --do) - ac_prev=docdir ;; - -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) - docdir=$ac_optarg ;; - - -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) - ac_prev=dvidir ;; - -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) - dvidir=$ac_optarg ;; - - -enable-* | --enable-*) - ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid feature name: '$ac_useropt'" - ac_useropt_orig=$ac_useropt - ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"enable_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval enable_$ac_useropt=\$ac_optarg ;; - - -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ - | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ - | --exec | --exe | --ex) - ac_prev=exec_prefix ;; - -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ - | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ - | --exec=* | --exe=* | --ex=*) - exec_prefix=$ac_optarg ;; - - -gas | --gas | --ga | --g) - # Obsolete; use --with-gas. - with_gas=yes ;; - - -help | --help | --hel | --he | -h) - ac_init_help=long ;; - -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) - ac_init_help=recursive ;; - -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) - ac_init_help=short ;; - - -host | --host | --hos | --ho) - ac_prev=host_alias ;; - -host=* | --host=* | --hos=* | --ho=*) - host_alias=$ac_optarg ;; - - -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) - ac_prev=htmldir ;; - -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ - | --ht=*) - htmldir=$ac_optarg ;; - - -includedir | --includedir | --includedi | --included | --include \ - | --includ | --inclu | --incl | --inc) - ac_prev=includedir ;; - -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ - | --includ=* | --inclu=* | --incl=* | --inc=*) - includedir=$ac_optarg ;; - - -infodir | --infodir | --infodi | --infod | --info | --inf) - ac_prev=infodir ;; - -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) - infodir=$ac_optarg ;; - - -libdir | --libdir | --libdi | --libd) - ac_prev=libdir ;; - -libdir=* | --libdir=* | --libdi=* | --libd=*) - libdir=$ac_optarg ;; - - -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ - | --libexe | --libex | --libe) - ac_prev=libexecdir ;; - -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ - | --libexe=* | --libex=* | --libe=*) - libexecdir=$ac_optarg ;; - - -localedir | --localedir | --localedi | --localed | --locale) - ac_prev=localedir ;; - -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) - localedir=$ac_optarg ;; - - -localstatedir | --localstatedir | --localstatedi | --localstated \ - | --localstate | --localstat | --localsta | --localst | --locals) - ac_prev=localstatedir ;; - -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ - | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) - localstatedir=$ac_optarg ;; - - -mandir | --mandir | --mandi | --mand | --man | --ma | --m) - ac_prev=mandir ;; - -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) - mandir=$ac_optarg ;; - - -nfp | --nfp | --nf) - # Obsolete; use --without-fp. - with_fp=no ;; - - -no-create | --no-create | --no-creat | --no-crea | --no-cre \ - | --no-cr | --no-c | -n) - no_create=yes ;; - - -no-recursion | --no-recursion | --no-recursio | --no-recursi \ - | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) - no_recursion=yes ;; - - -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ - | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ - | --oldin | --oldi | --old | --ol | --o) - ac_prev=oldincludedir ;; - -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ - | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ - | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) - oldincludedir=$ac_optarg ;; - - -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) - ac_prev=prefix ;; - -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) - prefix=$ac_optarg ;; - - -program-prefix | --program-prefix | --program-prefi | --program-pref \ - | --program-pre | --program-pr | --program-p) - ac_prev=program_prefix ;; - -program-prefix=* | --program-prefix=* | --program-prefi=* \ - | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) - program_prefix=$ac_optarg ;; - - -program-suffix | --program-suffix | --program-suffi | --program-suff \ - | --program-suf | --program-su | --program-s) - ac_prev=program_suffix ;; - -program-suffix=* | --program-suffix=* | --program-suffi=* \ - | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) - program_suffix=$ac_optarg ;; - - -program-transform-name | --program-transform-name \ - | --program-transform-nam | --program-transform-na \ - | --program-transform-n | --program-transform- \ - | --program-transform | --program-transfor \ - | --program-transfo | --program-transf \ - | --program-trans | --program-tran \ - | --progr-tra | --program-tr | --program-t) - ac_prev=program_transform_name ;; - -program-transform-name=* | --program-transform-name=* \ - | --program-transform-nam=* | --program-transform-na=* \ - | --program-transform-n=* | --program-transform-=* \ - | --program-transform=* | --program-transfor=* \ - | --program-transfo=* | --program-transf=* \ - | --program-trans=* | --program-tran=* \ - | --progr-tra=* | --program-tr=* | --program-t=*) - program_transform_name=$ac_optarg ;; - - -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) - ac_prev=pdfdir ;; - -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) - pdfdir=$ac_optarg ;; - - -psdir | --psdir | --psdi | --psd | --ps) - ac_prev=psdir ;; - -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) - psdir=$ac_optarg ;; - - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil) - silent=yes ;; - - -runstatedir | --runstatedir | --runstatedi | --runstated \ - | --runstate | --runstat | --runsta | --runst | --runs \ - | --run | --ru | --r) - ac_prev=runstatedir ;; - -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ - | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ - | --run=* | --ru=* | --r=*) - runstatedir=$ac_optarg ;; - - -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) - ac_prev=sbindir ;; - -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ - | --sbi=* | --sb=*) - sbindir=$ac_optarg ;; - - -sharedstatedir | --sharedstatedir | --sharedstatedi \ - | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ - | --sharedst | --shareds | --shared | --share | --shar \ - | --sha | --sh) - ac_prev=sharedstatedir ;; - -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ - | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ - | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ - | --sha=* | --sh=*) - sharedstatedir=$ac_optarg ;; - - -site | --site | --sit) - ac_prev=site ;; - -site=* | --site=* | --sit=*) - site=$ac_optarg ;; - - -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) - ac_prev=srcdir ;; - -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) - srcdir=$ac_optarg ;; - - -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ - | --syscon | --sysco | --sysc | --sys | --sy) - ac_prev=sysconfdir ;; - -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ - | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) - sysconfdir=$ac_optarg ;; - - -target | --target | --targe | --targ | --tar | --ta | --t) - ac_prev=target_alias ;; - -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) - target_alias=$ac_optarg ;; - - -v | -verbose | --verbose | --verbos | --verbo | --verb) - verbose=yes ;; - - -version | --version | --versio | --versi | --vers | -V) - ac_init_version=: ;; - - -with-* | --with-*) - ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid package name: '$ac_useropt'" - ac_useropt_orig=$ac_useropt - ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"with_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval with_$ac_useropt=\$ac_optarg ;; - - -without-* | --without-*) - ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid package name: '$ac_useropt'" - ac_useropt_orig=$ac_useropt - ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"with_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval with_$ac_useropt=no ;; - - --x) - # Obsolete; use --with-x. - with_x=yes ;; - - -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ - | --x-incl | --x-inc | --x-in | --x-i) - ac_prev=x_includes ;; - -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ - | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) - x_includes=$ac_optarg ;; - - -x-libraries | --x-libraries | --x-librarie | --x-librari \ - | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) - ac_prev=x_libraries ;; - -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ - | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) - x_libraries=$ac_optarg ;; - - -*) as_fn_error $? "unrecognized option: '$ac_option' -Try '$0 --help' for more information" - ;; - - *=*) - ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` - # Reject names that are not valid shell variable names. - case $ac_envvar in #( - '' | [0-9]* | *[!_$as_cr_alnum]* ) - as_fn_error $? "invalid variable name: '$ac_envvar'" ;; - esac - eval $ac_envvar=\$ac_optarg - export $ac_envvar ;; - - *) - # FIXME: should be removed in autoconf 3.0. - printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2 - expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && - printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2 - : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" - ;; - - esac -done - -if test -n "$ac_prev"; then - ac_option=--`echo $ac_prev | sed 's/_/-/g'` - as_fn_error $? "missing argument to $ac_option" -fi - -if test -n "$ac_unrecognized_opts"; then - case $enable_option_checking in - no) ;; - fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; - *) printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; - esac -fi - -# Check all directory arguments for consistency. -for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ - datadir sysconfdir sharedstatedir localstatedir includedir \ - oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir runstatedir -do - eval ac_val=\$$ac_var - # Remove trailing slashes. - case $ac_val in - */ ) - ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` - eval $ac_var=\$ac_val;; - esac - # Be sure to have absolute directory names. - case $ac_val in - [\\/$]* | ?:[\\/]* ) continue;; - NONE | '' ) case $ac_var in *prefix ) continue;; esac;; - esac - as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" -done - -# There might be people who depend on the old broken behavior: '$host' -# used to hold the argument of --host etc. -# FIXME: To remove some day. -build=$build_alias -host=$host_alias -target=$target_alias - -# FIXME: To remove some day. -if test "x$host_alias" != x; then - if test "x$build_alias" = x; then - cross_compiling=maybe - elif test "x$build_alias" != "x$host_alias"; then - cross_compiling=yes - fi -fi - -ac_tool_prefix= -test -n "$host_alias" && ac_tool_prefix=$host_alias- - -test "$silent" = yes && exec 6>/dev/null - - -ac_pwd=`pwd` && test -n "$ac_pwd" && -ac_ls_di=`ls -di .` && -ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || - as_fn_error $? "working directory cannot be determined" -test "X$ac_ls_di" = "X$ac_pwd_ls_di" || - as_fn_error $? "pwd does not report name of working directory" - - -# Find the source files, if location was not specified. -if test -z "$srcdir"; then - ac_srcdir_defaulted=yes - # Try the directory containing this script, then the parent directory. - ac_confdir=`$as_dirname -- "$as_myself" || -$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_myself" : 'X\(//\)[^/]' \| \ - X"$as_myself" : 'X\(//\)$' \| \ - X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || -printf "%s\n" X"$as_myself" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - srcdir=$ac_confdir - if test ! -r "$srcdir/$ac_unique_file"; then - srcdir=.. - fi -else - ac_srcdir_defaulted=no -fi -if test ! -r "$srcdir/$ac_unique_file"; then - test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." - as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" -fi -ac_msg="sources are in $srcdir, but 'cd $srcdir' does not work" -ac_abs_confdir=`( - cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" - pwd)` -# When building in place, set srcdir=. -if test "$ac_abs_confdir" = "$ac_pwd"; then - srcdir=. -fi -# Remove unnecessary trailing slashes from srcdir. -# Double slashes in file names in object file debugging info -# mess up M-x gdb in Emacs. -case $srcdir in -*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; -esac -for ac_var in $ac_precious_vars; do - eval ac_env_${ac_var}_set=\${${ac_var}+set} - eval ac_env_${ac_var}_value=\$${ac_var} - eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} - eval ac_cv_env_${ac_var}_value=\$${ac_var} -done - -# -# Report the --help message. -# -if test "$ac_init_help" = "long"; then - # Omit some internal or obsolete options to make the list less imposing. - # This message is too long to be a string in the A/UX 3.1 sh. - cat <<_ACEOF -'configure' configures this package to adapt to many kinds of systems. - -Usage: $0 [OPTION]... [VAR=VALUE]... - -To assign environment variables (e.g., CC, CFLAGS...), specify them as -VAR=VALUE. See below for descriptions of some of the useful variables. - -Defaults for the options are specified in brackets. - -Configuration: - -h, --help display this help and exit - --help=short display options specific to this package - --help=recursive display the short help of all the included packages - -V, --version display version information and exit - -q, --quiet, --silent do not print 'checking ...' messages - --cache-file=FILE cache test results in FILE [disabled] - -C, --config-cache alias for '--cache-file=config.cache' - -n, --no-create do not create output files - --srcdir=DIR find the sources in DIR [configure dir or '..'] - -Installation directories: - --prefix=PREFIX install architecture-independent files in PREFIX - [$ac_default_prefix] - --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX - [PREFIX] - -By default, 'make install' will install all the files in -'$ac_default_prefix/bin', '$ac_default_prefix/lib' etc. You can specify -an installation prefix other than '$ac_default_prefix' using '--prefix', -for instance '--prefix=\$HOME'. - -For better control, use the options below. - -Fine tuning of the installation directories: - --bindir=DIR user executables [EPREFIX/bin] - --sbindir=DIR system admin executables [EPREFIX/sbin] - --libexecdir=DIR program executables [EPREFIX/libexec] - --sysconfdir=DIR read-only single-machine data [PREFIX/etc] - --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] - --localstatedir=DIR modifiable single-machine data [PREFIX/var] - --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] - --libdir=DIR object code libraries [EPREFIX/lib] - --includedir=DIR C header files [PREFIX/include] - --oldincludedir=DIR C header files for non-gcc [/usr/include] - --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] - --datadir=DIR read-only architecture-independent data [DATAROOTDIR] - --infodir=DIR info documentation [DATAROOTDIR/info] - --localedir=DIR locale-dependent data [DATAROOTDIR/locale] - --mandir=DIR man documentation [DATAROOTDIR/man] - --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] - --htmldir=DIR html documentation [DOCDIR] - --dvidir=DIR dvi documentation [DOCDIR] - --pdfdir=DIR pdf documentation [DOCDIR] - --psdir=DIR ps documentation [DOCDIR] -_ACEOF - - cat <<\_ACEOF -_ACEOF -fi - -if test -n "$ac_init_help"; then - - cat <<\_ACEOF - -Report bugs to the package provider. -_ACEOF -ac_status=$? -fi - -if test "$ac_init_help" = "recursive"; then - # If there are subdirs, report their specific --help. - for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue - test -d "$ac_dir" || - { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || - continue - ac_builddir=. - -case "$ac_dir" in -.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; -*) - ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` - # A ".." for each directory in $ac_dir_suffix. - ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` - case $ac_top_builddir_sub in - "") ac_top_builddir_sub=. ac_top_build_prefix= ;; - *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; - esac ;; -esac -ac_abs_top_builddir=$ac_pwd -ac_abs_builddir=$ac_pwd$ac_dir_suffix -# for backward compatibility: -ac_top_builddir=$ac_top_build_prefix - -case $srcdir in - .) # We are building in place. - ac_srcdir=. - ac_top_srcdir=$ac_top_builddir_sub - ac_abs_top_srcdir=$ac_pwd ;; - [\\/]* | ?:[\\/]* ) # Absolute name. - ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir - ac_abs_top_srcdir=$srcdir ;; - *) # Relative name. - ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_build_prefix$srcdir - ac_abs_top_srcdir=$ac_pwd/$srcdir ;; -esac -ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix - - cd "$ac_dir" || { ac_status=$?; continue; } - # Check for configure.gnu first; this name is used for a wrapper for - # Metaconfig's "Configure" on case-insensitive file systems. - if test -f "$ac_srcdir/configure.gnu"; then - echo && - $SHELL "$ac_srcdir/configure.gnu" --help=recursive - elif test -f "$ac_srcdir/configure"; then - echo && - $SHELL "$ac_srcdir/configure" --help=recursive - else - printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2 - fi || ac_status=$? - cd "$ac_pwd" || { ac_status=$?; break; } - done -fi - -test -n "$ac_init_help" && exit $ac_status -if $ac_init_version; then - cat <<\_ACEOF -configure -generated by GNU Autoconf 2.72 - -Copyright (C) 2023 Free Software Foundation, Inc. -This configure script is free software; the Free Software Foundation -gives unlimited permission to copy, distribute and modify it. -_ACEOF - exit -fi - -## ------------------------ ## -## Autoconf initialization. ## -## ------------------------ ## -ac_configure_args_raw= -for ac_arg -do - case $ac_arg in - *\'*) - ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; - esac - as_fn_append ac_configure_args_raw " '$ac_arg'" -done - -case $ac_configure_args_raw in - *$as_nl*) - ac_safe_unquote= ;; - *) - ac_unsafe_z='|&;<>()$`\\"*?[ '' ' # This string ends in space, tab. - ac_unsafe_a="$ac_unsafe_z#~" - ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g" - ac_configure_args_raw=` printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;; -esac - -cat >config.log <<_ACEOF -This file contains any messages produced by compilers while -running configure, to aid debugging if configure makes a mistake. - -It was created by $as_me, which was -generated by GNU Autoconf 2.72. Invocation command line was - - $ $0$ac_configure_args_raw - -_ACEOF -exec 5>>config.log -{ -cat <<_ASUNAME -## --------- ## -## Platform. ## -## --------- ## - -hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` - -/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` -/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` -/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` -/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` - -_ASUNAME - -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac - printf "%s\n" "PATH: $as_dir" - done -IFS=$as_save_IFS - -} >&5 - -cat >&5 <<_ACEOF - - -## ----------- ## -## Core tests. ## -## ----------- ## - -_ACEOF - - -# Keep a trace of the command line. -# Strip out --no-create and --no-recursion so they do not pile up. -# Strip out --silent because we don't want to record it for future runs. -# Also quote any args containing shell meta-characters. -# Make two passes to allow for proper duplicate-argument suppression. -ac_configure_args= -ac_configure_args0= -ac_configure_args1= -ac_must_keep_next=false -for ac_pass in 1 2 -do - for ac_arg - do - case $ac_arg in - -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil) - continue ;; - *\'*) - ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; - esac - case $ac_pass in - 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; - 2) - as_fn_append ac_configure_args1 " '$ac_arg'" - if test $ac_must_keep_next = true; then - ac_must_keep_next=false # Got value, back to normal. - else - case $ac_arg in - *=* | --config-cache | -C | -disable-* | --disable-* \ - | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ - | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ - | -with-* | --with-* | -without-* | --without-* | --x) - case "$ac_configure_args0 " in - "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; - esac - ;; - -* ) ac_must_keep_next=true ;; - esac - fi - as_fn_append ac_configure_args " '$ac_arg'" - ;; - esac - done -done -{ ac_configure_args0=; unset ac_configure_args0;} -{ ac_configure_args1=; unset ac_configure_args1;} - -# When interrupted or exit'd, cleanup temporary files, and complete -# config.log. We remove comments because anyway the quotes in there -# would cause problems or look ugly. -# WARNING: Use '\'' to represent an apostrophe within the trap. -# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. -trap 'exit_status=$? - # Sanitize IFS. - IFS=" "" $as_nl" - # Save into config.log some information that might help in debugging. - { - echo - - printf "%s\n" "## ---------------- ## -## Cache variables. ## -## ---------------- ##" - echo - # The following way of writing the cache mishandles newlines in values, -( - for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do - eval ac_val=\$$ac_var - case $ac_val in #( - *${as_nl}*) - case $ac_var in #( - *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 -printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; - esac - case $ac_var in #( - _ | IFS | as_nl) ;; #( - BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( - *) { eval $ac_var=; unset $ac_var;} ;; - esac ;; - esac - done - (set) 2>&1 | - case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( - *${as_nl}ac_space=\ *) - sed -n \ - "s/'\''/'\''\\\\'\'''\''/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" - ;; #( - *) - sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" - ;; - esac | - sort -) - echo - - printf "%s\n" "## ----------------- ## -## Output variables. ## -## ----------------- ##" - echo - for ac_var in $ac_subst_vars - do - eval ac_val=\$$ac_var - case $ac_val in - *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; - esac - printf "%s\n" "$ac_var='\''$ac_val'\''" - done | sort - echo - - if test -n "$ac_subst_files"; then - printf "%s\n" "## ------------------- ## -## File substitutions. ## -## ------------------- ##" - echo - for ac_var in $ac_subst_files - do - eval ac_val=\$$ac_var - case $ac_val in - *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; - esac - printf "%s\n" "$ac_var='\''$ac_val'\''" - done | sort - echo - fi - - if test -s confdefs.h; then - printf "%s\n" "## ----------- ## -## confdefs.h. ## -## ----------- ##" - echo - cat confdefs.h - echo - fi - test "$ac_signal" != 0 && - printf "%s\n" "$as_me: caught signal $ac_signal" - printf "%s\n" "$as_me: exit $exit_status" - } >&5 - rm -f core *.core core.conftest.* && - rm -f -r conftest* confdefs* conf$$* $ac_clean_files && - exit $exit_status -' 0 -for ac_signal in 1 2 13 15; do - trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal -done -ac_signal=0 - -# confdefs.h avoids OS command line length limits that DEFS can exceed. -rm -f -r conftest* confdefs.h - -printf "%s\n" "/* confdefs.h */" > confdefs.h - -# Predefined preprocessor variables. - -printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h - -printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h - -printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h - -printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h - -printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h - -printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h - - -# Let the site file select an alternate cache file if it wants to. -# Prefer an explicitly selected file to automatically selected ones. -if test -n "$CONFIG_SITE"; then - ac_site_files="$CONFIG_SITE" -elif test "x$prefix" != xNONE; then - ac_site_files="$prefix/share/config.site $prefix/etc/config.site" -else - ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" -fi - -for ac_site_file in $ac_site_files -do - case $ac_site_file in #( - */*) : - ;; #( - *) : - ac_site_file=./$ac_site_file ;; -esac - if test -f "$ac_site_file" && test -r "$ac_site_file"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 -printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;} - sed 's/^/| /' "$ac_site_file" >&5 - . "$ac_site_file" \ - || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 -printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} -as_fn_error $? "failed to load site script $ac_site_file -See 'config.log' for more details" "$LINENO" 5; } - fi -done - -if test -r "$cache_file"; then - # Some versions of bash will fail to source /dev/null (special files - # actually), so we avoid doing that. DJGPP emulates it as a regular file. - if test /dev/null != "$cache_file" && test -f "$cache_file"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 -printf "%s\n" "$as_me: loading cache $cache_file" >&6;} - case $cache_file in - [\\/]* | ?:[\\/]* ) . "$cache_file";; - *) . "./$cache_file";; - esac - fi -else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 -printf "%s\n" "$as_me: creating cache $cache_file" >&6;} - >$cache_file -fi - -# Check that the precious variables saved in the cache have kept the same -# value. -ac_cache_corrupted=false -for ac_var in $ac_precious_vars; do - eval ac_old_set=\$ac_cv_env_${ac_var}_set - eval ac_new_set=\$ac_env_${ac_var}_set - eval ac_old_val=\$ac_cv_env_${ac_var}_value - eval ac_new_val=\$ac_env_${ac_var}_value - case $ac_old_set,$ac_new_set in - set,) - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: '$ac_var' was set to '$ac_old_val' in the previous run" >&5 -printf "%s\n" "$as_me: error: '$ac_var' was set to '$ac_old_val' in the previous run" >&2;} - ac_cache_corrupted=: ;; - ,set) - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: '$ac_var' was not set in the previous run" >&5 -printf "%s\n" "$as_me: error: '$ac_var' was not set in the previous run" >&2;} - ac_cache_corrupted=: ;; - ,);; - *) - if test "x$ac_old_val" != "x$ac_new_val"; then - # differences in whitespace do not lead to failure. - ac_old_val_w=`echo x $ac_old_val` - ac_new_val_w=`echo x $ac_new_val` - if test "$ac_old_val_w" != "$ac_new_val_w"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: '$ac_var' has changed since the previous run:" >&5 -printf "%s\n" "$as_me: error: '$ac_var' has changed since the previous run:" >&2;} - ac_cache_corrupted=: - else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in '$ac_var' since the previous run:" >&5 -printf "%s\n" "$as_me: warning: ignoring whitespace changes in '$ac_var' since the previous run:" >&2;} - eval $ac_var=\$ac_old_val - fi - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: former value: '$ac_old_val'" >&5 -printf "%s\n" "$as_me: former value: '$ac_old_val'" >&2;} - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: current value: '$ac_new_val'" >&5 -printf "%s\n" "$as_me: current value: '$ac_new_val'" >&2;} - fi;; - esac - # Pass precious variables to config.status. - if test "$ac_new_set" = set; then - case $ac_new_val in - *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; - *) ac_arg=$ac_var=$ac_new_val ;; - esac - case " $ac_configure_args " in - *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. - *) as_fn_append ac_configure_args " '$ac_arg'" ;; - esac - fi -done -if $ac_cache_corrupted; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 -printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 -printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;} - as_fn_error $? "run '${MAKE-make} distclean' and/or 'rm $cache_file' - and start over" "$LINENO" 5 -fi -## -------------------- ## -## Main body of script. ## -## -------------------- ## - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - - -for ac_prog in make -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_prog_MAKE+y} -then : - printf %s "(cached) " >&6 -else case e in #( - e) if test -n "$MAKE"; then - ac_cv_prog_MAKE="$MAKE" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then - ac_cv_prog_MAKE="$ac_prog" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi ;; -esac -fi -MAKE=$ac_cv_prog_MAKE -if test -n "$MAKE"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MAKE" >&5 -printf "%s\n" "$MAKE" >&6; } -else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } -fi - - - test -n "$MAKE" && break -done -test -n "$MAKE" || MAKE="no" - -if test "$MAKE" == "no" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: without GNU Make, you have to inspect 'Makefile' and deduce build targets yourself." >&5 -printf "%s\n" "$as_me: without GNU Make, you have to inspect 'Makefile' and deduce build targets yourself." >&6;} -fi - -for ac_prog in git -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_prog_GIT+y} -then : - printf %s "(cached) " >&6 -else case e in #( - e) if test -n "$GIT"; then - ac_cv_prog_GIT="$GIT" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then - ac_cv_prog_GIT="$ac_prog" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi ;; -esac -fi -GIT=$ac_cv_prog_GIT -if test -n "$GIT"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $GIT" >&5 -printf "%s\n" "$GIT" >&6; } -else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } -fi - - - test -n "$GIT" && break -done -test -n "$GIT" || GIT="no" - -if test "$GIT" == "no" -then : - as_fn_error $? "install Git, before continuing." "$LINENO" 5 -fi - -for ac_prog in python3 -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_prog_PYTHON3+y} -then : - printf %s "(cached) " >&6 -else case e in #( - e) if test -n "$PYTHON3"; then - ac_cv_prog_PYTHON3="$PYTHON3" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then - ac_cv_prog_PYTHON3="$ac_prog" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi ;; -esac -fi -PYTHON3=$ac_cv_prog_PYTHON3 -if test -n "$PYTHON3"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PYTHON3" >&5 -printf "%s\n" "$PYTHON3" >&6; } -else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } -fi - - - test -n "$PYTHON3" && break -done -test -n "$PYTHON3" || PYTHON3="no" - -if test "$PYTHON3" == "no" -then : - as_fn_error $? "install Python 3, before continuing." "$LINENO" 5 -fi - -# required in Makefile to ensure proper path resolution during preprocessing -# realpath is not available on macOS -for ac_prog in realpath -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_prog_REALPATH+y} -then : - printf %s "(cached) " >&6 -else case e in #( - e) if test -n "$REALPATH"; then - ac_cv_prog_REALPATH="$REALPATH" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then - ac_cv_prog_REALPATH="$ac_prog" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi ;; -esac -fi -REALPATH=$ac_cv_prog_REALPATH -if test -n "$REALPATH"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $REALPATH" >&5 -printf "%s\n" "$REALPATH" >&6; } -else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } -fi - - - test -n "$REALPATH" && break -done -test -n "$REALPATH" || REALPATH="no" - -if test "$REALPATH" == "no" -then : - as_fn_error $? "set a persistent alias for 'realpath', before continuing, e.g. - -alias='python3 -c \"import pathlib,sys;print(pathlib.Path(sys.argv[1]).resolve())\"'\" -" "$LINENO" 5 -fi - -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: initializing python3 venv..." >&5 -printf "%s\n" "$as_me: initializing python3 venv..." >&6;} -make .venv - -cat >confcache <<\_ACEOF -# This file is a shell script that caches the results of configure -# tests run on this system so they can be shared between configure -# scripts and configure runs, see configure's option --config-cache. -# It is not useful on other systems. If it contains results you don't -# want to keep, you may remove or edit it. -# -# config.status only pays attention to the cache file if you give it -# the --recheck option to rerun configure. -# -# 'ac_cv_env_foo' variables (set or unset) will be overridden when -# loading this file, other *unset* 'ac_cv_foo' will be assigned the -# following values. - -_ACEOF - -# The following way of writing the cache mishandles newlines in values, -# but we know of no workaround that is simple, portable, and efficient. -# So, we kill variables containing newlines. -# Ultrix sh set writes to stderr and can't be redirected directly, -# and sets the high bit in the cache file unless we assign to the vars. -( - for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do - eval ac_val=\$$ac_var - case $ac_val in #( - *${as_nl}*) - case $ac_var in #( - *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 -printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; - esac - case $ac_var in #( - _ | IFS | as_nl) ;; #( - BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( - *) { eval $ac_var=; unset $ac_var;} ;; - esac ;; - esac - done - - (set) 2>&1 | - case $as_nl`(ac_space=' '; set) 2>&1` in #( - *${as_nl}ac_space=\ *) - # 'set' does not quote correctly, so add quotes: double-quote - # substitution turns \\\\ into \\, and sed turns \\ into \. - sed -n \ - "s/'/'\\\\''/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" - ;; #( - *) - # 'set' quotes correctly as required by POSIX, so do not add quotes. - sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" - ;; - esac | - sort -) | - sed ' - /^ac_cv_env_/b end - t clear - :clear - s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/ - t end - s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ - :end' >>confcache -if diff "$cache_file" confcache >/dev/null 2>&1; then :; else - if test -w "$cache_file"; then - if test "x$cache_file" != "x/dev/null"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 -printf "%s\n" "$as_me: updating cache $cache_file" >&6;} - if test ! -f "$cache_file" || test -h "$cache_file"; then - cat confcache >"$cache_file" - else - case $cache_file in #( - */* | ?:*) - mv -f confcache "$cache_file"$$ && - mv -f "$cache_file"$$ "$cache_file" ;; #( - *) - mv -f confcache "$cache_file" ;; - esac - fi - fi - else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 -printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;} - fi -fi -rm -f confcache - -test "x$prefix" = xNONE && prefix=$ac_default_prefix -# Let make expand exec_prefix. -test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' - -# Transform confdefs.h into DEFS. -# Protect against shell expansion while executing Makefile rules. -# Protect against Makefile macro expansion. -# -# If the first sed substitution is executed (which looks for macros that -# take arguments), then branch to the quote section. Otherwise, -# look for a macro that doesn't take arguments. -ac_script=' -:mline -/\\$/{ - N - s,\\\n,, - b mline -} -t clear -:clear -s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g -t quote -s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g -t quote -b any -:quote -s/[][ `~#$^&*(){}\\|;'\''"<>?]/\\&/g -s/\$/$$/g -H -:any -${ - g - s/^\n// - s/\n/ /g - p -} -' -DEFS=`sed -n "$ac_script" confdefs.h` - - -ac_libobjs= -ac_ltlibobjs= -U= -for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue - # 1. Remove the extension, and $U if already installed. - ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' - ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"` - # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR - # will be set to the directory where LIBOBJS objects are built. - as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" - as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' -done -LIBOBJS=$ac_libobjs - -LTLIBOBJS=$ac_ltlibobjs - - - -: "${CONFIG_STATUS=./config.status}" -ac_write_fail=0 -ac_clean_files_save=$ac_clean_files -ac_clean_files="$ac_clean_files $CONFIG_STATUS" -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 -printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;} -as_write_fail=0 -cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 -#! $SHELL -# Generated by $as_me. -# Run this file to recreate the current configuration. -# Compiler output produced by configure, useful for debugging -# configure, is in config.log if it exists. - -debug=false -ac_cs_recheck=false -ac_cs_silent=false - -SHELL=\${CONFIG_SHELL-$SHELL} -export SHELL -_ASEOF -cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 -## -------------------- ## -## M4sh Initialization. ## -## -------------------- ## - -# Be more Bourne compatible -DUALCASE=1; export DUALCASE # for MKS sh -if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 -then : - emulate sh - NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else case e in #( - e) case `(set -o) 2>/dev/null` in #( - *posix*) : - set -o posix ;; #( - *) : - ;; -esac ;; -esac -fi - - - -# Reset variables that may have inherited troublesome values from -# the environment. - -# IFS needs to be set, to space, tab, and newline, in precisely that order. -# (If _AS_PATH_WALK were called with IFS unset, it would have the -# side effect of setting IFS to empty, thus disabling word splitting.) -# Quoting is to prevent editors from complaining about space-tab. -as_nl=' -' -export as_nl -IFS=" "" $as_nl" - -PS1='$ ' -PS2='> ' -PS4='+ ' - -# Ensure predictable behavior from utilities with locale-dependent output. -LC_ALL=C -export LC_ALL -LANGUAGE=C -export LANGUAGE - -# We cannot yet rely on "unset" to work, but we need these variables -# to be unset--not just set to an empty or harmless value--now, to -# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct -# also avoids known problems related to "unset" and subshell syntax -# in other old shells (e.g. bash 2.01 and pdksh 5.2.14). -for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH -do eval test \${$as_var+y} \ - && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : -done - -# Ensure that fds 0, 1, and 2 are open. -if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi -if (exec 3>&2) ; then :; else exec 2>/dev/null; fi - -# The user is always right. -if ${PATH_SEPARATOR+false} :; then - PATH_SEPARATOR=: - (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { - (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || - PATH_SEPARATOR=';' - } -fi - - -# Find who we are. Look in the path if we contain no directory separator. -as_myself= -case $0 in #(( - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac - test -r "$as_dir$0" && as_myself=$as_dir$0 && break - done -IFS=$as_save_IFS - - ;; -esac -# We did not find ourselves, most probably we were run as 'sh COMMAND' -# in which case we are not to be found in the path. -if test "x$as_myself" = x; then - as_myself=$0 -fi -if test ! -f "$as_myself"; then - printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 - exit 1 -fi - - - -# as_fn_error STATUS ERROR [LINENO LOG_FD] -# ---------------------------------------- -# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are -# provided, also output the error to LOG_FD, referencing LINENO. Then exit the -# script with STATUS, using 1 if that was 0. -as_fn_error () -{ - as_status=$1; test $as_status -eq 0 && as_status=1 - if test "$4"; then - as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 - fi - printf "%s\n" "$as_me: error: $2" >&2 - as_fn_exit $as_status -} # as_fn_error - - -# as_fn_set_status STATUS -# ----------------------- -# Set $? to STATUS, without forking. -as_fn_set_status () -{ - return $1 -} # as_fn_set_status - -# as_fn_exit STATUS -# ----------------- -# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. -as_fn_exit () -{ - set +e - as_fn_set_status $1 - exit $1 -} # as_fn_exit - -# as_fn_unset VAR -# --------------- -# Portably unset VAR. -as_fn_unset () -{ - { eval $1=; unset $1;} -} -as_unset=as_fn_unset - -# as_fn_append VAR VALUE -# ---------------------- -# Append the text in VALUE to the end of the definition contained in VAR. Take -# advantage of any shell optimizations that allow amortized linear growth over -# repeated appends, instead of the typical quadratic growth present in naive -# implementations. -if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null -then : - eval 'as_fn_append () - { - eval $1+=\$2 - }' -else case e in #( - e) as_fn_append () - { - eval $1=\$$1\$2 - } ;; -esac -fi # as_fn_append - -# as_fn_arith ARG... -# ------------------ -# Perform arithmetic evaluation on the ARGs, and store the result in the -# global $as_val. Take advantage of shells that can avoid forks. The arguments -# must be portable across $(()) and expr. -if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null -then : - eval 'as_fn_arith () - { - as_val=$(( $* )) - }' -else case e in #( - e) as_fn_arith () - { - as_val=`expr "$@" || test $? -eq 1` - } ;; -esac -fi # as_fn_arith - - -if expr a : '\(a\)' >/dev/null 2>&1 && - test "X`expr 00001 : '.*\(...\)'`" = X001; then - as_expr=expr -else - as_expr=false -fi - -if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then - as_basename=basename -else - as_basename=false -fi - -if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then - as_dirname=dirname -else - as_dirname=false -fi - -as_me=`$as_basename -- "$0" || -$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| . 2>/dev/null || -printf "%s\n" X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ - s//\1/ - q - } - /^X\/\(\/\/\)$/{ - s//\1/ - q - } - /^X\/\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - - -# Determine whether it's possible to make 'echo' print without a newline. -# These variables are no longer used directly by Autoconf, but are AC_SUBSTed -# for compatibility with existing Makefiles. -ECHO_C= ECHO_N= ECHO_T= -case `echo -n x` in #((((( --n*) - case `echo 'xy\c'` in - *c*) ECHO_T=' ';; # ECHO_T is single tab character. - xy) ECHO_C='\c';; - *) echo `echo ksh88 bug on AIX 6.1` > /dev/null - ECHO_T=' ';; - esac;; -*) - ECHO_N='-n';; -esac - -# For backward compatibility with old third-party macros, we provide -# the shell variables $as_echo and $as_echo_n. New code should use -# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. -as_echo='printf %s\n' -as_echo_n='printf %s' - -rm -f conf$$ conf$$.exe conf$$.file -if test -d conf$$.dir; then - rm -f conf$$.dir/conf$$.file -else - rm -f conf$$.dir - mkdir conf$$.dir 2>/dev/null -fi -if (echo >conf$$.file) 2>/dev/null; then - if ln -s conf$$.file conf$$ 2>/dev/null; then - as_ln_s='ln -s' - # ... but there are two gotchas: - # 1) On MSYS, both 'ln -s file dir' and 'ln file dir' fail. - # 2) DJGPP < 2.04 has no symlinks; 'ln -s' creates a wrapper executable. - # In both cases, we have to default to 'cp -pR'. - ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -pR' - elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln - else - as_ln_s='cp -pR' - fi -else - as_ln_s='cp -pR' -fi -rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file -rmdir conf$$.dir 2>/dev/null - - -# as_fn_mkdir_p -# ------------- -# Create "$as_dir" as a directory, including parents if necessary. -as_fn_mkdir_p () -{ - - case $as_dir in #( - -*) as_dir=./$as_dir;; - esac - test -d "$as_dir" || eval $as_mkdir_p || { - as_dirs= - while :; do - case $as_dir in #( - *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( - *) as_qdir=$as_dir;; - esac - as_dirs="'$as_qdir' $as_dirs" - as_dir=`$as_dirname -- "$as_dir" || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || -printf "%s\n" X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - test -d "$as_dir" && break - done - test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" - - -} # as_fn_mkdir_p -if mkdir -p . 2>/dev/null; then - as_mkdir_p='mkdir -p "$as_dir"' -else - test -d ./-p && rmdir ./-p - as_mkdir_p=false -fi - - -# as_fn_executable_p FILE -# ----------------------- -# Test if FILE is an executable regular file. -as_fn_executable_p () -{ - test -f "$1" && test -x "$1" -} # as_fn_executable_p -as_test_x='test -x' -as_executable_p=as_fn_executable_p - -# Sed expression to map a string onto a valid CPP name. -as_sed_cpp="y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" -as_tr_cpp="eval sed '$as_sed_cpp'" # deprecated - -# Sed expression to map a string onto a valid variable name. -as_sed_sh="y%*+%pp%;s%[^_$as_cr_alnum]%_%g" -as_tr_sh="eval sed '$as_sed_sh'" # deprecated - - -exec 6>&1 -## ----------------------------------- ## -## Main body of $CONFIG_STATUS script. ## -## ----------------------------------- ## -_ASEOF -test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -# Save the log message, to keep $0 and so on meaningful, and to -# report actual input values of CONFIG_FILES etc. instead of their -# values after options handling. -ac_log=" -This file was extended by $as_me, which was -generated by GNU Autoconf 2.72. Invocation command line was - - CONFIG_FILES = $CONFIG_FILES - CONFIG_HEADERS = $CONFIG_HEADERS - CONFIG_LINKS = $CONFIG_LINKS - CONFIG_COMMANDS = $CONFIG_COMMANDS - $ $0 $@ - -on `(hostname || uname -n) 2>/dev/null | sed 1q` -" - -_ACEOF - - - - -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -# Files that config.status was made for. - -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -ac_cs_usage="\ -'$as_me' instantiates files and other configuration actions -from templates according to the current configuration. Unless the files -and actions are specified as TAGs, all are instantiated by default. - -Usage: $0 [OPTION]... [TAG]... - - -h, --help print this help, then exit - -V, --version print version number and configuration settings, then exit - --config print configuration, then exit - -q, --quiet, --silent - do not print progress messages - -d, --debug don't remove temporary files - --recheck update $as_me by reconfiguring in the same conditions - -Report bugs to the package provider." - -_ACEOF -ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"` -ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"` -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -ac_cs_config='$ac_cs_config_escaped' -ac_cs_version="\\ -config.status -configured by $0, generated by GNU Autoconf 2.72, - with options \\"\$ac_cs_config\\" - -Copyright (C) 2023 Free Software Foundation, Inc. -This config.status script is free software; the Free Software Foundation -gives unlimited permission to copy, distribute and modify it." - -ac_pwd='$ac_pwd' -srcdir='$srcdir' -test -n "\$AWK" || AWK=awk -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -# The default lists apply if the user does not specify any file. -ac_need_defaults=: -while test $# != 0 -do - case $1 in - --*=?*) - ac_option=`expr "X$1" : 'X\([^=]*\)='` - ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` - ac_shift=: - ;; - --*=) - ac_option=`expr "X$1" : 'X\([^=]*\)='` - ac_optarg= - ac_shift=: - ;; - *) - ac_option=$1 - ac_optarg=$2 - ac_shift=shift - ;; - esac - - case $ac_option in - # Handling of the options. - -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) - ac_cs_recheck=: ;; - --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) - printf "%s\n" "$ac_cs_version"; exit ;; - --config | --confi | --conf | --con | --co | --c ) - printf "%s\n" "$ac_cs_config"; exit ;; - --debug | --debu | --deb | --de | --d | -d ) - debug=: ;; - --he | --h | --help | --hel | -h ) - printf "%s\n" "$ac_cs_usage"; exit ;; - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil | --si | --s) - ac_cs_silent=: ;; - - # This is an error. - -*) as_fn_error $? "unrecognized option: '$1' -Try '$0 --help' for more information." ;; - - *) as_fn_append ac_config_targets " $1" - ac_need_defaults=false ;; - - esac - shift -done - -ac_configure_extra_args= - -if $ac_cs_silent; then - exec 6>/dev/null - ac_configure_extra_args="$ac_configure_extra_args --silent" -fi - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -if \$ac_cs_recheck; then - set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion - shift - \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6 - CONFIG_SHELL='$SHELL' - export CONFIG_SHELL - exec "\$@" -fi - -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -exec 5>>config.log -{ - echo - sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX -## Running $as_me. ## -_ASBOX - printf "%s\n" "$ac_log" -} >&5 - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 - -# Handling of arguments. -for ac_config_target in $ac_config_targets -do - case $ac_config_target in - - *) as_fn_error $? "invalid argument: '$ac_config_target'" "$LINENO" 5;; - esac -done - - -as_fn_exit 0 -_ACEOF -ac_clean_files=$ac_clean_files_save - -test $ac_write_fail = 0 || - as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 - - -# configure is writing to config.log, and then calls config.status. -# config.status does its own redirection, appending to config.log. -# Unfortunately, on DOS this fails, as config.log is still kept open -# by configure, so config.status won't be able to write to it; its -# output is simply discarded. So we exec the FD to /dev/null, -# effectively closing config.log, so it can be properly (re)opened and -# appended to by config.status. When coming back to configure, we -# need to make the FD available again. -if test "$no_create" != yes; then - ac_cs_success=: - ac_config_status_args= - test "$silent" = yes && - ac_config_status_args="$ac_config_status_args --quiet" - exec 5>/dev/null - $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false - exec 5>>config.log - # Use ||, not &&, to avoid exiting from the if with $? = 1, which - # would make configure fail if this is the last instruction. - $ac_cs_success || as_fn_exit 1 -fi -if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 -printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} -fi - - diff --git a/configure.ac b/configure.ac deleted file mode 100644 index e8c53d1..0000000 --- a/configure.ac +++ /dev/null @@ -1,27 +0,0 @@ -AC_INIT - -AC_CHECK_PROGS([MAKE], [make], [no]) -AS_IF([test "$MAKE" == "no"], - [AC_MSG_NOTICE([without GNU Make, you have to inspect 'Makefile' and deduce build targets yourself.])]) - -AC_CHECK_PROGS([GIT], [git], [no]) -AS_IF([test "$GIT" == "no"], - [AC_MSG_ERROR([install Git, before continuing.])]) - -AC_CHECK_PROGS([PYTHON3], [python3], [no]) -AS_IF([test "$PYTHON3" == "no"], - [AC_MSG_ERROR([install Python 3, before continuing.])]) - -# required in Makefile to ensure proper path resolution during preprocessing -# realpath is not available on macOS -AC_CHECK_PROGS([REALPATH], [realpath], [no]) -AS_IF([test "$REALPATH" == "no"], - [AC_MSG_ERROR([set a persistent alias for 'realpath', before continuing, e.g. - -alias='python3 -c "import pathlib,sys;print(pathlib.Path(sys.argv[[1]]).resolve())"'" -])]) - -AC_MSG_NOTICE([initializing python3 venv...]) -make .venv - -AC_OUTPUT diff --git a/pyproject.toml b/pyproject.toml index b5fcdb7..b3c3d30 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,12 +7,12 @@ requires = [ build-backend = "setuptools.build_meta" [project] -name = "byteb4rb1e-utils" +name = "byteb4rb1e.utils" description = "personal utilities and helpers" authors = [ - { name = "Tiara Rodney", email = "tiara.rodney@administratrix.de" } + { name = "Tiara Rodney", email = "tiara.rodney@byteb4rb1e.me" } ] -license = { file = "LICENSE" } +license-files = ["LICENSE"] readme = "README.md" classifiers = [ "Development Status :: 1 - Planning", @@ -48,7 +48,6 @@ strict = true max_line_length = 80 aggressive = 3 recursive = true -in-place = true [tool.setuptools_scm] diff --git a/requirements-dev.txt b/requirements-dev.txt deleted file mode 100644 index 15e7cea..0000000 --- a/requirements-dev.txt +++ /dev/null @@ -1,25 +0,0 @@ --i https://pypi.org/simple -astroid==3.3.9; python_full_version >= '3.9.0' -autopep8==2.3.2; python_version >= '3.9' -build==1.2.2.post1; python_version >= '3.8' --e . -certifi==2025.4.26; python_version >= '3.6' -colorama==0.4.6; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6' -dill==0.4.0; python_version >= '3.8' -distlib==0.3.9 -filelock==3.18.0; python_version >= '3.9' -isort==6.0.1; python_full_version >= '3.9.0' -mccabe==0.7.0; python_version >= '3.6' -mypy==1.15.0; python_version >= '3.9' -mypy-extensions==1.1.0; python_version >= '3.8' -packaging==25.0; python_version >= '3.8' -pipenv==2025.0.2; python_version >= '3.9' -platformdirs==4.3.7; python_version >= '3.9' -pycodestyle==2.13.0; python_version >= '3.9' -pylint==3.3.6; python_full_version >= '3.9.0' -pyproject-hooks==1.2.0; python_version >= '3.7' -setuptools==80.3.0; python_version >= '3.9' -setuptools-scm==8.2.0; python_version >= '3.8' -tomlkit==0.13.2; python_version >= '3.8' -typing-extensions==4.13.2; python_version >= '3.8' -virtualenv==20.30.0; python_version >= '3.8' diff --git a/tests/unit/__init__.py b/src/byteb4rb1e/testing/__init__.py similarity index 100% rename from tests/unit/__init__.py rename to src/byteb4rb1e/testing/__init__.py diff --git a/src/byteb4rb1e/testing/pytest/__init__.py b/src/byteb4rb1e/testing/pytest/__init__.py new file mode 100644 index 0000000..87e7c10 --- /dev/null +++ b/src/byteb4rb1e/testing/pytest/__init__.py @@ -0,0 +1,14 @@ +import os +from pathlib import Path +from typing import Tuple + + +def get_current_test() -> Tuple[Path, str]: + current_test_env = os.getenv("PYTEST_CURRENT_TEST") + if current_test_env is None: + raise RuntimeError("PYTEST_CURRENT_TEST not set. Must be run under pytest.") + + suite_path, case_name = current_test_env.split('::', 1) + case_name = case_name.split(' ', 1)[0] + return Path(suite_path).resolve(), case_name + diff --git a/src/byteb4rb1e/testing/pytest/decorators.py b/src/byteb4rb1e/testing/pytest/decorators.py new file mode 100644 index 0000000..a7d8161 --- /dev/null +++ b/src/byteb4rb1e/testing/pytest/decorators.py @@ -0,0 +1,47 @@ +from functools import wraps +from pathlib import Path +import os +import subprocess +import sys + +from byteb4rb1e.testing.pytest import get_current_test + + +def run_in_subprocess_once(): + """ + A decorator that reruns th test in a subprocess if not already inside one. + Requires pytest to be installed and test to be run by pytest. + + For what? Anything that can't be done in a thread-safe manner, e.g. modifying PYTHON_PATH + """ + def decorator(test_func): + @wraps(test_func) + def wrapper(*args, **kwargs): + if os.environ.get("XPYTEST_INSIDE_SUBPROCESS") == "1": + return test_func(*args, **kwargs) + + suite_path, case_name = get_current_test() + + cmd = [ + sys.executable, + "-m", "pytest", + f"{suite_path}::{case_name}", + ] + + result = subprocess.run( + cmd, + env={**os.environ, "XPYTEST_INSIDE_SUBPROCESS": "1"}, + capture_output=True, + text=True, + ) + + if result.returncode != 0: + print(' '.join(cmd)) + print("==== Subprocess stdout ====") + print(result.stdout) + print("==== Subprocess stderr ====") + print(result.stderr) + raise AssertionError(f"Subprocess test failed with exit code {result.returncode}") + return wrapper + return decorator + diff --git a/src/byteb4rb1e/testing/pytest/fixtures.py b/src/byteb4rb1e/testing/pytest/fixtures.py new file mode 100644 index 0000000..7c93041 --- /dev/null +++ b/src/byteb4rb1e/testing/pytest/fixtures.py @@ -0,0 +1,44 @@ +import os +from pathlib import Path +import sys +from typing import Dict, Tuple, Union + +import pytest + +from byteb4rb1e.testing.pytest import get_current_test + +_SITE_PACKAGE_COUNTER: Dict[str, int] = {} + + +@pytest.fixture +def current_test() -> Tuple[Path, str]: + """ + """ + return get_current_test() + + +@pytest.fixture +def mock_system_site_package_dir(tmp_path): + global _SITE_PACKAGE_COUNTER + + package_id = _SITE_PACKAGE_COUNTER.setdefault(tmp_path, 0) + _SITE_PACKAGE_COUNTER[tmp_path] += 1 + + sys_path = tmp_path / str(package_id) + + def _create(name: str) -> Path: + pkg_path = sys_path / name.replace('.', os.path.sep) + + pkg_path.mkdir(parents=True) + + (pkg_path / "__init__.py").touch() + + sys.path.insert(0, str(sys_path)) + + return pkg_path + + yield _create + + # cleanup sys.path after test + if str(sys_path) in sys.path: + sys.path.remove(str(sys_path)) diff --git a/tests/unit/byteb4rb1e_utils/__init__.py b/src/byteb4rb1e/utils/__init__.py similarity index 100% rename from tests/unit/byteb4rb1e_utils/__init__.py rename to src/byteb4rb1e/utils/__init__.py diff --git a/src/byteb4rb1e/utils/argparse/__init__.py b/src/byteb4rb1e/utils/argparse/__init__.py new file mode 100644 index 0000000..84ae3ed --- /dev/null +++ b/src/byteb4rb1e/utils/argparse/__init__.py @@ -0,0 +1,6 @@ +"""Utilities for building composable CLIs from command dataclasses.""" + +from byteb4rb1e.utils.argparse.command import CLICommand +from byteb4rb1e.utils.argparse.dispatcher import CLI + +__all__ = ["CLI", "CLICommand"] diff --git a/src/byteb4rb1e/utils/argparse/command.py b/src/byteb4rb1e/utils/argparse/command.py new file mode 100644 index 0000000..199e4f1 --- /dev/null +++ b/src/byteb4rb1e/utils/argparse/command.py @@ -0,0 +1,54 @@ +"""Base command dataclass for composable CLI trees.""" + +from __future__ import annotations + +from argparse import ArgumentParser +from dataclasses import dataclass, fields +from typing import Any, ClassVar, Dict, List, Optional, Type + + +@dataclass +class CLICommand: + """Base class for CLI commands. + + Subclasses define their identity (name, help, description) as + dataclass fields. These are passed as kwargs to + ``subparsers.add_parser()``. + + Override ``add_arguments`` to register flags and positionals. + Override ``execute`` to implement the command's logic. + + Nest subcommands by setting ``_subcommands`` as a class variable. + """ + + name: str = "" + help: str = "" + description: str = "" + + _subcommands: ClassVar[List[Type[Command]]] = [] + + def add_arguments(self, parser: ArgumentParser) -> None: + """Add arguments to the parser. Override in subclasses.""" + + def execute(self, args: Any) -> int: + """Run the command. Override in subclasses. + + Returns an exit code (0 = success). + """ + return 0 + + def parser_kwargs(self) -> Dict[str, Any]: + """Return the dataclass fields as kwargs for add_parser. + + Excludes ``name`` (used as the positional parser name) and + any empty-string fields so argparse defaults apply. + """ + skip = {"name"} + kwargs = {} + for f in fields(self): + if f.name in skip or f.name.startswith("_"): + continue + val = getattr(self, f.name) + if val != "": + kwargs[f.name] = val + return kwargs diff --git a/src/byteb4rb1e/utils/argparse/dispatcher.py b/src/byteb4rb1e/utils/argparse/dispatcher.py new file mode 100644 index 0000000..b579351 --- /dev/null +++ b/src/byteb4rb1e/utils/argparse/dispatcher.py @@ -0,0 +1,122 @@ +"""CLI dispatcher — builds parser trees from command dataclasses.""" + +from __future__ import annotations + +import logging +from argparse import ArgumentDefaultsHelpFormatter, ArgumentParser +from typing import Any, Dict, List, Optional, Type + +from byteb4rb1e.utils.argparse.command import CLICommand + + +class CLI: + """Composable CLI built from a tree of Command dataclasses. + + Recursively bootstraps an argparse parser hierarchy and tracks + dest names so ``run()`` can dispatch to the correct leaf command + without dest chaining in the caller. + + Usage:: + + cli = CLI(prog="repository", description="...") + cli.bootstrap([MirrorCommand, IndexCommand]) + cli.run() + """ + + def __init__( + self, + prog: Optional[str] = None, + description: str = "", + ) -> None: + kwargs = {} # type: Dict[str, Any] + if prog: + kwargs["prog"] = prog + if description: + kwargs["description"] = description + kwargs.setdefault( + "formatter_class", ArgumentDefaultsHelpFormatter, + ) + self.parser = ArgumentParser(**kwargs) + self._dests = [] # type: List[str] + self._commands = {} # type: Dict[str, Command] + + def add_arguments(self, parser: ArgumentParser) -> None: + """Add global arguments to the root parser.""" + parser.add_argument( + "-v", "--verbose", action="count", default=0, + help="Increase verbosity (-v for INFO, -vv for DEBUG)", + ) + + def bootstrap( + self, + commands: List[Type[Command]], + ) -> None: + """Build the parser tree from a list of top-level commands.""" + self.add_arguments(self.parser) + dest = "command" + self._dests.append(dest) + sub = self.parser.add_subparsers(dest=dest) + for cmd_cls in commands: + self._add(sub, cmd_cls, prefix="") + + def _add( + self, + subparsers: Any, + cmd_cls: Type[Command], + prefix: str, + ) -> None: + """Recursively add a command and its subcommands.""" + cmd = cmd_cls() + parser = subparsers.add_parser( + cmd.name, + formatter_class=ArgumentDefaultsHelpFormatter, + **cmd.parser_kwargs(), + ) + cmd.add_arguments(parser) + + key = "%s.%s" % (prefix, cmd.name) if prefix else cmd.name + self._commands[key] = cmd + + if cmd._subcommands: + dest = "%s_command" % cmd.name + self._dests.append(dest) + child_sub = parser.add_subparsers(dest=dest) + for sc_cls in cmd._subcommands: + self._add(child_sub, sc_cls, prefix=key) + + def _resolve(self, args: Any) -> Optional[Command]: + """Walk dest chain to find the leaf command.""" + parts = [] # type: List[str] + for dest in self._dests: + val = getattr(args, dest, None) + if val is None: + continue + parts.append(val) + if not parts: + return None + key = ".".join(parts) + return self._commands.get(key) + + @staticmethod + def _setup_logging(verbosity: int) -> None: + if verbosity >= 2: + level = logging.DEBUG + elif verbosity >= 1: + level = logging.INFO + else: + level = logging.WARNING + logging.basicConfig( + level=level, + format="%(asctime)s [%(levelname)s] %(message)s", + handlers=[logging.StreamHandler()], + ) + + def run(self) -> None: + """Parse args and dispatch to the leaf command.""" + args = self.parser.parse_args() + self._setup_logging(getattr(args, "verbose", 0)) + cmd = self._resolve(args) + if cmd is None: + self.parser.print_help() + raise SystemExit(1) + raise SystemExit(cmd.execute(args)) diff --git a/src/byteb4rb1e_utils/collections.py b/src/byteb4rb1e/utils/collections.py similarity index 100% rename from src/byteb4rb1e_utils/collections.py rename to src/byteb4rb1e/utils/collections.py diff --git a/tests/unit/byteb4rb1e_utils/collections/__init__.py b/src/byteb4rb1e/utils/http/__init__.py similarity index 100% rename from tests/unit/byteb4rb1e_utils/collections/__init__.py rename to src/byteb4rb1e/utils/http/__init__.py diff --git a/src/byteb4rb1e/utils/http/client.py b/src/byteb4rb1e/utils/http/client.py new file mode 100644 index 0000000..0962445 --- /dev/null +++ b/src/byteb4rb1e/utils/http/client.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python3 +"""Generic HTTP client. + +Thin urllib wrapper with retry-on-rate-limit. No domain knowledge — +GitHub, Bitbucket, etc. are handled by higher-level modules. +""" + +import json +import time +from typing import Any, Dict, Optional +import urllib.request +import urllib.parse +from warnings import warn + + +class HttpResponse: + def __init__(self, status: int, headers: dict, data: bytes, reason: str): + self.status_code = status + self.headers = headers + self.data = data + self.reason = reason + self.text = data.decode("utf-8", errors="replace") + + def json(self): + return json.loads(self.data.decode("utf-8")) + + +def _request( + url: str, + method: str = "GET", + params: Optional[Dict[str, Any]] = None, + headers: Optional[Dict[str, str]] = None, + data: Optional[bytes] = None, +) -> HttpResponse: + # TODO: do proper exponential backoff + backoff = [1, 2, 4] + + if params: + query = urllib.parse.urlencode(params) + url = f"{url}?{query}" + + req = urllib.request.Request( + url, + headers=headers or {}, + method=method, + data=data, + ) + + for delay in backoff: + try: + with urllib.request.urlopen(req, timeout=30) as resp: + status = resp.getcode() + resp_data = resp.read() + resp_headers = dict(resp.getheaders()) + + if status == 429: + warn(f"Rate-limited on {url} (HTTP {status})." + f" Backing off {delay}s...") + time.sleep(delay) + continue + + return HttpResponse( + status, resp_headers, resp_data, resp.reason, + ) + + except urllib.error.HTTPError as e: + status = e.code + err_data = e.read() + err_headers = dict(e.headers.items()) + if status == 429: + warn(f"Rate-limited on {url} (HTTP {status})." + f" Backing off {delay}s...") + time.sleep(delay) + continue + return HttpResponse( + status, err_headers, err_data, e.reason, + ) + + except urllib.error.URLError as e: + raise Exception( + "Network error on %s: %s", url, e, + ) from e + + # If all retries exhausted, return last error-like response + return HttpResponse(503, {}, b"", "Service unavailable") + + +def get( + url: str, + params: Optional[Dict[str, Any]] = None, + headers: Optional[Dict[str, str]] = None, +) -> HttpResponse: + return _request(url, method="GET", params=params, headers=headers) + + +def post( + url: str, + data: Optional[bytes] = None, + headers: Optional[Dict[str, str]] = None, +) -> HttpResponse: + return _request(url, method="POST", headers=headers, data=data) + + +def put( + url: str, + data: Optional[bytes] = None, + headers: Optional[Dict[str, str]] = None, +) -> HttpResponse: + return _request(url, method="PUT", headers=headers, data=data) diff --git a/src/byteb4rb1e_utils/http/server/__init__.py b/src/byteb4rb1e/utils/http/server/__init__.py similarity index 99% rename from src/byteb4rb1e_utils/http/server/__init__.py rename to src/byteb4rb1e/utils/http/server/__init__.py index c1f6186..2486612 100644 --- a/src/byteb4rb1e_utils/http/server/__init__.py +++ b/src/byteb4rb1e/utils/http/server/__init__.py @@ -1,7 +1,7 @@ from dataclasses import dataclass from http.server import SimpleHTTPRequestHandler -from byteb4rb1e_utils.io import ChunksIO +from byteb4rb1e.utils.io import ChunksIO @dataclass diff --git a/src/byteb4rb1e_utils/http/server/__main__.py b/src/byteb4rb1e/utils/http/server/__main__.py similarity index 96% rename from src/byteb4rb1e_utils/http/server/__main__.py rename to src/byteb4rb1e/utils/http/server/__main__.py index 7bca378..b66bc52 100644 --- a/src/byteb4rb1e_utils/http/server/__main__.py +++ b/src/byteb4rb1e/utils/http/server/__main__.py @@ -8,12 +8,12 @@ from http.server import HTTPServer from io import BytesIO, IOBase from typing import Optional, Tuple, List -from byteb4rb1e_utils.http.server import ( +from byteb4rb1e.utils.http.server import ( HandlerOptions, MultipartUploadHandler, ServerOptions, ) -from byteb4rb1e_utils.io import ChunksIO +from byteb4rb1e.utils.io import ChunksIO __doc__ = """tsmuds - Tiara's Simple Multipart Upload Debugging Server diff --git a/src/byteb4rb1e_utils/io/__init__.py b/src/byteb4rb1e/utils/io/__init__.py similarity index 100% rename from src/byteb4rb1e_utils/io/__init__.py rename to src/byteb4rb1e/utils/io/__init__.py diff --git a/src/byteb4rb1e/utils/saas/bitbucket.py b/src/byteb4rb1e/utils/saas/bitbucket.py new file mode 100644 index 0000000..d9b5bad --- /dev/null +++ b/src/byteb4rb1e/utils/saas/bitbucket.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python3 +"""Bitbucket Cloud REST API v2.0 wrapper. + +Thin layer over http.py for Bitbucket-specific operations: + +- Bearer token authentication +- Repository existence checks +- Repository creation within a workspace/project +""" + +import json +from typing import Any, Dict, Optional + +from byteb4rb1e.utils.http import client as http_client + + +BITBUCKET_API = "https://api.bitbucket.org/2.0" + + +def http_headers(token: str) -> Dict[str, str]: + """Construct Bitbucket API headers with Bearer token auth.""" + return { + "Authorization": f"Bearer {token}", + "Accept": "application/json", + "Content-Type": "application/json", + } + + +def repository_exists( + workspace: str, + repo_slug: str, + token: str, +) -> bool: + """Check whether a repository exists in the workspace.""" + url = f"{BITBUCKET_API}/repositories/{workspace}/{repo_slug}" + resp = http_client.get(url, headers=http_headers(token)) + return resp.status_code == 200 + + +def create_repository( + workspace: str, + repo_slug: str, + token: str, + project: Optional[str] = None, + description: str = "", + is_private: bool = True, +) -> http_client.HttpResponse: + """Create a new repository in the workspace. + + When *project* is given the repository is assigned to that + Bitbucket project (by key). This is required for workspaces + that scope access keys at the project level. + + Returns the API response. Caller should check status_code == 200 + for success. + """ + url = f"{BITBUCKET_API}/repositories/{workspace}/{repo_slug}" + body: Dict[str, Any] = { + "scm": "git", + "is_private": is_private, + "description": description, + "fork_policy": "no_forks", + } + if project: + body["project"] = {"key": project} + return http_client.put( + url, + data=json.dumps(body).encode("utf-8"), + headers=http_headers(token), + ) + + +def clone_url( + workspace: str, + repo_slug: str, +) -> str: + """Return the SSH clone URL for a Bitbucket repository.""" + return f"git@bitbucket.org:{workspace}/{repo_slug}.git" diff --git a/src/byteb4rb1e/utils/saas/github.py b/src/byteb4rb1e/utils/saas/github.py new file mode 100644 index 0000000..d174827 --- /dev/null +++ b/src/byteb4rb1e/utils/saas/github.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 +import hashlib +from pathlib import Path +from typing import Any, Dict, List, Optional + +from byteb4rb1e.utils.http import client as http_client + + +GITHUB_API = "https://api.github.com" + + +def http_headers(token: Optional[str]) -> Dict[str, str]: + headers = { + "Accept": "application/vnd.github+json", + "User-Agent": "sphinx-h5p-worker1" + } + if token: + # Use standard PAT header; token not logged anywhere. + headers["Authorization"] = f"Bearer {token}" + return headers + + +def blob_sha(path: Path) -> str: + """Calculate Git blob SHA-1 for a file, matching GitHub API 'sha'.""" + data = path.read_bytes() + header = f"blob {len(data)}\0".encode("utf-8") + store = header + data + return hashlib.sha1(store).hexdigest() + + +def list_org_repos(org: str, token: Optional[str]) -> List[Dict[str, Any]]: + repos: List[Dict[str, Any]] = [] + page = 1 + per_page = 100 + while True: + url = f"{GITHUB_API}/orgs/{org}/repos" + resp = http_client.get( + url, + params={"page": page, "per_page": per_page, "type": "public"}, + headers=http_headers(token), + ) + if resp.status_code != 200: + raise RuntimeError(f"Failed to list repos for org {org}: {resp.status_code} {resp.text}") + batch = resp.json() + if not batch: + break + repos.extend(batch) + page += 1 + return repos + + +def fetch_file( + org: str, + repo: str, + path: str, + token: str +) -> http_client.HttpResponse: + """ + """ + url = f"{GITHUB_API}/repos/{org}/{repo}/{path}" + + return http_client.get( + url, + headers=http_headers(token), + ) diff --git a/src/byteb4rb1e/utils/string.py b/src/byteb4rb1e/utils/string.py new file mode 100644 index 0000000..800a5bc --- /dev/null +++ b/src/byteb4rb1e/utils/string.py @@ -0,0 +1,91 @@ +from typing import Optional + + +class RollingHash: + """implementation of Rabin-Karp rolling hash + """ + #: default base + base: int = 31 + #: default modulus + mod: int = 10**9 + 7 + #: current computed hash + _hash: int + #: prime number base (e.g., 31) + _base: int + #: large prime modulus (to prevent overflow) + _mod: int + # Precomputation of ``base^(length-1) % mod`` for removing the old byte when + # rolling over + _hbase_factor: int + + def __init__( + self, + data: bytes, + base: Optional[int] = None, + mod: Optional[int] = None + ): + """Initialize the rolling hash with a given base and modulus. + + base: Prime number base (e.g., 31) + mod: Large prime modulus to prevent overflow + length: Length of the pattern to match + """ + self._base = base if base else RollingHash.base + + self._mod = mod if mod else RollingHash.mod + + self._hash = RollingHash.compute_initial_hash( + data, + self._base, + self._mod + ) + + self._hbase_factor = pow(self._base, len(data) - 1, self._mod) + + @staticmethod + def compute_initial_hash( + data: bytes, + base: int, + mod: int, + ) -> int: + """Compute the hash for the initial window (first `length` bytes). + + rather use this standalone for computing the hash of the search pattern, + to avoid the overhead of instantiating an object. + + :param data: data to build hash for + :param base: + :param: mod: + + :returns: hash of data + """ + hash_ = 0 + for i in range(len(data)): + # computing the modulus at each iteration, as to avoid the summed + # integer to be chunky, as in HUUUUGEE... + hash_ = (hash_ * base + data[i]) % mod + return hash_ + + def roll(self, old_byte: int, new_byte: int) -> int: + """Efficiently update hash by removing ``old_byte`` and adding + ``new_byte`` + + The old_byte removal uses a pre-computed value of the highest base used + in the polynomial calculation. This speeds things up a bit. + + I was thinking about a way on how to store the old_byte efficiently + within the class object, but that would require storing the entire data, + basically doubling the memory consumption as the data must definetly + also live outside of the class object. A memoryview could solve this + problem, but at the cost of making the implementation more complex, so + this will have to do. + + :param old_byte: The ordinal of the first byte in buffer to roll over + :param new_byte: The ordinal of the byte newly appended to the buffer + """ + # Remove old + self._hash = (self._hash - old_byte * self._hbase_factor) % self.mod + # Add new + self._hash = (self._hash * self.base + new_byte) % self.mod + + return self._hash diff --git a/tests/unit/byteb4rb1e_utils/io/__init__.py b/src/byteb4rb1e/utils/urllib/__init__.py similarity index 100% rename from tests/unit/byteb4rb1e_utils/io/__init__.py rename to src/byteb4rb1e/utils/urllib/__init__.py diff --git a/src/byteb4rb1e/utils/urllib/request.py b/src/byteb4rb1e/utils/urllib/request.py new file mode 100644 index 0000000..2408d94 --- /dev/null +++ b/src/byteb4rb1e/utils/urllib/request.py @@ -0,0 +1,41 @@ +import email +import importlib.resources +import mimetypes +from urllib.request import URLError +import urllib.request + + +class PkgHandler(urllib.request.BaseHandler): + """ + """ + def pkg_open(self, req) -> urllib.request.addinfourl: + pkg_files = importlib.resources.files(req.host) + + try: + fh = next( + pkg_files.glob(req.selector.lstrip('//')) + ).open('rb') + except Exception as e: + raise URLError(f'{e.__class__.__name__}: {e}') from e + + fh.seek(0, 2); + size = fh.tell(); + fh.seek(0); + + mtype, compression = mimetypes.guess_type(req.selector) + + if compression and mtype: + mtype = f"{mtype}+{compression}" + + headers = email.message_from_string( + 'Content-Type: %s\nContent-Length: %d\n' % + (mtype or 'text/plain', size) + ) + + if not mtype or mtype.startswith('text/'): + fh.close() + fh = next( + pkg_files.glob(req.selector.lstrip('//')) + ).open('r') + + return urllib.request.addinfourl(fh, headers, None) diff --git a/src/byteb4rb1e/utils/vcs/__init__.py b/src/byteb4rb1e/utils/vcs/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/byteb4rb1e/utils/vcs/git.py b/src/byteb4rb1e/utils/vcs/git.py new file mode 100644 index 0000000..cd4cd87 --- /dev/null +++ b/src/byteb4rb1e/utils/vcs/git.py @@ -0,0 +1,345 @@ +#!/usr/bin/env python3 +"""Git subprocess wrapper for repository operations. + +Provides primitives for mirror cloning, syncing, remote management, +file extraction from bare repos, and submodule management. +No pygit2 or gitpython, uses subprocess only. +""" +import logging +import subprocess +from pathlib import Path +from typing import List, Optional + +logger = logging.getLogger(__name__) + + +class GitError(Exception): + """A git subprocess returned a non-zero exit code.""" + + def __init__(self, args: List[str], returncode: int, stderr: str): + self.args_list = args + self.returncode = returncode + self.stderr = stderr + super().__init__( + f"git exited {returncode}: {' '.join(args)}\n{stderr}" + ) + + +def parse_base_url(base_url: str) -> str: + """Extract workspace from an SCP-style Bitbucket base URL. + + The host part must be exactly ``bitbucket.org`` — bootstrapping + requires the Bitbucket API, so other hosts are rejected. + + >>> _parse_base_url("git@bitbucket.org:byteb4rb1e") + 'byteb4rb1e' + """ + # SCP-style: git@bitbucket.org:workspace + if ":" not in base_url or "//" in base_url: + raise ValueError( + f"Expected SCP-style URL (git@bitbucket.org:workspace), " + f"got: {base_url}" + ) + host_part, workspace = base_url.split(":", 1) + # host_part is e.g. "git@bitbucket.org" + host = host_part.split("@", 1)[-1] + if host != "bitbucket.org": + raise ValueError( + f"Mirror base URL must target bitbucket.org, " + f"got host: {host}" + ) + return Path(workspace).parent + + +def parse_repo_name(base_url: str) -> str: + """Extract workspace from an SCP-style Bitbucket base URL. + + The host part must be exactly ``bitbucket.org`` — bootstrapping + requires the Bitbucket API, so other hosts are rejected. + + >>> _parse_base_url("git@bitbucket.org:byteb4rb1e") + 'byteb4rb1e' + """ + # SCP-style: git@bitbucket.org:workspace + if ":" not in base_url or "//" in base_url: + raise ValueError( + f"Expected SCP-style URL (git@bitbucket.org:workspace), " + f"got: {base_url}" + ) + host_part, workspace = base_url.split(":", 1) + # host_part is e.g. "git@bitbucket.org" + host = host_part.split("@", 1)[-1] + if host != "bitbucket.org": + raise ValueError( + f"Mirror base URL must target bitbucket.org, " + f"got host: {host}" + ) + return Path(workspace).name.split('.')[0] + + + +def _run( + args: List[str], + cwd: Optional[Path] = None, + capture_stdout: bool = False, +) -> subprocess.CompletedProcess: # type: ignore[type-arg] + """Run a git command, raising GitError on failure.""" + cmd = ["git"] + args + logger.debug("$ %s", " ".join(cmd)) + result = subprocess.run( + cmd, + cwd=cwd, + capture_output=True, + text=True, + ) + if result.returncode != 0: + raise GitError(cmd, result.returncode, result.stderr.strip()) + return result + + +def mirror_clone(source_url: str, dest: Path) -> None: + """Clone a repository as a bare mirror. + + Equivalent to ``git clone --mirror ``. + The destination directory must not already exist. + """ + _run(["clone", "--mirror", source_url, str(dest)]) + logger.info("Cloned mirror %s → %s", source_url, dest) + + +def add_remote(repo: Path, name: str, url: str) -> None: + """Add a named remote to a bare repository.""" + _run(["remote", "add", name, url], cwd=repo) + logger.debug("Added remote %s → %s in %s", name, url, repo) + + +def has_remote(repo: Path, name: str) -> bool: + """Check whether a named remote exists.""" + result = _run(["remote"], cwd=repo) + return name in result.stdout.splitlines() + + +def mirror_update(repo: Path) -> None: + """Fetch all remotes in a bare mirror repository. + + Equivalent to ``git remote update`` inside the bare repo. + """ + _run(["remote", "update"], cwd=repo) + logger.debug("Updated remotes in %s", repo) + + +def fetch(repo: Path, remote: str = "origin") -> None: + """Fetch from a single remote.""" + _run(["fetch", remote], cwd=repo) + logger.debug("fetched %s in %s", remote, repo) + + +def show_ref(repo: Path) -> str: + """Return the raw output of ``git show-ref`` (all refs + SHAs). + + Returns an empty string if the repo has no refs. + """ + try: + result = _run(["show-ref"], cwd=repo) + return result.stdout + except GitError: + return "" + + +def ls_remote(repo: Path, remote: str) -> str: + """Return the raw output of ``git ls-remote ``. + + Returns an empty string if the remote has no refs or on error. + """ + try: + result = _run(["ls-remote", remote], cwd=repo) + return result.stdout + except GitError: + return "" + + +def mirror_push(repo: Path, remote: str) -> None: + """Push the full mirror to a remote. + + Equivalent to ``git push --mirror ``. + """ + _run(["push", "--mirror", remote], cwd=repo) + logger.info("Pushed mirror to %s from %s", remote, repo) + + +def read_file( + repo: Path, + filepath: str, + ref: str = "HEAD", +) -> Optional[str]: + """Extract a file's contents from a bare repo without checkout. + + Returns the file content as a string, or None if the file does + not exist at the given ref. + """ + try: + result = _run( + ["show", f"{ref}:{filepath}"], + cwd=repo, + capture_stdout=True, + ) + return result.stdout + except GitError: + return None + + +# ------------------------------------------------------------------- +# Ref / tag primitives +# ------------------------------------------------------------------- + +def list_tags(repo: Path) -> List[str]: + """List all tags in a repository.""" + result = _run(["tag", "-l"], cwd=repo) + return [t for t in result.stdout.splitlines() if t] + + +def resolve_ref(repo: Path, ref: str) -> str: + """Resolve a ref to a full SHA. + + Raises GitError if the ref cannot be resolved. + """ + result = _run( + ["rev-parse", ref], cwd=repo, capture_stdout=True, + ) + return result.stdout.strip() + + +def head_ref(repo: Path) -> str: + """Return the full SHA of HEAD.""" + return resolve_ref(repo, "HEAD") + + +# ------------------------------------------------------------------- +# Pull-through bare clone cache +# ------------------------------------------------------------------- + +def bare_path_for_url(url: str, cache_dir: Path) -> Path: + """Derive a cache path from a clone URL. + + Strips scheme/host, keeps the path component, appends ``.git``. + + Examples:: + + https://github.com/h5p/h5p-multi-choice + → cache_dir / h5p / h5p-multi-choice.git + git@github.com:h5p/h5p-multi-choice.git + → cache_dir / h5p / h5p-multi-choice.git + """ + # Handle SCP-style URLs (git@host:path) + if ":" in url and "//" not in url: + path_part = url.split(":", 1)[1] + else: + # Strip scheme + host + from urllib.parse import urlparse + parsed = urlparse(url) + path_part = parsed.path.lstrip("/") + + # Strip trailing .git if present, then re-add it + if path_part.endswith(".git"): + path_part = path_part[:-4] + + return cache_dir / (path_part + ".git") + + +def ensure_bare_clone(url: str, cache_dir: Path) -> Path: + """Ensure a bare mirror clone exists in *cache_dir*. + + If the bare repo already exists, fetches updates via + ``mirror_update``. Otherwise, creates a new mirror clone. + Returns the path to the bare repo. + """ + bare_path = bare_path_for_url(url, cache_dir) + if bare_path.exists(): + mirror_update(bare_path) + logger.debug("Updated existing cache %s", bare_path) + else: + bare_path.parent.mkdir(parents=True, exist_ok=True) + mirror_clone(url, bare_path) + logger.info("Cached new bare clone %s", bare_path) + return bare_path + + +# ------------------------------------------------------------------- +# Submodule operations +# ------------------------------------------------------------------- + +def has_submodule(repo: Path, path: str) -> bool: + """Check whether a submodule is registered at *path*. + + Reads ``.gitmodules`` to determine whether the submodule exists. + *path* is resolved relative to *repo*, then compared against + the repository root so the check works when *repo* is a + subdirectory of the actual git working tree. + Returns False if ``.gitmodules`` does not exist. + """ + try: + toplevel = Path( + _run( + ["rev-parse", "--show-toplevel"], cwd=repo, + ).stdout.strip() + ) + except GitError: + return False + gitmodules = toplevel / ".gitmodules" + if not gitmodules.is_file(): + return False + # Resolve the full path relative to the repo root + full_path = (repo / path).resolve() + try: + rel_path = str(full_path.relative_to(toplevel.resolve())) + except ValueError: + return False + try: + result = _run( + ["config", "--file", str(gitmodules), + "--get-regexp", r"submodule\..*\.path"], + cwd=toplevel, + ) + except GitError: + return False + for line in result.stdout.splitlines(): + parts = line.split(None, 1) + if len(parts) == 2 and parts[1] == rel_path: + return True + return False + + +def submodule_add(repo: Path, url: str, path: str) -> None: + """Add a git submodule at *path* pointing to *url*. + + Equivalent to ``git submodule add `` inside *repo*. + """ + _run(["submodule", "add", url, path], cwd=repo) + logger.info("Added submodule %s → %s", url, path) + + +def submodule_update(repo: Path, path: str) -> None: + """Fetch and update a submodule to the latest remote HEAD. + + Enters the submodule directory, fetches origin, and checks out + the latest commit on the remote default branch. + """ + sub_path = repo / path + _run(["fetch", "origin"], cwd=sub_path) + # Determine default branch from remote HEAD + result = _run( + ["symbolic-ref", "refs/remotes/origin/HEAD", + "--short"], + cwd=sub_path, + ) + default_branch = result.stdout.strip() + _run(["checkout", default_branch], cwd=sub_path) + logger.info("Updated submodule %s to %s", path, default_branch) + + +def submodule_checkout(repo: Path, path: str, ref: str) -> None: + """Fetch and checkout a specific ref in a submodule.""" + sub_path = repo / path + _run(["fetch", "origin"], cwd=sub_path) + _run(["checkout", ref], cwd=sub_path) + logger.info("Checked out submodule %s at %s", path, ref) diff --git a/tests/integration/byteb4rb1e/testing/pytest/test_.py b/tests/integration/byteb4rb1e/testing/pytest/test_.py new file mode 100644 index 0000000..8141015 --- /dev/null +++ b/tests/integration/byteb4rb1e/testing/pytest/test_.py @@ -0,0 +1,33 @@ +import os +from pathlib import Path + +import pytest + +pytestmark = pytest.mark.pytest + +from byteb4rb1e.testing.pytest import get_current_test +from byteb4rb1e.testing.pytest.decorators import run_in_subprocess_once + + +class Test_get_current_test: + """ + """ + + def test_default(self): + """ + """ + os.environ['PYTEST_CURRENT_TEST'] = 'foo::bar (something)' + + result = get_current_test() + + assert isinstance(result[0], Path) + assert str(result[0].name) == 'foo' + + assert result[1] == 'bar' + + def test_invalid(self): + """ + """ + del os.environ['PYTEST_CURRENT_TEST'] + with pytest.raises(RuntimeError): + get_current_test() diff --git a/tests/integration/byteb4rb1e/testing/pytest/test_decorators.py b/tests/integration/byteb4rb1e/testing/pytest/test_decorators.py new file mode 100644 index 0000000..c906bef --- /dev/null +++ b/tests/integration/byteb4rb1e/testing/pytest/test_decorators.py @@ -0,0 +1,21 @@ +from pathlib import Path + +import pytest + +pytestmark = pytest.mark.pytest + +from byteb4rb1e.testing.pytest.decorators import run_in_subprocess_once + + +@run_in_subprocess_once() +def test_run_in_subprocess_once(tmp_path): + marker = tmp_path / "executed_in_subprocess.txt" + + if marker.exists(): + raise AssertionError("Marker file exists before test logic ran (shouldn't happen in parent process)") + + # Create proof of execution + marker.write_text("Subprocess was here.") + + # Now assert it + assert marker.exists() diff --git a/tests/integration/byteb4rb1e/testing/pytest/test_fixtures.py b/tests/integration/byteb4rb1e/testing/pytest/test_fixtures.py new file mode 100644 index 0000000..a08851d --- /dev/null +++ b/tests/integration/byteb4rb1e/testing/pytest/test_fixtures.py @@ -0,0 +1,38 @@ +from pathlib import Path +import importlib.resources + +import pytest + +pytestmark = pytest.mark.pytest + +from byteb4rb1e.testing.pytest.decorators import run_in_subprocess_once +from byteb4rb1e.testing.pytest.fixtures import ( + current_test, + mock_system_site_package_dir +) + + +def test_current_test(current_test): + """ + """ + suite_path, case_name = current_test + + assert str(Path(__file__)) == str(suite_path) + assert case_name == "test_current_test" + + +@run_in_subprocess_once() +def test_mock_system_site_package_dir(mock_system_site_package_dir): + """ + """ + dummy_data = 'Hello' + + pkgdir = mock_system_site_package_dir('foobarpkg') + + (pkgdir / 'data.txt').write_text(dummy_data) + + assert (pkgdir / '__init__.py').exists() + + result = next(importlib.resources.files('foobarpkg').glob('data.txt')).read_text() + + assert result == dummy_data diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py new file mode 100644 index 0000000..7c7aa51 --- /dev/null +++ b/tests/integration/conftest.py @@ -0,0 +1,5 @@ +def pytest_configure(config): + # register an additional marker + config.addinivalue_line( + "markers", "pytest: test pytest integration" + ) diff --git a/tests/unit/byteb4rb1e/utils/__init__.py b/tests/unit/byteb4rb1e/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/unit/byteb4rb1e_utils/collections/test_circular_buffer.py b/tests/unit/byteb4rb1e/utils/collections/test_circular_buffer.py similarity index 98% rename from tests/unit/byteb4rb1e_utils/collections/test_circular_buffer.py rename to tests/unit/byteb4rb1e/utils/collections/test_circular_buffer.py index aeb0934..1baf601 100644 --- a/tests/unit/byteb4rb1e_utils/collections/test_circular_buffer.py +++ b/tests/unit/byteb4rb1e/utils/collections/test_circular_buffer.py @@ -1,6 +1,6 @@ import unittest -from byteb4rb1e_utils.collections import CircularBuffer +from byteb4rb1e.utils.collections import CircularBuffer class test_init(unittest.TestCase): """CircularBuffer.__init__()""" diff --git a/tests/unit/byteb4rb1e_utils/io/test_chunksio.py b/tests/unit/byteb4rb1e/utils/io/test_chunksio.py similarity index 99% rename from tests/unit/byteb4rb1e_utils/io/test_chunksio.py rename to tests/unit/byteb4rb1e/utils/io/test_chunksio.py index 4218d69..a27f20f 100644 --- a/tests/unit/byteb4rb1e_utils/io/test_chunksio.py +++ b/tests/unit/byteb4rb1e/utils/io/test_chunksio.py @@ -1,7 +1,7 @@ from io import BytesIO, IOBase import unittest -from byteb4rb1e_utils.io import ChunksIO +from byteb4rb1e.utils.io import ChunksIO class TestGetChunkSize(unittest.TestCase): diff --git a/tests/unit/byteb4rb1e/utils/string/test_rolling_hash.py b/tests/unit/byteb4rb1e/utils/string/test_rolling_hash.py new file mode 100644 index 0000000..590f527 --- /dev/null +++ b/tests/unit/byteb4rb1e/utils/string/test_rolling_hash.py @@ -0,0 +1,61 @@ +import unittest + +from byteb4rb1e.utils.string import RollingHash + +class test_compute_initial_hash(unittest.TestCase): + """RollingHash.compute_initial_hash() + + i calculated the hashes by hand, as a basis for this test case. Hopefully + there's no logical flaw... + """ + + def test_default(self): + """computation of hash""" + result = RollingHash.compute_initial_hash( + b'abcdefg', + base = 31, + mod = 10**9 + 7 + ) + + self.assertEqual(result, 988021244) + +class test___init__(unittest.TestCase): + """RollingHash.__init__() + + Make sure the class instance is initialized correctly + + I calculated the hashes by hand, as a basis for this test case. Hopefully + there's no logical flaw... + """ + + def test_default(self): + """computation of initial hash and highest base factor""" + instance = RollingHash(b'abcdefg') + + self.assertEqual(instance._hash, 988021244) + self.assertEqual(instance._hbase_factor, 887503681) + + def test_defaults_override(self): + """override of defaults""" + instance = RollingHash( + b'abcdefg', + base = 9, + mod = 4 + ) + + self.assertEqual(instance._mod, 4) + self.assertEqual(instance._base, 9) + + +class test_roll(unittest.TestCase): + """RollingHash.roll()""" + def test_rolling_hash(self): + base=31 + mod=10**9 + 7 + + rh = RollingHash(b"foobar", base=base, mod=mod) + rolled_hash = rh.roll(ord("f"), ord("n")) + + control_hash = RollingHash.compute_initial_hash(b"oobarn", base, mod) + + self.assertEqual(rolled_hash, control_hash) diff --git a/tests/unit/byteb4rb1e/utils/urllib/test_request.py b/tests/unit/byteb4rb1e/utils/urllib/test_request.py new file mode 100644 index 0000000..468751d --- /dev/null +++ b/tests/unit/byteb4rb1e/utils/urllib/test_request.py @@ -0,0 +1,93 @@ +import os.path +import sys +import urllib.request + +import pytest + +from byteb4rb1e.testing.pytest.decorators import run_in_subprocess_once +from byteb4rb1e.testing.pytest.fixtures import mock_system_site_package_dir +from byteb4rb1e.utils.urllib.request import PkgHandler + + +class TestPkgHandler: + """ + """ + @run_in_subprocess_once() + def test_text(self, mock_system_site_package_dir): + """ + """ + _opener: urllib.request.OpenerDirector = urllib.request.build_opener( + PkgHandler() + ) + + dummy_data = 'Hello' + + pkg_dir = mock_system_site_package_dir('foobarpkg') + (pkg_dir / 'data.txt').write_text(dummy_data) + + result = _opener.open('pkg://foobarpkg/data.txt').readline() + + assert isinstance(result, str) + assert result == dummy_data + + + @run_in_subprocess_once() + def test_bytes(self, mock_system_site_package_dir): + """ + """ + _opener: urllib.request.OpenerDirector = urllib.request.build_opener( + PkgHandler() + ) + + dummy_data = b'foobar123' + + pkg_dir = mock_system_site_package_dir('foobarpkg') + (pkg_dir / 'data.bin').write_bytes(dummy_data) + + result = _opener.open('pkg://foobarpkg/data.bin').readline() + + assert isinstance(result, bytes) + assert result == dummy_data + + + @run_in_subprocess_once() + def test_subdir(self, mock_system_site_package_dir): + """ + """ + _opener: urllib.request.OpenerDirector = urllib.request.build_opener( + PkgHandler() + ) + + dummy_data = 'foobar123' + + pkg_dir = mock_system_site_package_dir('foobarpkg') + + dummy_file = (pkg_dir / 'foo' / 'bar' / 'data.txt') + + dummy_file.parent.mkdir(parents=True) + dummy_file.write_text(dummy_data) + + result = _opener.open('pkg://foobarpkg/foo/bar/data.txt').readline() + + assert result == dummy_data + + + @run_in_subprocess_once() + def test_nested_module(self, mock_system_site_package_dir): + """ + """ + _opener: urllib.request.OpenerDirector = urllib.request.build_opener( + PkgHandler() + ) + + dummy_data = 'foobar123' + + pkg_dir = mock_system_site_package_dir('foo.bar.pkg') + dummy_file = (pkg_dir / 'dummy' / 'data.txt') + + dummy_file.parent.mkdir(parents=True) + dummy_file.write_text(dummy_data) + + result = _opener.open('pkg://foo.bar.pkg/dummy/data.txt').readline() + + assert result == dummy_data diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..d4a94e1 --- /dev/null +++ b/tox.ini @@ -0,0 +1,54 @@ +[tox] +requires = + tox>=4.19 +env_list = + unit-py3{9-13} + integration-py3{9-13}-pytest8 + lint + format + +[testenv] +deps = + . + +[testenv:lint] +description = run type check on code base +labels = static +deps = + mypy +commands = + mypy src tests --junit-xml test-reports/{env_name}.xml + +[testenv:audit] +description = run type check on code base +labels = audit +deps = + pip-audit +commands = + pip-audit . + +[testenv:format] +description = run type check on code base +labels = static +deps = + autopep8 +commands = + autopep8 --diff --exit-code src tests + +[testenv:unit-py3{9-13}] +description = run type check on code base +labels = unit +deps = + {[testenv]deps} + pytest +commands = + pytest tests/unit --junitxml=test-reports/{env_name}.xml + +[testenv:integration-py3{9-13}-pytest8] +description = run pytest integration tests +labels = integration +deps = + {[testenv]deps} + pytest8: pytest>=8.0,<=9.0 +commands = + pytest tests/integration -m pytest --junitxml=test-reports/{env_name}.xml