diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6f017fe..843a6e0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,143 +1,117 @@ repos: - - repo: https://github.com/ambv/black - rev: 24.8.0 +- repo: https://github.com/ambv/black + rev: 25.12.0 hooks: - - id: black - name: "Format: Black" - args: ["--exclude", "test/resources", "--exclude", ".venv", "." ] - pass_filenames: false - - repo: https://github.com/pycqa/isort - rev: 5.13.2 + - id: black + name: "Format: Black" + args: ["--exclude", "test/resources", "--exclude", ".venv", "."] + pass_filenames: false +- repo: https://github.com/pycqa/isort + rev: 7.0.0 hooks: - - id: isort - name: "Format: ISort" - - repo: https://github.com/scop/pre-commit-shfmt - rev: v3.10.0-1 + - id: isort + name: "Format: ISort" +- repo: https://github.com/scop/pre-commit-shfmt + rev: v3.12.0-2 hooks: - - id: shfmt - name: "Format: ShFmt" - - repo: local + - id: shfmt + name: "Format: ShFmt" +- repo: local hooks: - - id: verify-install-requirements - name: "Scan: Verify Install Requirements Match" - language: system - entry: pipenv run python utils/verify_install_requirements.py - pass_filenames: false - - repo: https://github.com/pycqa/flake8 - rev: '7.1.1' + - id: verify-install-requirements + name: "Scan: Verify Install Requirements Match" + language: system + entry: pipenv run python utils/verify_install_requirements.py + pass_filenames: false +- repo: https://github.com/pycqa/flake8 + rev: '7.3.0' hooks: - - id: flake8 - name: "Scan: Flake8" - args: ["-j","4", "--exclude", "dist,build,.venv,test/resources", "."] - additional_dependencies: ["flake8-bugbear==24.8.19", "flake8-bandit==4.1.1"] - pass_filenames: false - - repo: https://github.com/PyCQA/bandit - rev: 1.8.0 + - id: flake8 + name: "Scan: Flake8" + args: ["-j", "4", "--exclude", "dist,build,.venv,test/resources", "."] + additional_dependencies: ["flake8-bugbear==24.8.19", "flake8-bandit==4.1.1"] + pass_filenames: false +- repo: https://github.com/PyCQA/bandit + rev: 1.9.2 hooks: - - id: bandit - name: "Scan: Bandit" - args: [--configfile,.bandit.yaml,-q,-r,"application_properties"] - pass_filenames: false - - repo: local + - id: bandit + name: "Scan: Bandit" + args: [--configfile, .bandit.yaml, -q, -r, "application_properties"] + pass_filenames: false +- repo: local hooks: - - id: pylint - name: "Scan: PyLint" - entry: pylint - language: system - types: [python] - require_serial: true - args: - [ - "-j=1", - "--recursive=y", - "-rn", # Only display messages - "-sn", # Don't display the score - "application_properties" - ] - pass_filenames: false - - repo: local + - id: pylint + name: "Scan: PyLint" + entry: pylint + language: system + types: [python] + require_serial: true + args: ["-j=1", "--recursive=y", "-rn", "-sn", "application_properties"] + pass_filenames: false +- repo: local hooks: - - id: pylint - name: "Scan: PyLint (test)" - entry: pylint - language: system - types: [python] - require_serial: true - args: - [ - "-j=1", - "--ignore", - "test/resources", - "--recursive=y", - "-rn", # Only display messages - "-sn", # Don't display the score - "test" - ] - pass_filenames: false - - repo: local + - id: pylint + name: "Scan: PyLint (test)" + entry: pylint + language: system + types: [python] + require_serial: true + args: ["-j=1", "--ignore", "test/resources", "--recursive=y", "-rn", "-sn", + "test"] + pass_filenames: false +- repo: local hooks: - - id: pylint - name: "Scan: PyLint (utils)" - entry: pylint - language: system - types: [python] - require_serial: true - args: - [ - "-j=1", - "--recursive=y", - "-rn", # Only display messages - "-sn", # Don't display the score - "utils" - ] - pass_filenames: false - - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.13.0 + - id: pylint + name: "Scan: PyLint (utils)" + entry: pylint + language: system + types: [python] + require_serial: true + args: ["-j=1", "--recursive=y", "-rn", "-sn", "utils"] + pass_filenames: false +- repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.19.1 hooks: - - id: mypy - name: "Scan: MyPy" - args: [--warn-return-any, --strict, application_properties ] - additional_dependencies: [ - tomli, types-PyYAML, pytest, pyjson5 - ] - pass_filenames: false - - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.13.0 + - id: mypy + name: "Scan: MyPy" + args: [--warn-return-any, --strict, application_properties ] + additional_dependencies: [ tomli, types-PyYAML, pytest, pyjson5 ] + pass_filenames: false +- repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.19.1 hooks: - - id: mypy - name: "Scan: MyPy (test)" - args: [--warn-return-any, --exclude, test/resources, --strict, test ] - additional_dependencies: [ - tomli, types-PyYAML, pytest, pyjson5 - ] - pass_filenames: false - - repo: https://github.com/jackdewinter/pymarkdown - rev: v0.9.27 + - id: mypy + name: "Scan: MyPy (test)" + args: [--warn-return-any, --exclude, test/resources, --strict, test ] + additional_dependencies: [ tomli, types-PyYAML, pytest, pyjson5 ] + pass_filenames: false +- repo: https://github.com/jackdewinter/pymarkdown + rev: v0.9.34 hooks: - - id: pymarkdown - name: "Scan: PyMarkdown (Old Documentation)" - pass_filenames: false - args: - - --config - - clean.json - - scan - - changelog.md - - README.md - - ./docs - - repo: https://github.com/jackdewinter/pymarkdown - rev: v0.9.27 + - id: pymarkdown + name: "Scan: PyMarkdown (Old Documentation)" + pass_filenames: false + args: + - --config + - clean.json + - scan + - changelog.md + - README.md + - ./docs +- repo: https://github.com/jackdewinter/pymarkdown + rev: v0.9.34 hooks: - - id: pymarkdown - name: "Scan: PyMarkdown (New Documentation)" - pass_filenames: false - args: - - --config - - newdocs/clean.json - - scan - - ./newdocs/src - - repo: https://github.com/koalaman/shellcheck-precommit - rev: v0.10.0 + - id: pymarkdown + name: "Scan: PyMarkdown (New Documentation)" + pass_filenames: false + args: + - --config + - newdocs/clean.json + - scan + - ./newdocs/src +- repo: https://github.com/koalaman/shellcheck-precommit + rev: v0.11.0 hooks: - - id: shellcheck - name: "Scan: Shellcheck" - args: ["-x", "-o","require-variable-braces"] + - id: shellcheck + name: "Scan: Shellcheck" + args: ["-x", "-o", "require-variable-braces"] diff --git a/.sourcery.yaml b/.sourcery.yaml index 22a863f..b71aa99 100644 --- a/.sourcery.yaml +++ b/.sourcery.yaml @@ -33,7 +33,7 @@ rule_settings: - refactoring - suggestion - comment - python_version: '3.9' # A string specifying the lowest Python version your project supports. Sourcery will not suggest refactorings requiring a higher Python version. + python_version: '3.10' # A string specifying the lowest Python version your project supports. Sourcery will not suggest refactorings requiring a higher Python version. # rules: # A list of custom rules Sourcery will include in its analysis. # - id: no-print-statements diff --git a/Pipfile b/Pipfile index c7f7356..23a332c 100644 --- a/Pipfile +++ b/Pipfile @@ -4,28 +4,32 @@ verify_ssl = true name = "pypi" [dev-packages] -build = "==1.3.0" +setuptools = "==80.9.0" +sourcery = "==1.40.0" +build = "==1.4.0" cookieslicer = "==0.1.5" -coverage = "==7.13.0" -importlib-metadata = "==8.7.0" +coverage = "==7.13.1" +importlib-metadata = "==8.7.1" mkdocs = "==1.6.1" -mkdocstrings = "0.29.1" -mkdocstrings-python = "1.16.12" -pre-commit = "==3.3.3" +mkdocstrings = "==1.0.0" +mkdocstrings-python = "==2.0.1" +pip-check-updates = "==0.28.0" +pre-commit = "==4.5.1" +pre-commit-update = "==0.9.0" project-summarizer = "==0.6.0" py = "==1.11.0" -pylint = "==3.3.7" +pylint = "==4.0.4" pylint-utils = "==0.6.0" pyroma = "==5.0.1" -pytest = "==8.4.0" +pytest = "==9.0.2" pytest-console-scripts = "==1.4.1" pytest-cov = "==7.0.0" pytest-html = "==4.1.1" pytest-timeout = "==2.4.0" pytest-xdist = "==3.8.0" -setuptools = "==80.9.0" -sourcery = "==1.35.0" -twine = "==6.1.0" +pyyaml = "==6.0.3" +tomli = "==2.4.0" +twine = "==6.2.0" [packages] typing-extensions = ">=4.5.0" diff --git a/Pipfile.lock b/Pipfile.lock index fd55b7c..ecdd369 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "e014c435f44b96c942ace5413b1ebef60e006bce36efa923f7268fe314577c34" + "sha256": "1e9ccc77142560239adaaa6606460ffb7ad91727fdd261b693c1a4dcc002bed1" }, "pipfile-spec": 6, "requires": { @@ -265,52 +265,57 @@ }, "tomli": { "hashes": [ - "sha256:00b5f5d95bbfc7d12f91ad8c593a1659b6387b43f054104cda404be6bda62456", - "sha256:0a154a9ae14bfcf5d8917a59b51ffd5a3ac1fd149b71b47a3a104ca4edcfa845", - "sha256:0c95ca56fbe89e065c6ead5b593ee64b84a26fca063b5d71a1122bf26e533999", - "sha256:0eea8cc5c5e9f89c9b90c4896a8deefc74f518db5927d0e0e8d4a80953d774d0", - "sha256:1cb4ed918939151a03f33d4242ccd0aa5f11b3547d0cf30f7c74a408a5b99878", - "sha256:4021923f97266babc6ccab9f5068642a0095faa0a51a246a6a02fccbb3514eaf", - "sha256:4c2ef0244c75aba9355561272009d934953817c49f47d768070c3c94355c2aa3", - "sha256:4dc4ce8483a5d429ab602f111a93a6ab1ed425eae3122032db7e9acf449451be", - "sha256:4f195fe57ecceac95a66a75ac24d9d5fbc98ef0962e09b2eddec5d39375aae52", - "sha256:5192f562738228945d7b13d4930baffda67b69425a7f0da96d360b0a3888136b", - "sha256:5e01decd096b1530d97d5d85cb4dff4af2d8347bd35686654a004f8dea20fc67", - "sha256:64be704a875d2a59753d80ee8a533c3fe183e3f06807ff7dc2232938ccb01549", - "sha256:70a251f8d4ba2d9ac2542eecf008b3c8a9fc5c3f9f02c56a9d7952612be2fdba", - "sha256:73ee0b47d4dad1c5e996e3cd33b8a76a50167ae5f96a2607cbe8cc773506ab22", - "sha256:74bf8464ff93e413514fefd2be591c3b0b23231a77f901db1eb30d6f712fc42c", - "sha256:792262b94d5d0a466afb5bc63c7daa9d75520110971ee269152083270998316f", - "sha256:7b0882799624980785240ab732537fcfc372601015c00f7fc367c55308c186f6", - "sha256:883b1c0d6398a6a9d29b508c331fa56adbcdff647f6ace4dfca0f50e90dfd0ba", - "sha256:88bd15eb972f3664f5ed4b57c1634a97153b4bac4479dcb6a495f41921eb7f45", - "sha256:8a35dd0e643bb2610f156cca8db95d213a90015c11fee76c946aa62b7ae7e02f", - "sha256:940d56ee0410fa17ee1f12b817b37a4d4e4dc4d27340863cc67236c74f582e77", - "sha256:97d5eec30149fd3294270e889b4234023f2c69747e555a27bd708828353ab606", - "sha256:a0e285d2649b78c0d9027570d4da3425bdb49830a6156121360b3f8511ea3441", - "sha256:a1f7f282fe248311650081faafa5f4732bdbfef5d45fe3f2e702fbc6f2d496e0", - "sha256:a4ea38c40145a357d513bffad0ed869f13c1773716cf71ccaa83b0fa0cc4e42f", - "sha256:a56212bdcce682e56b0aaf79e869ba5d15a6163f88d5451cbde388d48b13f530", - "sha256:ad805ea85eda330dbad64c7ea7a4556259665bdf9d2672f5dccc740eb9d3ca05", - "sha256:b273fcbd7fc64dc3600c098e39136522650c49bca95df2d11cf3b626422392c8", - "sha256:b5870b50c9db823c595983571d1296a6ff3e1b88f734a4c8f6fc6188397de005", - "sha256:b74a0e59ec5d15127acdabd75ea17726ac4c5178ae51b85bfe39c4f8a278e879", - "sha256:be71c93a63d738597996be9528f4abe628d1adf5e6eb11607bc8fe1a510b5dae", - "sha256:c22a8bf253bacc0cf11f35ad9808b6cb75ada2631c2d97c971122583b129afbc", - "sha256:c4665508bcbac83a31ff8ab08f424b665200c0e1e645d2bd9ab3d3e557b6185b", - "sha256:c5f3ffd1e098dfc032d4d3af5c0ac64f6d286d98bc148698356847b80fa4de1b", - "sha256:cebc6fe843e0733ee827a282aca4999b596241195f43b4cc371d64fc6639da9e", - "sha256:d1381caf13ab9f300e30dd8feadb3de072aeb86f1d34a8569453ff32a7dea4bf", - "sha256:d7d86942e56ded512a594786a5ba0a5e521d02529b3826e7761a05138341a2ac", - "sha256:e31d432427dcbf4d86958c184b9bfd1e96b5b71f8eb17e6d02531f434fd335b8", - "sha256:e95b1af3c5b07d9e643909b5abbec77cd9f1217e6d0bca72b0234736b9fb1f1b", - "sha256:f85209946d1fe94416debbb88d00eb92ce9cd5266775424ff81bc959e001acaf", - "sha256:feb0dacc61170ed7ab602d3d972a58f14ee3ee60494292d384649a3dc38ef463", - "sha256:ff72b71b5d10d22ecb084d345fc26f42b5143c5533db5e2eaba7d2d335358876" + "sha256:0408e3de5ec77cc7f81960c362543cbbd91ef883e3138e81b729fc3eea5b9729", + "sha256:0dc56fef0e2c1c470aeac5b6ca8cc7b640bb93e92d9803ddaf9ea03e198f5b0b", + "sha256:0e0fe8a0b8312acf3a88077a0802565cb09ee34107813bba1c7cd591fa6cfc8d", + "sha256:0f2e3955efea4d1cfbcb87bc321e00dc08d2bcb737fd1d5e398af111d86db5df", + "sha256:133e93646ec4300d651839d382d63edff11d8978be23da4cc106f5a18b7d0576", + "sha256:1b168f2731796b045128c45982d3a4874057626da0e2ef1fdd722848b741361d", + "sha256:1c8a885b370751837c029ef9bc014f27d80840e48bac415f3412e6593bbc18c1", + "sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a", + "sha256:1fb2945cbe303b1419e2706e711b7113da57b7db31ee378d08712d678a34e51e", + "sha256:20cedb4ee43278bc4f2fee6cb50daec836959aadaf948db5172e776dd3d993fc", + "sha256:20ffd184fb1df76a66e34bd1b36b4a4641bd2b82954befa32fe8163e79f1a702", + "sha256:26ab906a1eb794cd4e103691daa23d95c6919cc2fa9160000ac02370cc9dd3f6", + "sha256:2add28aacc7425117ff6364fe9e06a183bb0251b03f986df0e78e974047571fd", + "sha256:2b1e3b80e1d5e52e40e9b924ec43d81570f0e7d09d11081b797bc4692765a3d4", + "sha256:31d556d079d72db7c584c0627ff3a24c5d3fb4f730221d3444f3efb1b2514776", + "sha256:36b9d05b51e65b254ea6c2585b59d2c4cb91c8a3d91d0ed0f17591a29aaea54a", + "sha256:39b0b5d1b6dd03684b3fb276407ebed7090bbec989fa55838c98560c01113b66", + "sha256:3cf226acb51d8f1c394c1b310e0e0e61fecdd7adcb78d01e294ac297dd2e7f87", + "sha256:3d895d56bd3f82ddd6faaff993c275efc2ff38e52322ea264122d72729dca2b2", + "sha256:413540dce94673591859c4c6f794dfeaa845e98bf35d72ed59636f869ef9f86f", + "sha256:43e685b9b2341681907759cf3a04e14d7104b3580f808cfde1dfdb60ada85475", + "sha256:4cbcb367d44a1f0c2be408758b43e1ffb5308abe0ea222897d6bfc8e8281ef2f", + "sha256:551e321c6ba03b55676970b47cb1b73f14a0a4dce6a3e1a9458fd6d921d72e95", + "sha256:5572e41282d5268eb09a697c89a7bee84fae66511f87533a6f88bd2f7b652da9", + "sha256:5aa48d7c2356055feef06a43611fc401a07337d5b006be13a30f6c58f869e3c3", + "sha256:5b5807f3999fb66776dbce568cc9a828544244a8eb84b84b9bafc080c99597b9", + "sha256:5e3f639a7a8f10069d0e15408c0b96a2a828cfdec6fca05296ebcdcc28ca7c76", + "sha256:685306e2cc7da35be4ee914fd34ab801a6acacb061b6a7abca922aaf9ad368da", + "sha256:75c2f8bbddf170e8effc98f5e9084a8751f8174ea6ccf4fca5398436e0320bc8", + "sha256:7b438885858efd5be02a9a133caf5812b8776ee0c969fea02c45e8e3f296ba51", + "sha256:7d49c66a7d5e56ac959cb6fc583aff0651094ec071ba9ad43df785abc2320d86", + "sha256:7d6d9a4aee98fac3eab4952ad1d73aee87359452d1c086b5ceb43ed02ddb16b8", + "sha256:84d081fbc252d1b6a982e1870660e7330fb8f90f676f6e78b052ad4e64714bf0", + "sha256:8768715ffc41f0008abe25d808c20c3d990f42b6e2e58305d5da280ae7d1fa3b", + "sha256:920b1de295e72887bafa3ad9f7a792f811847d57ea6b1215154030cf131f16b1", + "sha256:9a08144fa4cba33db5255f9b74f0b89888622109bd2776148f2597447f92a94e", + "sha256:a26d7ff68dfdb9f87a016ecfd1e1c2bacbe3108f4e0f8bcd2228ef9a766c787d", + "sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c", + "sha256:b5ef256a3fd497d4973c11bf142e9ed78b150d36f5773f1ca6088c230ffc5867", + "sha256:b6c78bdf37764092d369722d9946cb65b8767bfa4110f902a1b2542d8d173c8a", + "sha256:bbb1b10aa643d973366dc2cb1ad94f99c1726a02343d43cbc011edbfac579e7c", + "sha256:c084ad935abe686bd9c898e62a02a19abfc9760b5a79bc29644463eaf2840cb0", + "sha256:c73add4bb52a206fd0c0723432db123c0c75c280cbd67174dd9d2db228ebb1b4", + "sha256:cae9c19ed12d4e8f3ebf46d1a75090e4c0dc16271c5bce1c833ac168f08fb614", + "sha256:d20b797a5c1ad80c516e41bc1fb0443ddb5006e9aaa7bda2d71978346aeb9132", + "sha256:d3d1654e11d724760cdb37a3d7691f0be9db5fbdaef59c9f532aabf87006dbaa", + "sha256:d878f2a6707cc9d53a1be1414bbb419e629c3d6e67f69230217bb663e76b5087" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==2.3.0" + "version": "==2.4.0" }, "typing-extensions": { "hashes": [ @@ -333,11 +338,19 @@ }, "astroid": { "hashes": [ - "sha256:1e5a5011af2920c7c67a53f65d536d65bfa7116feeaf2354d8b94f29573bb0ce", - "sha256:54c760ae8322ece1abd213057c4b5bba7c49818853fc901ef09719a60dbf9dec" + "sha256:08d1de40d251cc3dc4a7a12726721d475ac189e4e583d596ece7422bc176bda3", + "sha256:864a0a34af1bd70e1049ba1e61cee843a7252c826d97825fcee9b2fcbd9e1b14" ], - "markers": "python_full_version >= '3.9.0'", - "version": "==3.3.11" + "markers": "python_full_version >= '3.10.0'", + "version": "==4.0.3" + }, + "beautifulsoup4": { + "hashes": [ + "sha256:0918bfe44902e6ad8d57732ba310582e98da931428d231a5ecb9e7c703a735bb", + "sha256:6292b1c5186d356bba669ef9f7f051757099565ad9ada5dd630bd9de5fa7fb86" + ], + "markers": "python_full_version >= '3.7.0'", + "version": "==4.14.3" }, "binaryornot": { "hashes": [ @@ -348,20 +361,20 @@ }, "build": { "hashes": [ - "sha256:698edd0ea270bde950f53aed21f3a0135672206f3911e0176261a31e0e07b397", - "sha256:7145f0b5061ba90a1500d60bd1b13ca0a8a4cebdd0cc16ed8adf1c0e739f43b4" + "sha256:6a07c1b8eb6f2b311b96fcbdbce5dab5fe637ffda0fd83c9cac622e927501596", + "sha256:f1b91b925aa322be454f8330c6fb48b465da993d1e7e7e6fa35027ec49f3c936" ], "index": "pypi", "markers": "python_version >= '3.9'", - "version": "==1.3.0" + "version": "==1.4.0" }, "certifi": { "hashes": [ - "sha256:97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b", - "sha256:d8ab5478f2ecd78af242878415affce761ca6bc54a22a27e026d7c25357c3316" + "sha256:9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c", + "sha256:ac726dd470482006e014ad384921ed6438c457018f4b3d204aea4281258b2120" ], "markers": "python_version >= '3.7'", - "version": "==2025.11.12" + "version": "==2026.1.4" }, "cfgv": { "hashes": [ @@ -543,102 +556,102 @@ "toml" ], "hashes": [ - "sha256:0018f73dfb4301a89292c73be6ba5f58722ff79f51593352759c1790ded1cabe", - "sha256:00c3d22cf6fb1cf3bf662aaaa4e563be8243a5ed2630339069799835a9cc7f9b", - "sha256:02d9fb9eccd48f6843c98a37bd6817462f130b86da8660461e8f5e54d4c06070", - "sha256:0602f701057c6823e5db1b74530ce85f17c3c5be5c85fc042ac939cbd909426e", - "sha256:06cac81bf10f74034e055e903f5f946e3e26fc51c09fc9f584e4a1605d977053", - "sha256:086cede306d96202e15a4b77ace8472e39d9f4e5f9fd92dd4fecdfb2313b2080", - "sha256:0900872f2fdb3ee5646b557918d02279dc3af3dfb39029ac4e945458b13f73bc", - "sha256:0a3a30f0e257df382f5f9534d4ce3d4cf06eafaf5192beb1a7bd066cb10e78fb", - "sha256:0b3d67d31383c4c68e19a88e28fc4c2e29517580f1b0ebec4a069d502ce1e0bf", - "sha256:0dfa3855031070058add1a59fdfda0192fd3e8f97e7c81de0596c145dea51820", - "sha256:0f4872f5d6c54419c94c25dd6ae1d015deeb337d06e448cd890a1e89a8ee7f3b", - "sha256:11c21557d0e0a5a38632cbbaca5f008723b26a89d70db6315523df6df77d6232", - "sha256:166ad2a22ee770f5656e1257703139d3533b4a0b6909af67c6b4a3adc1c98657", - "sha256:193c3887285eec1dbdb3f2bd7fbc351d570ca9c02ca756c3afbc71b3c98af6ef", - "sha256:1d84e91521c5e4cb6602fe11ece3e1de03b2760e14ae4fcf1a4b56fa3c801fcd", - "sha256:1ed5630d946859de835a85e9a43b721123a8a44ec26e2830b296d478c7fd4259", - "sha256:22486cdafba4f9e471c816a2a5745337742a617fef68e890d8baf9f3036d7833", - "sha256:22ccfe8d9bb0d6134892cbe1262493a8c70d736b9df930f3f3afae0fe3ac924d", - "sha256:24e4e56304fdb56f96f80eabf840eab043b3afea9348b88be680ec5986780a0f", - "sha256:25dc33618d45456ccb1d37bce44bc78cf269909aa14c4db2e03d63146a8a1493", - "sha256:263c3dbccc78e2e331e59e90115941b5f53e85cfcc6b3b2fbff1fd4e3d2c6ea8", - "sha256:28ee1c96109974af104028a8ef57cec21447d42d0e937c0275329272e370ebcf", - "sha256:30a3a201a127ea57f7e14ba43c93c9c4be8b7d17a26e03bb49e6966d019eede9", - "sha256:3188936845cd0cb114fa6a51842a304cdbac2958145d03be2377ec41eb285d19", - "sha256:367449cf07d33dc216c083f2036bb7d976c6e4903ab31be400ad74ad9f85ce98", - "sha256:37eee4e552a65866f15dedd917d5e5f3d59805994260720821e2c1b51ac3248f", - "sha256:3a10260e6a152e5f03f26db4a407c4c62d3830b9af9b7c0450b183615f05d43b", - "sha256:3a7b1cd820e1b6116f92c6128f1188e7afe421c7e1b35fa9836b11444e53ebd9", - "sha256:3ab483ea0e251b5790c2aac03acde31bff0c736bf8a86829b89382b407cd1c3b", - "sha256:3ad968d1e3aa6ce5be295ab5fe3ae1bf5bb4769d0f98a80a0252d543a2ef2e9e", - "sha256:445badb539005283825959ac9fa4a28f712c214b65af3a2c464f1adc90f5fcbc", - "sha256:453b7ec753cf5e4356e14fe858064e5520c460d3bbbcb9c35e55c0d21155c256", - "sha256:494f5459ffa1bd45e18558cd98710c36c0b8fbfa82a5eabcbe671d80ecffbfe8", - "sha256:4b5de7d4583e60d5fd246dd57fcd3a8aa23c6e118a8c72b38adf666ba8e7e927", - "sha256:4f3e223b2b2db5e0db0c2b97286aba0036ca000f06aca9b12112eaa9af3d92ae", - "sha256:4fdb6f54f38e334db97f72fa0c701e66d8479af0bc3f9bfb5b90f1c30f54500f", - "sha256:51a202e0f80f241ccb68e3e26e19ab5b3bf0f813314f2c967642f13ebcf1ddfe", - "sha256:581f086833d24a22c89ae0fe2142cfaa1c92c930adf637ddf122d55083fb5a0f", - "sha256:583221913fbc8f53b88c42e8dbb8fca1d0f2e597cb190ce45916662b8b9d9621", - "sha256:58632b187be6f0be500f553be41e277712baa278147ecb7559983c6d9faf7ae1", - "sha256:5c67dace46f361125e6b9cace8fe0b729ed8479f47e70c89b838d319375c8137", - "sha256:5e70f92ef89bac1ac8a99b3324923b4749f008fdbd7aa9cb35e01d7a284a04f9", - "sha256:5f5d9bd30756fff3e7216491a0d6d520c448d5124d3d8e8f56446d6412499e74", - "sha256:5f8a0297355e652001015e93be345ee54393e45dc3050af4a0475c5a2b767d46", - "sha256:62d7c4f13102148c78d7353c6052af6d899a7f6df66a32bddcc0c0eb7c5326f8", - "sha256:69ac2c492918c2461bc6ace42d0479638e60719f2a4ef3f0815fa2df88e9f940", - "sha256:6abb3a4c52f05e08460bd9acf04fec027f8718ecaa0d09c40ffbc3fbd70ecc39", - "sha256:6e63ccc6e0ad8986386461c3c4b737540f20426e7ec932f42e030320896c311a", - "sha256:6e9e451dee940a86789134b6b0ffbe31c454ade3b849bb8a9d2cca2541a8e91d", - "sha256:6fb2d5d272341565f08e962cce14cdf843a08ac43bd621783527adb06b089c4b", - "sha256:71936a8b3b977ddd0b694c28c6a34f4fff2e9dd201969a4ff5d5fc7742d614b0", - "sha256:73419b89f812f498aca53f757dd834919b48ce4799f9d5cad33ca0ae442bdb1a", - "sha256:739c6c051a7540608d097b8e13c76cfa85263ced467168dc6b477bae3df7d0e2", - "sha256:7464663eaca6adba4175f6c19354feea61ebbdd735563a03d1e472c7072d27bb", - "sha256:74c136e4093627cf04b26a35dab8cbfc9b37c647f0502fc313376e11726ba303", - "sha256:76541dc8d53715fb4f7a3a06b34b0dc6846e3c69bc6204c55653a85dd6220971", - "sha256:7a485ff48fbd231efa32d58f479befce52dcb6bfb2a88bb7bf9a0b89b1bc8030", - "sha256:7e442c013447d1d8d195be62852270b78b6e255b79b8675bad8479641e21fd96", - "sha256:7f15a931a668e58087bc39d05d2b4bf4b14ff2875b49c994bbdb1c2217a8daeb", - "sha256:7f88ae3e69df2ab62fb0bc5219a597cb890ba5c438190ffa87490b315190bb33", - "sha256:8069e831f205d2ff1f3d355e82f511eb7c5522d7d413f5db5756b772ec8697f8", - "sha256:850d2998f380b1e266459ca5b47bc9e7daf9af1d070f66317972f382d46f1904", - "sha256:898cce66d0836973f48dda4e3514d863d70142bdf6dfab932b9b6a90ea5b222d", - "sha256:9097818b6cc1cfb5f174e3263eba4a62a17683bcfe5c4b5d07f4c97fa51fbf28", - "sha256:936bc20503ce24770c71938d1369461f0c5320830800933bc3956e2a4ded930e", - "sha256:9372dff5ea15930fea0445eaf37bbbafbc771a49e70c0aeed8b4e2c2614cc00e", - "sha256:9987a9e4f8197a1000280f7cc089e3ea2c8b3c0a64d750537809879a7b4ceaf9", - "sha256:99acd4dfdfeb58e1937629eb1ab6ab0899b131f183ee5f23e0b5da5cba2fec74", - "sha256:9b01c22bc74a7fb44066aaf765224c0d933ddf1f5047d6cdfe4795504a4493f8", - "sha256:a00d3a393207ae12f7c49bb1c113190883b500f48979abb118d8b72b8c95c032", - "sha256:a23e5a1f8b982d56fa64f8e442e037f6ce29322f1f9e6c2344cd9e9f4407ee57", - "sha256:a2bdb3babb74079f021696cb46b8bb5f5661165c385d3a238712b031a12355be", - "sha256:a394aa27f2d7ff9bc04cf703817773a59ad6dfbd577032e690f961d2460ee936", - "sha256:a6c6e16b663be828a8f0b6c5027d36471d4a9f90d28444aa4ced4d48d7d6ae8f", - "sha256:af0a583efaacc52ae2521f8d7910aff65cdb093091d76291ac5820d5e947fc1c", - "sha256:af827b7cbb303e1befa6c4f94fd2bf72f108089cfa0f8abab8f4ca553cf5ca5a", - "sha256:c4be718e51e86f553bcf515305a158a1cd180d23b72f07ae76d6017c3cc5d791", - "sha256:cdb3c9f8fef0a954c632f64328a3935988d33a6604ce4bf67ec3e39670f12ae5", - "sha256:d10fd186aac2316f9bbb46ef91977f9d394ded67050ad6d84d94ed6ea2e8e54e", - "sha256:d1e97353dcc5587b85986cda4ff3ec98081d7e84dd95e8b2a6d59820f0545f8a", - "sha256:d2a9d7f1c11487b1c69367ab3ac2d81b9b3721f097aa409a3191c3e90f8f3dd7", - "sha256:de7f6748b890708578fc4b7bb967d810aeb6fcc9bff4bb77dbca77dab2f9df6a", - "sha256:e5330fa0cc1f5c3c4c3bb8e101b742025933e7848989370a1d4c8c5e401ea753", - "sha256:e999e2dcc094002d6e2c7bbc1fb85b58ba4f465a760a8014d97619330cdbbbf3", - "sha256:eb76670874fdd6091eedcc856128ee48c41a9bbbb9c3f1c7c3cf169290e3ffd6", - "sha256:f1c23e24a7000da892a312fb17e33c5f94f8b001de44b7cf8ba2e36fbd15859e", - "sha256:f2ffc92b46ed6e6760f1d47a71e56b5664781bc68986dbd1836b2b70c0ce2071", - "sha256:f4f72a85316d8e13234cafe0a9f81b40418ad7a082792fa4165bd7d45d96066b", - "sha256:f59883c643cb19630500f57016f76cfdcd6845ca8c5b5ea1f6e17f74c8e5f511", - "sha256:f6aaef16d65d1787280943f1c8718dc32e9cf141014e4634d64446702d26e0ff", - "sha256:fe81055d8c6c9de76d60c94ddea73c290b416e061d40d542b24a5871bad498b7", - "sha256:ff45e0cd8451e293b63ced93161e189780baf444119391b3e7d25315060368a6" + "sha256:0403f647055de2609be776965108447deb8e384fe4a553c119e3ff6bfbab4784", + "sha256:0642eae483cc8c2902e4af7298bf886d605e80f26382124cddc3967c2a3df09e", + "sha256:0b609fc9cdbd1f02e51f67f51e5aee60a841ef58a68d00d5ee2c0faf357481a3", + "sha256:0d2c11f3ea4db66b5cbded23b20185c35066892c67d80ec4be4bab257b9ad1e0", + "sha256:0e42e0ec0cd3e0d851cb3c91f770c9301f48647cb2877cb78f74bdaa07639a79", + "sha256:132718176cc723026d201e347f800cd1a9e4b62ccd3f82476950834dad501c75", + "sha256:16cc1da46c04fb0fb128b4dc430b78fa2aba8a6c0c9f8eb391fd5103409a6ac6", + "sha256:18be793c4c87de2965e1c0f060f03d9e5aff66cfeae8e1dbe6e5b88056ec153f", + "sha256:1a55d509a1dc5a5b708b5dad3b5334e07a16ad4c2185e27b40e4dba796ab7f88", + "sha256:1dcb645d7e34dcbcc96cd7c132b1fc55c39263ca62eb961c064eb3928997363b", + "sha256:2016745cb3ba554469d02819d78958b571792bb68e31302610e898f80dd3a573", + "sha256:228b90f613b25ba0019361e4ab81520b343b622fc657daf7e501c4ed6a2366c0", + "sha256:309ef5706e95e62578cda256b97f5e097916a2c26247c287bbe74794e7150df2", + "sha256:339dc63b3eba969067b00f41f15ad161bf2946613156fb131266d8debc8e44d0", + "sha256:3820778ea1387c2b6a818caec01c63adc5b3750211af6447e8dcfb9b6f08dbba", + "sha256:3d42df8201e00384736f0df9be2ced39324c3907607d17d50d50116c989d84cd", + "sha256:3e7b8bd70c48ffb28461ebe092c2345536fb18bbbf19d287c8913699735f505c", + "sha256:3f2f725aa3e909b3c5fdb8192490bdd8e1495e85906af74fe6e34a2a77ba0673", + "sha256:3fc6a169517ca0d7ca6846c3c5392ef2b9e38896f61d615cb75b9e7134d4ee1e", + "sha256:45980ea19277dc0a579e432aef6a504fe098ef3a9032ead15e446eb0f1191aee", + "sha256:4d010d080c4888371033baab27e47c9df7d6fb28d0b7b7adf85a4a49be9298b3", + "sha256:4de84e71173d4dada2897e5a0e1b7877e5eefbfe0d6a44edee6ce31d9b8ec09e", + "sha256:549d195116a1ba1e1ae2f5ca143f9777800f6636eab917d4f02b5310d6d73461", + "sha256:562ec27dfa3f311e0db1ba243ec6e5f6ab96b1edfcfc6cf86f28038bc4961ce6", + "sha256:57dfc8048c72ba48a8c45e188d811e5efd7e49b387effc8fb17e97936dde5bf6", + "sha256:5899d28b5276f536fcf840b18b61a9fce23cc3aec1d114c44c07fe94ebeaa500", + "sha256:60cfb538fe9ef86e5b2ab0ca8fc8d62524777f6c611dcaf76dc16fbe9b8e698a", + "sha256:623dcc6d7a7ba450bbdbeedbaa0c42b329bdae16491af2282f12a7e809be7eb9", + "sha256:67170979de0dacac3f3097d02b0ad188d8edcea44ccc44aaa0550af49150c7dc", + "sha256:6e73ebb44dca5f708dc871fe0b90cf4cff1a13f9956f747cc87b535a840386f5", + "sha256:6f34591000f06e62085b1865c9bc5f7858df748834662a51edadfd2c3bfe0dd3", + "sha256:724b1b270cb13ea2e6503476e34541a0b1f62280bc997eab443f87790202033d", + "sha256:75a6f4aa904301dab8022397a22c0039edc1f51e90b83dbd4464b8a38dc87842", + "sha256:77545b5dcda13b70f872c3b5974ac64c21d05e65b1590b441c8560115dc3a0d1", + "sha256:776483fd35b58d8afe3acbd9988d5de592ab6da2d2a865edfdbc9fdb43e7c486", + "sha256:77cc258aeb29a3417062758975521eae60af6f79e930d6993555eeac6a8eac29", + "sha256:794f7c05af0763b1bbd1b9e6eff0e52ad068be3b12cd96c87de037b01390c968", + "sha256:868a2fae76dfb06e87291bcbd4dcbcc778a8500510b618d50496e520bd94d9b9", + "sha256:8842af7f175078456b8b17f1b73a0d16a65dcbdc653ecefeb00a56b3c8c298c4", + "sha256:8d9bc218650022a768f3775dd7fdac1886437325d8d295d923ebcfef4892ad5c", + "sha256:8f572d989142e0908e6acf57ad1b9b86989ff057c006d13b76c146ec6a20216a", + "sha256:90480b2134999301eea795b3a9dbf606c6fbab1b489150c501da84a959442465", + "sha256:916abf1ac5cf7eb16bc540a5bf75c71c43a676f5c52fcb9fe75a2bd75fb944e8", + "sha256:92f980729e79b5d16d221038dbf2e8f9a9136afa072f9d5d6ed4cb984b126a09", + "sha256:933082f161bbb3e9f90d00990dc956120f608cdbcaeea15c4d897f56ef4fe416", + "sha256:97ab3647280d458a1f9adb85244e81587505a43c0c7cff851f5116cd2814b894", + "sha256:985b7836931d033570b94c94713c6dba5f9d3ff26045f72c3e5dbc5fe3361e5a", + "sha256:9e549d642426e3579b3f4b92d0431543b012dcb6e825c91619d4e93b7363c3f9", + "sha256:9edd0e01a343766add6817bc448408858ba6b489039eaaa2018474e4001651a4", + "sha256:9ee68b21909686eeb21dfcba2c3b81fee70dcf38b140dcd5aa70680995fa3aa5", + "sha256:9f5e772ed5fef25b3de9f2008fe67b92d46831bd2bc5bdc5dd6bfd06b83b316f", + "sha256:a03a4f3a19a189919c7055098790285cc5c5b0b3976f8d227aea39dbf9f8bfdb", + "sha256:a4d240d260a1aed814790bbe1f10a5ff31ce6c21bc78f0da4a1e8268d6c80dbd", + "sha256:a5a68357f686f8c4d527a2dc04f52e669c2fc1cbde38f6f7eb6a0e58cbd17cae", + "sha256:a998cc0aeeea4c6d5622a3754da5a493055d2d95186bad877b0a34ea6e6dbe0a", + "sha256:b67e47c5595b9224599016e333f5ec25392597a89d5744658f837d204e16c63e", + "sha256:b6f3b96617e9852703f5b633ea01315ca45c77e879584f283c44127f0f1ec564", + "sha256:b7593fe7eb5feaa3fbb461ac79aac9f9fc0387a5ca8080b0c6fe2ca27b091afd", + "sha256:bb3f6562e89bad0110afbe64e485aac2462efdce6232cdec7862a095dc3412f6", + "sha256:bb4f8c3c9a9f34423dba193f241f617b08ffc63e27f67159f60ae6baf2dcfe0f", + "sha256:bd63e7b74661fed317212fab774e2a648bc4bb09b35f25474f8e3325d2945cd7", + "sha256:be753b225d159feb397bd0bf91ae86f689bad0da09d3b301478cd39b878ab31a", + "sha256:bf100a3288f9bb7f919b87eb84f87101e197535b9bd0e2c2b5b3179633324fee", + "sha256:c223d078112e90dc0e5c4e35b98b9584164bea9fbbd221c0b21c5241f6d51b62", + "sha256:c3d8c679607220979434f494b139dfb00131ebf70bb406553d69c1ff01a5c33d", + "sha256:c43257717611ff5e9a1d79dce8e47566235ebda63328718d9b65dd640bc832ef", + "sha256:c832ec92c4499ac463186af72f9ed4d8daec15499b16f0a879b0d1c8e5cf4a3b", + "sha256:c8e2706ceb622bc63bac98ebb10ef5da80ed70fbd8a7999a5076de3afaef0fb1", + "sha256:cb237bfd0ef4d5eb6a19e29f9e528ac67ac3be932ea6b44fb6cc09b9f3ecff78", + "sha256:ccd7a6fca48ca9c131d9b0a2972a581e28b13416fc313fb98b6d24a03ce9a398", + "sha256:d10a2ed46386e850bb3de503a54f9fe8192e5917fcbb143bfef653a9355e9a53", + "sha256:d1443ba9acbb593fa7c1c29e011d7c9761545fe35e7652e85ce7f51a16f7e08d", + "sha256:d2287ac9360dec3837bfdad969963a5d073a09a85d898bd86bea82aa8876ef3c", + "sha256:d3c9f051b028810f5a87c88e5d6e9af3c0ff32ef62763bf15d29f740453ca909", + "sha256:d72140ccf8a147e94274024ff6fd8fb7811354cf7ef88b1f0a988ebaa5bc774f", + "sha256:d938b4a840fb1523b9dfbbb454f652967f18e197569c32266d4d13f37244c3d9", + "sha256:db622b999ffe49cb891f2fff3b340cdc2f9797d01a0a202a0973ba2562501d90", + "sha256:e09fbecc007f7b6afdfb3b07ce5bd9f8494b6856dd4f577d26c66c391b829851", + "sha256:e1fa280b3ad78eea5be86f94f461c04943d942697e0dac889fa18fff8f5f9147", + "sha256:e4f18eca6028ffa62adbd185a8f1e1dd242f2e68164dba5c2b74a5204850b4cf", + "sha256:e825dbb7f84dfa24663dd75835e7257f8882629fc11f03ecf77d84a75134b864", + "sha256:eaecf47ef10c72ece9a2a92118257da87e460e113b83cc0d2905cbbe931792b4", + "sha256:ef6688db9bf91ba111ae734ba6ef1a063304a881749726e0d3575f5c10a9facf", + "sha256:f398ba4df52d30b1763f62eed9de5620dcde96e6f491f4c62686736b155aa6e4", + "sha256:f80e2bb21bfab56ed7405c2d79d34b5dc0bc96c2c1d2a067b643a09fb756c43a", + "sha256:f83351e0f7dcdb14d7326c3d8d8c4e915fa685cbfdc6281f9470d97a04e9dfe4", + "sha256:f8dca5590fec7a89ed6826fce625595279e586ead52e9e958d3237821fbc750c", + "sha256:fa3edde1aa8807de1d05934982416cb3ec46d1d4d91e280bcce7cca01c507992", + "sha256:fea07c1a39a22614acb762e3fbbb4011f65eedafcb2948feeef641ac78b4ee5c", + "sha256:ff10896fa55167371960c5908150b434b71c876dfab97b69478f22c8b445ea19", + "sha256:ff86d4e85188bba72cfb876df3e11fa243439882c55957184af44a35bd5880b7", + "sha256:ffed1e4980889765c84a5d1a566159e363b71d6b6fbaf0bebc9d3c30bc016766" ], "index": "pypi", "markers": "python_version >= '3.10'", - "version": "==7.13.0" + "version": "==7.13.1" }, "defusedxml": { "hashes": [ @@ -689,11 +702,11 @@ }, "filelock": { "hashes": [ - "sha256:15d9e9a67306188a44baa72f569d2bfd803076269365fdea0934385da4dc361a", - "sha256:b8360948b351b80f420878d8516519a2204b07aefcdcfd24912a5d33127f188c" + "sha256:18c57ee915c7ec61cff0ecf7f0f869936c7c30191bb0cf406f1341778d0834e1", + "sha256:4b0dda527ee31078689fc205ec4f1c1bf7d56cf88b6dc9426c4f230e46c2dce1" ], "markers": "python_version >= '3.10'", - "version": "==3.20.1" + "version": "==3.20.3" }, "ghp-import": { "hashes": [ @@ -702,6 +715,22 @@ ], "version": "==2.1.0" }, + "gitdb": { + "hashes": [ + "sha256:5ef71f855d191a3326fcfbc0d5da835f26b13fbcba60c32c21091c349ffdb571", + "sha256:67073e15955400952c6565cc3e707c554a4eea2e428946f7a4c162fab9bd9bcf" + ], + "markers": "python_version >= '3.7'", + "version": "==4.0.12" + }, + "gitpython": { + "hashes": [ + "sha256:400124c7d0ef4ea03f7310ac2fbf7151e09ff97f2a3288d64a440c584a29c37f", + "sha256:79812ed143d9d25b6d176a10bb511de0f9c67b1fa641d82097b0ab90398a2058" + ], + "markers": "python_version >= '3.7'", + "version": "==3.1.46" + }, "griffe": { "hashes": [ "sha256:6f6762661949411031f5fcda9593f586e6ce8340f0ba88921a0f2ef7a81eb9a3", @@ -736,12 +765,12 @@ }, "importlib-metadata": { "hashes": [ - "sha256:d13b81ad223b890aa16c5471f2ac3056cf76c5f10f82d6f9292f0b415f389000", - "sha256:e5dd1551894c77868a30651cef00984d50e1002d06942a7101d34870c5f02afd" + "sha256:49fef1ae6440c182052f407c8d34a68f72efc36db9ca90dc0113398f2fdde8bb", + "sha256:5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151" ], "index": "pypi", "markers": "python_version >= '3.9'", - "version": "==8.7.0" + "version": "==8.7.1" }, "iniconfig": { "hashes": [ @@ -753,11 +782,11 @@ }, "isort": { "hashes": [ - "sha256:58d8927ecce74e5087aef019f778d4081a3b6c98f15a80ba35782ca8a2097784", - "sha256:9b8f96a14cfee0677e78e941ff62f03769a06d412aabb9e2a90487b3b7e8d481" + "sha256:1bcabac8bc3c36c7fb7b98a76c8abb18e0f841a3ba81decac7691008592499c1", + "sha256:5513527951aadb3ac4292a41a16cbc50dd1642432f5e8c20057d414bdafb4187" ], - "markers": "python_full_version >= '3.9.0'", - "version": "==6.1.0" + "markers": "python_full_version >= '3.10.0'", + "version": "==7.0.0" }, "jaraco.classes": { "hashes": [ @@ -769,11 +798,11 @@ }, "jaraco.context": { "hashes": [ - "sha256:9bae4ea555cf0b14938dc0aee7c9f32ed303aa20a3b73e7dc80111628792d1b3", - "sha256:f797fc481b490edb305122c9181830a3a5b76d84ef6d1aef2fb9b47ab956f9e4" + "sha256:55fc21af4b4f9ca94aa643b6ee7fe13b1e4c01abf3aeb98ca4ad9c80b741c786", + "sha256:953ae8dddb57b1d791bf72ea1009b32088840a7dd19b9ba16443f62be919ee57" ], - "markers": "python_version >= '3.8'", - "version": "==6.0.1" + "markers": "python_version >= '3.9'", + "version": "==6.0.2" }, "jaraco.functools": { "hashes": [ @@ -961,21 +990,21 @@ }, "mkdocstrings": { "hashes": [ - "sha256:37a9736134934eea89cbd055a513d40a020d87dfcae9e3052c2a6b8cd4af09b6", - "sha256:8722f8f8c5cd75da56671e0a0c1bbed1df9946c0cef74794d6141b34011abd42" + "sha256:351a006dbb27aefce241ade110d3cd040c1145b7a3eb5fd5ac23f03ed67f401a", + "sha256:4c50eb960bff6e05dfc631f6bc00dfabffbcb29c5ff25f676d64daae05ed82fa" ], "index": "pypi", - "markers": "python_version >= '3.9'", - "version": "==0.29.1" + "markers": "python_version >= '3.10'", + "version": "==1.0.0" }, "mkdocstrings-python": { "hashes": [ - "sha256:22ded3a63b3d823d57457a70ff9860d5a4de9e8b1e482876fc9baabaf6f5f374", - "sha256:9b9eaa066e0024342d433e332a41095c4e429937024945fea511afe58f63175d" + "sha256:66ecff45c5f8b71bf174e11d49afc845c2dfc7fc0ab17a86b6b337e0f24d8d90", + "sha256:843a562221e6a471fefdd4b45cc6c22d2607ccbad632879234fa9692e9cf7732" ], "index": "pypi", - "markers": "python_version >= '3.9'", - "version": "==1.16.12" + "markers": "python_version >= '3.10'", + "version": "==2.0.1" }, "more-itertools": { "hashes": [ @@ -1043,11 +1072,20 @@ }, "pathspec": { "hashes": [ - "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", - "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712" + "sha256:bac5cf97ae2c2876e2d25ebb15078eb04d76e4b98921ee31c6f85ade8b59444d", + "sha256:e80767021c1cc524aa3fb14bedda9c34406591343cc42797b386ce7b9354fb6c" + ], + "markers": "python_version >= '3.9'", + "version": "==1.0.3" + }, + "pip-check-updates": { + "hashes": [ + "sha256:76e9c12a58ec51043a8af859b0a3863cb8bcacb6afdbf8eb0452f27e23fbda75", + "sha256:eed1fb10de57239aa0332056d4df44ee737b15098abbd00f43a2d0916fca12c5" ], + "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==0.12.1" + "version": "==0.28.0" }, "platformdirs": { "hashes": [ @@ -1067,12 +1105,21 @@ }, "pre-commit": { "hashes": [ - "sha256:10badb65d6a38caff29703362271d7dca483d01da88f9d7e05d0b97171c136cb", - "sha256:a2256f489cd913d575c145132ae196fe335da32d91a8294b7afe6622335dd023" + "sha256:3b3afd891e97337708c1674210f8eba659b52a38ea5f822ff142d10786221f77", + "sha256:eb545fcff725875197837263e977ea257a402056661f09dae08e4b149b030a61" ], "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==3.3.3" + "markers": "python_version >= '3.10'", + "version": "==4.5.1" + }, + "pre-commit-update": { + "hashes": [ + "sha256:0264337064c362515405a2861431e1518f3a711c50e5dce5a7b484f2eb33f1af", + "sha256:404dba7b176a042e2b4858b752c4e920595a7bc6935e4f594d7554083bd5c4d9" + ], + "index": "pypi", + "markers": "python_version >= '3.10'", + "version": "==0.9.0" }, "project-summarizer": { "hashes": [ @@ -1102,12 +1149,12 @@ }, "pylint": { "hashes": [ - "sha256:2b11de8bde49f9c5059452e0c310c079c746a0a8eeaa789e5aa966ecc23e4559", - "sha256:43860aafefce92fca4cf6b61fe199cdc5ae54ea28f9bf4cd49de267b5195803d" + "sha256:63e06a37d5922555ee2c20963eb42559918c20bd2b21244e4ef426e7c43b92e0", + "sha256:d9b71674e19b1c36d79265b5887bf8e55278cbe236c9e95d22dc82cf044fdbd2" ], "index": "pypi", - "markers": "python_full_version >= '3.9.0'", - "version": "==3.3.7" + "markers": "python_full_version >= '3.10.0'", + "version": "==4.0.4" }, "pylint-utils": { "hashes": [ @@ -1120,11 +1167,11 @@ }, "pymdown-extensions": { "hashes": [ - "sha256:4969c691009a389fb1f9712dd8e7bd70dcc418d15a0faf70acb5117d022f7de8", - "sha256:e8698a66055b1dc0dca2a7f2c9d0ea6f5faa7834a9c432e3535ab96c0c4e509b" + "sha256:5c73566ab0cf38c6ba084cb7c5ea64a119ae0500cce754ccb682761dfea13a52", + "sha256:ea9e62add865da80a271d00bfa1c0fa085b20d133fb3fc97afdc88e682f60b2f" ], "markers": "python_version >= '3.9'", - "version": "==10.19.1" + "version": "==10.20" }, "pyproject-hooks": { "hashes": [ @@ -1145,12 +1192,12 @@ }, "pytest": { "hashes": [ - "sha256:14d920b48472ea0dbf68e45b96cd1ffda4705f33307dcc86c676c1b5104838a6", - "sha256:f40f825768ad76c0977cbacdf1fd37c6f7a468e460ea6a0636078f8972d4517e" + "sha256:711ffd45bf766d5264d487b917733b453d917afd2b0ad65223959f59089f875b", + "sha256:75186651a92bd89611d1d9fc20f0b4345fd827c41ccd5c299a868a05d70edf11" ], "index": "pypi", - "markers": "python_version >= '3.9'", - "version": "==8.4.0" + "markers": "python_version >= '3.10'", + "version": "==9.0.2" }, "pytest-console-scripts": { "hashes": [ @@ -1305,6 +1352,7 @@ "sha256:fa160448684b4e94d80416c0fa4aac48967a969efe22931448d853ada8baf926", "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0" ], + "index": "pypi", "markers": "python_version >= '3.8'", "version": "==6.0.3" }, @@ -1356,6 +1404,14 @@ "markers": "python_full_version >= '3.8.0'", "version": "==14.2.0" }, + "ruamel.yaml": { + "hashes": [ + "sha256:27592957fedf6e0b62f281e96effd28043345e0e66001f97683aa9a40c667c93", + "sha256:53eb66cd27849eff968ebf8f0bf61f46cdac2da1d1f3576dd4ccee9b25c31993" + ], + "markers": "python_version >= '3.9'", + "version": "==0.19.1" + }, "setuptools": { "hashes": [ "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922", @@ -1373,14 +1429,30 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", "version": "==1.17.0" }, + "smmap": { + "hashes": [ + "sha256:26ea65a03958fa0c8a1c7e8c7a58fdc77221b8910f6be2131affade476898ad5", + "sha256:b30115f0def7d7531d22a0fb6502488d879e75b260a9db4d0819cfb25403af5e" + ], + "markers": "python_version >= '3.7'", + "version": "==5.0.2" + }, + "soupsieve": { + "hashes": [ + "sha256:4cf733bc50fa805f5df4b8ef4740fc0e0fa6218cf3006269afd3f9d6d80fd350", + "sha256:a11fe2a6f3d76ab3cf2de04eb339c1be5b506a8a47f2ceb6d139803177f85434" + ], + "markers": "python_version >= '3.9'", + "version": "==2.8.1" + }, "sourcery": { "hashes": [ - "sha256:0d1c63eb0465ed9405bea422ac6229aa1128e784160a481389ed6dbe90080682", - "sha256:196e20bcc1b295b326005f728638f0a4bbb9c1fe7399dce4d4409ecfc9a5e487", - "sha256:61db72f1183abd231bc448a4d03a74738f3b1013ad4396dc2935c080c3863c36" + "sha256:19116cc91aed5db2badca22cd2d745b8e2151bf22bac037d4b00aa2edd52217c", + "sha256:4b14cad029f259cf46e2f069ef35d5d2701886a13fdb6f64edbe8672e4b21cca", + "sha256:7a45fd88840cd167747519984213091912fe3782bc167af0c2de1c78d3d9672d" ], "index": "pypi", - "version": "==1.35.0" + "version": "==1.40.0" }, "text-unidecode": { "hashes": [ @@ -1389,6 +1461,68 @@ ], "version": "==1.3" }, + "toml": { + "hashes": [ + "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", + "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f" + ], + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2'", + "version": "==0.10.2" + }, + "tomli": { + "hashes": [ + "sha256:0408e3de5ec77cc7f81960c362543cbbd91ef883e3138e81b729fc3eea5b9729", + "sha256:0dc56fef0e2c1c470aeac5b6ca8cc7b640bb93e92d9803ddaf9ea03e198f5b0b", + "sha256:0e0fe8a0b8312acf3a88077a0802565cb09ee34107813bba1c7cd591fa6cfc8d", + "sha256:0f2e3955efea4d1cfbcb87bc321e00dc08d2bcb737fd1d5e398af111d86db5df", + "sha256:133e93646ec4300d651839d382d63edff11d8978be23da4cc106f5a18b7d0576", + "sha256:1b168f2731796b045128c45982d3a4874057626da0e2ef1fdd722848b741361d", + "sha256:1c8a885b370751837c029ef9bc014f27d80840e48bac415f3412e6593bbc18c1", + "sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a", + "sha256:1fb2945cbe303b1419e2706e711b7113da57b7db31ee378d08712d678a34e51e", + "sha256:20cedb4ee43278bc4f2fee6cb50daec836959aadaf948db5172e776dd3d993fc", + "sha256:20ffd184fb1df76a66e34bd1b36b4a4641bd2b82954befa32fe8163e79f1a702", + "sha256:26ab906a1eb794cd4e103691daa23d95c6919cc2fa9160000ac02370cc9dd3f6", + "sha256:2add28aacc7425117ff6364fe9e06a183bb0251b03f986df0e78e974047571fd", + "sha256:2b1e3b80e1d5e52e40e9b924ec43d81570f0e7d09d11081b797bc4692765a3d4", + "sha256:31d556d079d72db7c584c0627ff3a24c5d3fb4f730221d3444f3efb1b2514776", + "sha256:36b9d05b51e65b254ea6c2585b59d2c4cb91c8a3d91d0ed0f17591a29aaea54a", + "sha256:39b0b5d1b6dd03684b3fb276407ebed7090bbec989fa55838c98560c01113b66", + "sha256:3cf226acb51d8f1c394c1b310e0e0e61fecdd7adcb78d01e294ac297dd2e7f87", + "sha256:3d895d56bd3f82ddd6faaff993c275efc2ff38e52322ea264122d72729dca2b2", + "sha256:413540dce94673591859c4c6f794dfeaa845e98bf35d72ed59636f869ef9f86f", + "sha256:43e685b9b2341681907759cf3a04e14d7104b3580f808cfde1dfdb60ada85475", + "sha256:4cbcb367d44a1f0c2be408758b43e1ffb5308abe0ea222897d6bfc8e8281ef2f", + "sha256:551e321c6ba03b55676970b47cb1b73f14a0a4dce6a3e1a9458fd6d921d72e95", + "sha256:5572e41282d5268eb09a697c89a7bee84fae66511f87533a6f88bd2f7b652da9", + "sha256:5aa48d7c2356055feef06a43611fc401a07337d5b006be13a30f6c58f869e3c3", + "sha256:5b5807f3999fb66776dbce568cc9a828544244a8eb84b84b9bafc080c99597b9", + "sha256:5e3f639a7a8f10069d0e15408c0b96a2a828cfdec6fca05296ebcdcc28ca7c76", + "sha256:685306e2cc7da35be4ee914fd34ab801a6acacb061b6a7abca922aaf9ad368da", + "sha256:75c2f8bbddf170e8effc98f5e9084a8751f8174ea6ccf4fca5398436e0320bc8", + "sha256:7b438885858efd5be02a9a133caf5812b8776ee0c969fea02c45e8e3f296ba51", + "sha256:7d49c66a7d5e56ac959cb6fc583aff0651094ec071ba9ad43df785abc2320d86", + "sha256:7d6d9a4aee98fac3eab4952ad1d73aee87359452d1c086b5ceb43ed02ddb16b8", + "sha256:84d081fbc252d1b6a982e1870660e7330fb8f90f676f6e78b052ad4e64714bf0", + "sha256:8768715ffc41f0008abe25d808c20c3d990f42b6e2e58305d5da280ae7d1fa3b", + "sha256:920b1de295e72887bafa3ad9f7a792f811847d57ea6b1215154030cf131f16b1", + "sha256:9a08144fa4cba33db5255f9b74f0b89888622109bd2776148f2597447f92a94e", + "sha256:a26d7ff68dfdb9f87a016ecfd1e1c2bacbe3108f4e0f8bcd2228ef9a766c787d", + "sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c", + "sha256:b5ef256a3fd497d4973c11bf142e9ed78b150d36f5773f1ca6088c230ffc5867", + "sha256:b6c78bdf37764092d369722d9946cb65b8767bfa4110f902a1b2542d8d173c8a", + "sha256:bbb1b10aa643d973366dc2cb1ad94f99c1726a02343d43cbc011edbfac579e7c", + "sha256:c084ad935abe686bd9c898e62a02a19abfc9760b5a79bc29644463eaf2840cb0", + "sha256:c73add4bb52a206fd0c0723432db123c0c75c280cbd67174dd9d2db228ebb1b4", + "sha256:cae9c19ed12d4e8f3ebf46d1a75090e4c0dc16271c5bce1c833ac168f08fb614", + "sha256:d20b797a5c1ad80c516e41bc1fb0443ddb5006e9aaa7bda2d71978346aeb9132", + "sha256:d3d1654e11d724760cdb37a3d7691f0be9db5fbdaef59c9f532aabf87006dbaa", + "sha256:d878f2a6707cc9d53a1be1414bbb419e629c3d6e67f69230217bb663e76b5087" + ], + "index": "pypi", + "markers": "python_version >= '3.8'", + "version": "==2.4.0" + }, "tomlkit": { "hashes": [ "sha256:430cf247ee57df2b94ee3fbe588e71d362a941ebb545dec29b53961d61add2a1", @@ -1405,6 +1539,22 @@ "markers": "python_version >= '3.9'", "version": "==1.1.0" }, + "tqdm": { + "hashes": [ + "sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2", + "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2" + ], + "markers": "python_version >= '3.7'", + "version": "==4.67.1" + }, + "tqdm-loggable": { + "hashes": [ + "sha256:175abec3e1f63bbd2eac192fa5da075e80c7bb715d7ccf3cd1a29b7ab5af0617", + "sha256:9703046302b93a667166487759e6f3f49597e86c89eb132ba1f31caa07bf0941" + ], + "markers": "python_version >= '3.9'", + "version": "==0.2" + }, "trove-classifiers": { "hashes": [ "sha256:a74f0400524fc83620a9be74a07074b5cbe7594fd4d97fd4c2bfde625fdc1633", @@ -1414,12 +1564,12 @@ }, "twine": { "hashes": [ - "sha256:a47f973caf122930bf0fbbf17f80b83bc1602c9ce393c7845f289a3001dc5384", - "sha256:be324f6272eff91d07ee93f251edf232fc647935dd585ac003539b42404a8dbd" + "sha256:418ebf08ccda9a8caaebe414433b0ba5e25eb5e4a927667122fbe8f829f985d8", + "sha256:e5ed0d2fd70c9959770dce51c8f39c8945c574e18173a7b81802dab51b4b75cf" ], "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==6.1.0" + "markers": "python_version >= '3.9'", + "version": "==6.2.0" }, "typed-argument-parser": { "hashes": [ @@ -1455,19 +1605,19 @@ }, "urllib3": { "hashes": [ - "sha256:016f9c98bb7e98085cb2b4b17b87d2c702975664e4f060c6532e64d1c1a5e797", - "sha256:ec21cddfe7724fc7cb4ba4bea7aa8e2ef36f607a4bab81aa6ce42a13dc3f03dd" + "sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed", + "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4" ], "markers": "python_version >= '3.9'", - "version": "==2.6.2" + "version": "==2.6.3" }, "virtualenv": { "hashes": [ - "sha256:643d3914d73d3eeb0c552cbb12d7e82adf0e504dbf86a3182f8771a153a1971c", - "sha256:c21c9cede36c9753eeade68ba7d523529f228a403463376cf821eaae2b650f1b" + "sha256:575a8d6b124ef88f6f51d56d656132389f961062a9177016a50e4f507bbcc19f", + "sha256:8befb5c81842c641f8ee658481e42641c68b5eab3521d8e092d18320902466ba" ], "markers": "python_version >= '3.8'", - "version": "==20.35.4" + "version": "==20.36.1" }, "watchdog": { "hashes": [ diff --git a/README.md b/README.md index 256b328..3986b5a 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,8 @@ | | | |---|---| |Project|[![Version](https://img.shields.io/pypi/v/application_properties.svg)](https://pypi.org/project/application_properties) [![Python Versions](https://img.shields.io/pypi/pyversions/application_properties.svg)](https://pypi.org/project/application_properties) ![platforms](https://img.shields.io/badge/platform-windows%20%7C%20macos%20%7C%20linux-lightgrey) [![License](https://img.shields.io/github/license/jackdewinter/application_properties.svg)](https://github.com/jackdewinter/application_properties/blob/main/LICENSE.txt) [![GitHub top language](https://img.shields.io/github/languages/top/jackdewinter/application_properties)](https://github.com/jackdewinter/application_properties)| -|Quality|[![GitHub Workflow Status (event)](https://img.shields.io/github/actions/workflow/status/jackdewinter/application_properties/main.yml?branch=main)](https://github.com/jackdewinter/application_properties/actions/workflows/main.yml) [![Issues](https://img.shields.io/github/issues/jackdewinter/application_properties.svg)](https://github.com/jackdewinter/application_properties/issues) [![codecov](https://codecov.io/gh/jackdewinter/application_properties/branch/main/graph/badge.svg?token=PD5TKS8NQQ)](https://codecov.io/gh/jackdewinter/application_properties) [![Sourcery](https://img.shields.io/badge/Sourcery-enabled-brightgreen)](https://sourcery.ai) ![snyk](https://img.shields.io/snyk/vulnerabilities/github/jackdewinter/application_properties) | -| |![GitHub Pipenv locked dependency version (branch)](https://img.shields.io/github/pipenv/locked/dependency-version/jackdewinter/application_properties/dev/black/main) ![GitHub Pipenv locked dependency version (branch)](https://img.shields.io/github/pipenv/locked/dependency-version/jackdewinter/application_properties/dev/flake8/main) ![GitHub Pipenv locked dependency version (branch)](https://img.shields.io/github/pipenv/locked/dependency-version/jackdewinter/application_properties/dev/pylint/main) ![GitHub Pipenv locked dependency version (branch)](https://img.shields.io/github/pipenv/locked/dependency-version/jackdewinter/application_properties/dev/mypy/main) ![GitHub Pipenv locked dependency version (branch)](https://img.shields.io/github/pipenv/locked/dependency-version/jackdewinter/application_properties/dev/pyroma/main) ![GitHub Pipenv locked dependency version (branch)](https://img.shields.io/github/pipenv/locked/dependency-version/jackdewinter/application_properties/dev/pre-commit/main) ![GitHub Pipenv locked dependency version (branch)](https://img.shields.io/github/pipenv/locked/dependency-version/jackdewinter/application_properties/dev/sourcery/main)| +|Quality|[![GitHub Workflow Status (event)](https://img.shields.io/github/actions/workflow/status/jackdewinter/application_properties/main.yml)](https://github.com/jackdewinter/application_properties/actions/workflows/main.yml) [![Issues](https://img.shields.io/github/issues/jackdewinter/application_properties.svg)](https://github.com/jackdewinter/application_properties/issues) [![codecov](https://codecov.io/gh/jackdewinter/application_properties/branch/main/graph/badge.svg?token=PD5TKS8NQQ)](https://codecov.io/gh/jackdewinter/application_properties) [![Sourcery](https://img.shields.io/badge/Sourcery-enabled-brightgreen)](https://sourcery.ai) ![Dynamic JSON Badge](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Fjackdewinter%2Fapplication_properties%2Fmain%2Fpublish%2Fdependencies.json&query=%24.mkdocs&label=MkDocs) | +| | ![Dynamic JSON Badge](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Fjackdewinter%2Fapplication_properties%2Fmain%2Fpublish%2Fdependencies.json&query=%24.black&label=Black) ![Dynamic JSON Badge](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Fjackdewinter%2Fapplication_properties%2Fmain%2Fpublish%2Fdependencies.json&query=%24.flake8&label=Flake8) ![Dynamic JSON Badge](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Fjackdewinter%2Fapplication_properties%2Fmain%2Fpublish%2Fdependencies.json&query=%24.pylint&label=PyLint) ![Dynamic JSON Badge](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Fjackdewinter%2Fapplication_properties%2Fmain%2Fpublish%2Fdependencies.json&query=%24.mirrors-mypy&label=MyPy) ![Dynamic JSON Badge](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Fjackdewinter%2Fapplication_properties%2Fmain%2Fpublish%2Fdependencies.json&query=%24.pyroma&label=PyRoma) ![Dynamic JSON Badge](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Fjackdewinter%2Fapplication_properties%2Fmain%2Fpublish%2Fdependencies.json&query=%24.pre-commit&label=Pre-Commit) ![Dynamic JSON Badge](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Fjackdewinter%2Fapplication_properties%2Fmain%2Fpublish%2Fdependencies.json&query=%24.sourcery&label=Sourcery) | |Community|[![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://github.com/jackdewinter/application_properties/graphs/commit-activity) [![Stars](https://img.shields.io/github/stars/jackdewinter/application_properties.svg)](https://github.com/jackdewinter/application_properties/stargazers) [![Forks](https://img.shields.io/github/forks/jackdewinter/application_properties.svg)](https://github.com/jackdewinter/application_properties/network/members) [![Contributors](https://img.shields.io/github/contributors/jackdewinter/application_properties.svg)](https://github.com/jackdewinter/application_properties/graphs/contributors) [![Downloads](https://img.shields.io/pypi/dm/application_properties.svg)](https://pypistats.org/packages/application_properties)| |Maintainers|[![LinkedIn](https://img.shields.io/badge/-LinkedIn-black.svg?logo=linkedin&colorB=555)](https://www.linkedin.com/in/jackdewinter/)| diff --git a/application_properties/application_properties_loader_helper.py b/application_properties/application_properties_loader_helper.py index 9c3c30d..c953b4a 100644 --- a/application_properties/application_properties_loader_helper.py +++ b/application_properties/application_properties_loader_helper.py @@ -13,7 +13,7 @@ class ApplicationPropertiesLoaderHelper: @staticmethod def set_error_handler_if_not_set( - handle_error_fn: Optional[Callable[[str, Optional[Exception]], None]] + handle_error_fn: Optional[Callable[[str, Optional[Exception]], None]], ) -> Callable[[str, Optional[Exception]], None]: """ If the error_handler is not set, make sure to set it to print to output. diff --git a/check_project_dependencies.sh b/check_project_dependencies.sh new file mode 100644 index 0000000..665da7a --- /dev/null +++ b/check_project_dependencies.sh @@ -0,0 +1,235 @@ +#!/usr/bin/env bash + +# Set the script mode to "strict". +# http://redsymbol.net/articles/unofficial-bash-strict-mode/ without the fail fast. +set -uo pipefail + +# Set up any project based local script variables. +SCRIPT_NAME=$(basename -- "${BASH_SOURCE[0]}") +SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd) +TEMP_FILE=$(mktemp /tmp/"${SCRIPT_NAME}".XXXXXXXXX) +TEMP_FILE2=$(mktemp ./"${SCRIPT_NAME}".XXXXXXXXX.txt) + +SCRIPT_TITLE="Analyzing project dependencies" + +# Perform any cleanup required by the script. +# shellcheck disable=SC2329 +cleanup_function() { + + if [[ ${VERBOSE_MODE} -ne 0 ]]; then + echo "{Performing clean up for script '${SCRIPT_NAME}'.}" + fi + + # If the temp file was used, get rid of it. + if [ -f "${TEMP_FILE}" ]; then + rm "${TEMP_FILE}" + fi + if [ -f "${TEMP_FILE2}" ]; then + rm "${TEMP_FILE2}" + fi + + # Restore the current directory. + popd >/dev/null 2>&1 || exit +} + +verbose_echo() { + echo_text=${1:-} + + if [ "${VERBOSE_MODE}" -ne 0 ]; then + echo "${echo_text}" + fi +} + +# Start the main part of the script off with a title. +start_process() { + verbose_echo "${SCRIPT_TITLE}..." + verbose_echo "" + verbose_echo "{Saving current directory prior to execution.}" + if ! pushd "${SCRIPT_DIR}" >"${TEMP_FILE}" 2>&1; then + cat "${TEMP_FILE}" + complete_process 1 "Script cannot save the current directory before proceeding." + fi + + trap cleanup_function EXIT +} + +# Simple function to stop the process with information about why it stopped. +complete_process() { + local SCRIPT_RETURN_CODE=${1} + local COMPLETE_REASON=${2:-} + + if [ -n "${COMPLETE_REASON}" ]; then + echo "${COMPLETE_REASON}" + fi + + if [ "${SCRIPT_RETURN_CODE}" -ne 0 ]; then + echo "" + echo "${SCRIPT_TITLE} failed." + else + verbose_echo "" + verbose_echo "${SCRIPT_TITLE} succeeded." + fi + + exit "${SCRIPT_RETURN_CODE}" +} + +# Give the user hints on how the script can be used. +show_usage() { + local SCRIPT_NAME=$0 + + echo "Usage:" + echo " $(basename "${SCRIPT_NAME}") [flags]" + echo "" + echo "Summary:" + echo " Check for updates to project dependencies managed via pipenv and pre-commit." + echo "" + echo "Flags:" + echo " -u,--upgrade Upgrade the dependencies to the latest versions. (default is check only)" + echo " -x,--debug Display debug information about the script as it executes." + echo " -q,--quiet Do not display detailed information during execution." + echo " -h,--help Display this help text." + echo "" + exit 1 +} + +# Parse the command line. +parse_command_line() { + + VERBOSE_MODE=1 + DEBUG_MODE=0 + CHECK_MODE=1 + PARAMS=() + while (("$#")); do + case "$1" in + + -u | --upgrade) + CHECK_MODE=0 + shift + ;; + -q | --quiet) + VERBOSE_MODE=0 + shift + ;; + -x | --debug) + DEBUG_MODE=1 + shift + ;; + -h | --help) + show_usage + ;; + -*) # unsupported flags + echo "Error: Unsupported flag ${1}" >&2 + show_usage + ;; + *) # preserve positional arguments + PARAMS+=("${1}") + shift + ;; + esac + done + + if [[ ${DEBUG_MODE} -ne 0 ]]; then + set -x + fi +} + +# Parse any command line values. +parse_command_line "$@" + +# Clean entrance into the script. +start_process + +# Both tools have issues with UTF-8 on Windows unless these are applied. +export PYTHONIOENCODING=utf-8 +# set PYTHONIOENCODING=utf-8 + +check_for_updates() { + local PACKAGE_TYPE=${1} + local DEV_FLAG=${2:-} + + verbose_echo " Checking ${PACKAGE_TYPE} packages section of Pipfile..." + verbose_echo " Exporting ${PACKAGE_TYPE} packages section into requirements file." + # shellcheck disable=SC2086 # Double quote to prevent splitting and globbing. + if ! pipenv run python utils/generate_requirements_file.py ${DEV_FLAG} >"${TEMP_FILE2}"; then + complete_process 1 "Error occurred generating ${PACKAGE_TYPE} requirements file." + fi + + verbose_echo " Checking ${PACKAGE_TYPE} packages requirements file." + if ! pipenv run pcu "${TEMP_FILE2}" >"${TEMP_FILE}" 2>&1; then + cat "${TEMP_FILE}" + complete_process 1 "Error occurred checking Pipfile packages updates." + fi + + # shellcheck disable=SC2086 # Double quote to prevent splitting and globbing. + if ! PIPFILE_PACKAGES_NEEDING_UPDATING=$(pipenv run python utils/count_remaining_pcu_packages.py ${DEV_FLAG} "${TEMP_FILE}"); then + complete_process 1 "Error occurred checking filtered Pipfile packages." + fi + if [[ "${PIPFILE_PACKAGES_NEEDING_UPDATING}" != "0" ]]; then + echo " ${PIPFILE_PACKAGES_NEEDING_UPDATING} Pipfile packages are eligible for updating." + # shellcheck disable=SC2086 # Double quote to prevent splitting and globbing. + pipenv run python utils/count_remaining_pcu_packages.py ${DEV_FLAG} "${TEMP_FILE}" --list + NEED_UPDATE=1 + fi +} + +perform_updates() { + local PACKAGE_TYPE=${1} + local DEV_FLAG=${2:-} + local IMPORT_FLAGS=${3:-} + + verbose_echo " Updating ${PACKAGE_TYPE} packages section of Pipfile..." + verbose_echo " Exporting ${PACKAGE_TYPE} packages section into requirements file." + # shellcheck disable=SC2086 # Double quote to prevent splitting and globbing. + if ! pipenv run python utils/generate_requirements_file.py ${DEV_FLAG} >"${TEMP_FILE2}"; then + complete_process 1 "Error occurred generating ${PACKAGE_TYPE} requirements file." + fi + + verbose_echo " Upgrading ${PACKAGE_TYPE} packages requirements file." + if ! pipenv run pcu --upgrade "${TEMP_FILE2}" >"${TEMP_FILE}" 2>&1; then + cat "${TEMP_FILE}" + complete_process 1 "Error occurred updating Pipfile packages." + fi + + verbose_echo " Importing upgraded requirements file back into ${PACKAGE_TYPE} packages section." + # shellcheck disable=SC2086 # Double quote to prevent splitting and globbing. + if ! pipenv install -r "${TEMP_FILE2}" ${IMPORT_FLAGS} >"${TEMP_FILE}" 2>&1; then + cat "${TEMP_FILE}" + complete_process 1 "Error occurred installing updated ${PACKAGE_TYPE} packages into pipenv." + fi +} + +if [[ ${CHECK_MODE} -eq 1 ]]; then + + verbose_echo "Checking for Pre-Commit package updates..." + NEED_UPDATE=0 + if ! pipenv run pre-commit-update --dry-run >"${TEMP_FILE}" 2>&1; then + echo "One or more Pre-Commit packages are eligible for updating." + NEED_UPDATE=1 + fi + + verbose_echo "Checking for Pipfile package updates..." + + check_for_updates "standard" "" + check_for_updates "development" "--dev" + + verbose_echo "" + if [[ ${NEED_UPDATE} -eq 0 ]]; then + verbose_echo "All project dependencies are up to date." + else + complete_process 2 "One or more project dependencies can be updated." + fi +else + verbose_echo "Performing any required Pre-Commit package updates..." + if ! pipenv run pre-commit-update >"${TEMP_FILE}" 2>&1; then + cat "${TEMP_FILE}" + complete_process 1 "Error occurred updating Pre-Commit packages." + fi + + verbose_echo "Performing any required Pipfile package updates..." + + perform_updates "standard" "" "" + perform_updates "development" "--dev" "--categories=dev-packages" +fi + +# Normal exit from the script. +complete_process 0 diff --git a/clean.sh b/clean.sh index d632cbc..c17abdb 100644 --- a/clean.sh +++ b/clean.sh @@ -12,7 +12,7 @@ TEMP_FILE=$(mktemp /tmp/"${SCRIPT_NAME}".XXXXXXXXX) SCRIPT_TITLE="Analyzing project cleanliness" # Perform any cleanup required by the script. -# shellcheck disable=SC2317 # Unreachable code +# shellcheck disable=SC2329 cleanup_function() { if [[ ${VERBOSE_MODE} -ne 0 ]]; then @@ -402,6 +402,14 @@ analyze_pylint_suppressions() { fi } +look_for_upgrades() { + + verbose_echo "{Looking for Python package upgrades in Pre-Commit and Pipenv.}" + if ! ./check_project_dependencies.sh; then + complete_process 1 "{One or more project dependencies can be updated. Please run './check_project_dependencies.sh --upgrade' to update them.}" + fi +} + execute_test_suite() { echo "" @@ -474,6 +482,8 @@ if [[ ${PERFORMANCE_ONLY_MODE} -eq 0 ]]; then find_unused_pylint_suppressions + look_for_upgrades + execute_test_suite if ! ./package-release.sh; then diff --git a/cookieslicer.json b/cookieslicer.json index 7ea3fd5..1f2b8fd 100644 --- a/cookieslicer.json +++ b/cookieslicer.json @@ -1 +1 @@ -{"config_version": 4} \ No newline at end of file +{"config_version": 5} diff --git a/newdocs/src/changelog.md b/newdocs/src/changelog.md index c9332b1..8d01254 100644 --- a/newdocs/src/changelog.md +++ b/newdocs/src/changelog.md @@ -2,93 +2,17 @@ ## Unversioned - In Main, Not Released - -### Fixed and Added + +### Added - None -## Version 0.9.0 - Date: 2025-06-30 + +### Changed - -### Fixed and Added - -- Added proper documentation. -- Hosting documentation at ReadTheDocs. -- [Issue 148](https://github.com/jackdewinter/application_properties/issues/148) - - Added JSON5 support, which includes support for JSON comments. - -## Version 0.8.3 - Date: 2025-06-15 - - -### Fixed and Added - -- [Issue 271](https://github.com/jackdewinter/application_properties/issues/271) - - Applying project templates across projects. - -## Version 0.8.2 - Date: 2024-01-28 - - -### Fixed and Added - -- [Issue 195](https://github.com/jackdewinter/application_properties/issues/195) - - Added YAML support for loading properties -- Fixed issue with installation not specifying `pyyaml>=6.0` as an installation dependency - -## Version 0.8.0 - Date: 2023-07-16 - - -### Fixed and Added - -- [Issue 192](https://github.com/jackdewinter/application_properties/issues/192) - - moved useful utility functions from PyMarkdown project into application_properties - project -- [Issue 156](https://github.com/jackdewinter/application_properties/issues/156) - - brought into alignment with other projects, for ease of maintenance - - split up Pipfile dependencies into dev-packages and packages -- updating dependencies - 2023Jul15 -- updating dependencies - 2023Jul02 - -## Version 0.7.0 - Date: 2023-04-22 - - -### Fixed and Added - -- [Issue 137](https://github.com/jackdewinter/application_properties/issues/137) - - to support multiple configurations, added clear_map flag to Json loader - - refactoring to clean things up for upcoming changes -- [Issue 2](https://github.com/jackdewinter/application_properties/issues/2) - - added ability to translate from string to other forms - - controlled by flag, and only occurs on pure strings, not any strings with - any typing - - i.e. only manual set and "config" files are untyped, so only those are - affected -- [Issue 145](https://github.com/jackdewinter/application_properties/issues/145) - - added TOML configuration file support as a typed configuration file -- upgraded tooling packages to latest version - -## Version 0.6.0 - Date: xxxx-xx-xx - -- quick release to help PyMarkdown project - -## Version 0.5.2 - Date: 2022-04-01 - - -### Fixed and Added - -- Added `py.typed` file to ensure that type hints are consumed by package. -- Added `__all__` variable to `__init__.py` to resolve mypy error - -## Version 0.5.1 - Date: 2022-04-01 - - -### Fixed and Added - -- Adding Python typing hints -- Cleaning up project infrastructure to current PyMarkdown standards. - -## Version 0.5.0 - Date: 2021-06-16 +- None - -### Fixed and Added + +### Fixed -- Initial release +- None diff --git a/newdocs/src/contribute.md b/newdocs/src/contribute.md index 5842e77..574f816 100644 --- a/newdocs/src/contribute.md +++ b/newdocs/src/contribute.md @@ -29,7 +29,7 @@ team. If you volunteer to help, we can provide guidance and help to you at a low cost to us. If what you want to do is not contrary to the direction of the project, we can usually work something out to help you meet your needs. - + **OR** Let us say that you want to get involved with a project and help. You diff --git a/newdocs/src/user-guide.md b/newdocs/src/user-guide.md index b4ce2d7..69d424a 100644 --- a/newdocs/src/user-guide.md +++ b/newdocs/src/user-guide.md @@ -31,7 +31,7 @@ us know. ## Starting with Something Simple - + ### Goals The goals for this section are to introduce: @@ -40,7 +40,7 @@ The goals for this section are to introduce: - the `get_string_property` function used to query an `ApplicationProperties` instance which has loaded zero or more data sources - + ### Example Starting on our journey of using the `application_properties` package, @@ -75,7 +75,7 @@ did_error = False property_value = (None) ``` - + ### Explanation Starting with the main block at the second half of the example, the script @@ -105,7 +105,7 @@ most applications will want to provide an alternative way to manage the error. However, instead of trying to second guess the application, we defined a default handler function that meets our "work by default" philosophy. - + ### Things To Try Experiment with the following to see what happens, executing the script again @@ -118,7 +118,7 @@ when needed: ## Adding A Configuration File - + ### Goals The goals for this section are to introduce: @@ -128,7 +128,7 @@ The goals for this section are to introduce: - how the loading of a configuration file influences the configuration items and their retrieval - + ### Example With the basics taken care of, the next step to take on our journey involves the @@ -170,7 +170,7 @@ did_error = False property_value = 2 ``` - + ### Explanation To facilitate the loading of the configuration file `.sample`, the function @@ -189,7 +189,7 @@ that is passed as its first parameter. Therefore, when the `get_string_property` function is invoked, the configuration manager finds the `mode` property and relay its value as `2`. - + ### Things To Try Experiment with the following to see what happens, executing the script again @@ -204,7 +204,7 @@ when needed: ## Get Property Functions - + ### Goals The goals for this section are to introduce: @@ -214,7 +214,7 @@ The goals for this section are to introduce: - the `get_integer_property` function and `get_boolean_property` used to query an `ApplicationProperties` instance - + ### Example To make use of the specific configuration file from the previous section, we need @@ -239,7 +239,7 @@ integer_property_value = 3 boolean_property_value = False ``` - + ### Explanation For the retrieval of configuration item values, three changes were made. The first @@ -278,7 +278,7 @@ stored [hierarchically](./getting-started.md#hierarchical) is important, allowin both the application and its user to understand what configuration items are logically grouped together by the application. - + ### Things To Try Experiment with the following to see what happens, executing the script again @@ -291,7 +291,7 @@ when needed: ## Project Default Configuration Files - + ### Goals The goals for this section are to introduce: @@ -299,7 +299,7 @@ The goals for this section are to introduce: - default configuration files not specified on the command line - configuration layers and how they interact with each other - + ### Example For this example, create a new file `pyproject.toml` in the current directory @@ -346,7 +346,7 @@ some_when_value = 2 some_thing_value = 3 ``` - + ### Explanation The changes made to the example's `MultisourceConfigurationLoader` section add @@ -416,7 +416,7 @@ needs of the tool where this documentation is being built. We feel strongly that this feature is very important in providing a flexible configuration management system. - + ### Things To Try Experiment with the following to see what happens, executing the script again when @@ -430,7 +430,7 @@ needed: ## Setting Individual Properties - + ### Goals The goals for this section are to introduce: @@ -439,7 +439,7 @@ The goals for this section are to introduce: - one option for setting specific properties from the command line - the use of special characters when specifying non-string command line properties - + ### Example For this example, change the lower half of the example's content to: @@ -474,7 +474,7 @@ some_when_value = 12 verbosity_value = 3 ``` - + ### Explanation This example is lengthy, so it bears breaking down into distinct components. @@ -519,7 +519,7 @@ to the configuration item type table, no special `$` characters at the start of the value leave the value's type as a string. For the two values that start with the `$#` sequence, that means to treat the value as an integer type. - + ### Things To Try Experiment with the following to see what happens, executing the script again @@ -532,7 +532,7 @@ when needed: ## Strict Mode and Type Conversion When Getting Property Values - + ### Goals The goals for this section are to introduce: @@ -544,7 +544,7 @@ Please note that `strict_mode` and `convert_untyped_if_possible` can both be set at when the instance of the `ApplicationProperties` class is created. However, `strict_mode` may also be specified at the `get_*_property` level. - + ### Example For this example, create a new python file and set its content to: @@ -606,7 +606,7 @@ other_value = Exception(The value for property 'some.other-number' must be of ty other_value = 1 ``` - + ### Explanation When getting the value to return from any of the `get_*_property` functions, most @@ -649,7 +649,7 @@ that our `convert_untyped_if_possible` mode will allow for this to happen, becom more flexible and responsive the needs of applications... while allowing `strict_mode` to be used at the same time. - + ### Things To Try Experiment with the following to see what happens, executing the script again when @@ -662,7 +662,7 @@ needed: ## Required Properties and Validation Functions - + ### Goals The goals for this section are to introduce: @@ -670,7 +670,7 @@ The goals for this section are to introduce: - required properties for the `get_*_property` functions - validation functions for the `get_string_property` and `get_integer_property` functions - + ### Example For this example, create a new python file and set its content to: @@ -716,7 +716,7 @@ some_when_value = None some_when_value = Exception(The value for property 'some.when' is not valid: Value 'tomorrow' is not 'me', 'you' or 'them') ``` - + ### Explanation The first example shows a request to the configuration manager for the value of @@ -753,7 +753,7 @@ already been performed. What we are trying to say is that the `valid_value_fn` function should only worry about one thing: checking to see if the value passed in, which is already correctly typed, is valid for the scenario in question. - + ### Things To Try Experiment with the following to see what happens, executing the script again when diff --git a/package-release.sh b/package-release.sh index 9f03fa4..5651b1d 100644 --- a/package-release.sh +++ b/package-release.sh @@ -12,7 +12,7 @@ TEMP_FILE=$(mktemp /tmp/"${SCRIPT_NAME}".XXXXXXXXX) SCRIPT_TITLE="Creation of application package" # Perform any cleanup required by the script. -# shellcheck disable=SC2317 # Unreachable code +# shellcheck disable=SC2329 cleanup_function() { # If the temp file was used, get rid of it. @@ -132,16 +132,16 @@ load_properties_from_file() { } # Check the packaging before we use it. -check_with_pyroma() { +# check_with_pyroma() { - if [ "${VERBOSE_MODE}" -ne 0 ]; then - echo "Checking the application packaging against standards." - fi - if ! pipenv run pyroma -n 10 "${SCRIPT_DIR}" >"${TEMP_FILE}" 2>&1; then - cat "${TEMP_FILE}" - complete_process 1 "Packaging script did not pass 'pyroma' inspection." - fi -} +# if [ "${VERBOSE_MODE}" -ne 0 ]; then +# echo "Checking the application packaging against standards." +# fi +# if ! pipenv run pyroma -n 10 "${SCRIPT_DIR}" >"${TEMP_FILE}" 2>&1; then +# cat "${TEMP_FILE}" +# complete_process 1 "Packaging script did not pass 'pyroma' inspection." +# fi +# } # Remove the previous artifacts to allow us to do this cleanly and predictably. remove_previous_packaging_directories() { @@ -199,7 +199,7 @@ load_properties_from_file # Main body of the script. -check_with_pyroma +# check_with_pyroma remove_previous_packaging_directories diff --git a/project.properties b/project.properties index f5c8eab..f331409 100644 --- a/project.properties +++ b/project.properties @@ -1,2 +1,4 @@ # Name of the module PYTHON_MODULE_NAME=application_properties +PACKAGE_UPDATE_EXCLUDE_LIST=typing-extensions,tomli,pyyaml,pyjson5 +PACKAGE_UPDATE_DEV_EXCLUDE_LIST=sourcery diff --git a/ptest.sh b/ptest.sh index fbf446c..8f41cbd 100644 --- a/ptest.sh +++ b/ptest.sh @@ -40,7 +40,7 @@ load_properties_from_file() { } # Perform any cleanup required by the script. -# shellcheck disable=SC2317 # Unreachable code +# shellcheck disable=SC2329 cleanup_function() { # If the temp file was used, get rid of it. @@ -106,6 +106,7 @@ show_usage() { echo " -w,--workers Enabled testing with multiple workers." echo " -k,--keyword [keyword] Execute only the tests matching the specified keyword." echo " -p,--publish Publish the project summaries of previously executed tests." + echo " -v,--test-verbose Display a log debug information about each test execution." echo " -x,--debug Display debug information about the script as it executes." echo " -q,--quiet Do not display detailed information during execution." echo " -h,--help Display this help text." @@ -123,6 +124,7 @@ parse_command_line() { PUBLISH_MODE=0 MULTIPLE_WORKER_ARGS= KEYWORD_ARG= + TEST_VERBOSE_MODE= FAILURE_ARGS="--maxfail=5" GENERATE_HTML_MODE=1 PARAMS=() @@ -165,6 +167,10 @@ parse_command_line() { VERBOSE_MODE=0 shift ;; + -v | --test-verbose) + TEST_VERBOSE_MODE="--log-cli-level=DEBUG" + shift + ;; -x | --debug) DEBUG_MODE=1 shift @@ -264,12 +270,20 @@ execute_tests() { # Run the tests. if [[ ${VERBOSE_MODE} -ne 0 ]]; then # shellcheck disable=SC2086 # Double quote to prevent splitting and globbing. - if ! pipenv run pytest ${MULTIPLE_WORKER_ARGS} ${FAILURE_ARGS} "${KEYWORD_ARG[@]}" "${pytest_args[@]}"; then + if ! pipenv run pytest \ + --log-format="%(asctime)s %(levelname)s %(message)s" \ + --log-date-format="%Y-%m-%dT%H:%M:%S.%f" \ + ${TEST_VERBOSE_MODE} \ + ${MULTIPLE_WORKER_ARGS} ${FAILURE_ARGS} "${KEYWORD_ARG[@]}" "${pytest_args[@]}"; then TEST_EXECUTION_SUCCEEDED=0 fi else # shellcheck disable=SC2086 # Double quote to prevent splitting and globbing. - if ! pipenv run pytest ${MULTIPLE_WORKER_ARGS} ${FAILURE_ARGS} "${KEYWORD_ARG[@]}" "${pytest_args[@]}" >"${TEMP_FILE}" 2>&1; then + if ! pipenv run pytest \ + --log-format="%(asctime)s %(levelname)s %(message)s" \ + --log-date-format="%Y-%m-%dT%H:%M:%S.%f" \ + ${TEST_VERBOSE_MODE} \ + ${MULTIPLE_WORKER_ARGS} ${FAILURE_ARGS} "${KEYWORD_ARG[@]}" "${pytest_args[@]}" >"${TEMP_FILE}" 2>&1; then TEST_EXECUTION_SUCCEEDED=0 fi fi diff --git a/setup.py b/setup.py index 4aaf8c0..687ed23 100644 --- a/setup.py +++ b/setup.py @@ -67,7 +67,7 @@ def get_package_modules(): MODULE_NAME = "application_properties" PACKAGE_NAME = "application_properties" SEMANTIC_VERSION = get_semantic_version() -MINIMUM_PYTHON_VERSION = "3.9.0" +MINIMUM_PYTHON_VERSION = "3.10.0" ONE_LINE_DESCRIPTION = get_description() LONG_DESCRIPTION = load_readme_file() @@ -78,7 +78,6 @@ def get_package_modules(): "Development Status :: 4 - Beta", "Environment :: Console", "Intended Audience :: Developers", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", diff --git a/test/test_multisource_configuration_loader.py b/test/test_multisource_configuration_loader.py index e1c0348..b0601b5 100644 --- a/test/test_multisource_configuration_loader.py +++ b/test/test_multisource_configuration_loader.py @@ -1,5 +1,5 @@ """ -Moduole for tests of the multisource configuration loader. +Moduole for tests of the multisource configuration loader. NOTE: These tests are for the configuration loader, not to test the correctness of any of the individual loaders themselves. diff --git a/utils/count_remaining_pcu_packages.py b/utils/count_remaining_pcu_packages.py new file mode 100644 index 0000000..8d1a3df --- /dev/null +++ b/utils/count_remaining_pcu_packages.py @@ -0,0 +1,85 @@ +""" +Module to count the number of packages that can be updated, as output from 'pcu'. +""" + +import argparse +import configparser +from typing import List + + +def __handle_arguments(): + parser = argparse.ArgumentParser( + description="Analyze PyTest tests to determine if extra coverage is present." + ) + parser.add_argument( + "-d", + "--dev", + dest="export_dev_packages", + action="store_true", + default=False, + help="output the dev-packages section instead of packages section", + ) + parser.add_argument( + "-l", + "--list", + dest="list_items", + action="store_true", + default=False, + help="output the dev-packages section instead of packages section", + ) + parser.add_argument("file_name", action="store", help="file_to_consume") + + return parser.parse_args() + + +def __load_package_exclude_list_from_properties_file(use_dev_list: bool) -> List[str]: + + with open("project.properties", "r", encoding="utf-8") as properties_file: + properties_text = properties_file.read() + config = configparser.RawConfigParser() + config.read_string(f"[main]\n{properties_text}") + ss = config.get( + "main", + ( + "PACKAGE_UPDATE_DEV_EXCLUDE_LIST" + if use_dev_list + else "PACKAGE_UPDATE_EXCLUDE_LIST" + ), + fallback="", + ).split(",") + return [i.strip() for i in ss] + + +parsed_args = __handle_arguments() +exclude_list = __load_package_exclude_list_from_properties_file( + parsed_args.export_dev_packages +) + +with open(parsed_args.file_name, "r", encoding="utf-8") as file: + text = file.read() +has_extra_parameters = parsed_args.list_items + +file_lines = text.splitlines() +have_seen_start = False +non_excluded_packages: List[str] = [] +for line in file_lines: + line = line.strip() + if line.startswith("In "): + have_seen_start = True + continue + if not have_seen_start or not line: + continue + if line.startswith("All dependencies match") or line.startswith("Run pcu"): + break + while " " in line: + line = line.replace(" ", " ") + x = line.split(" ") + if x[0] not in exclude_list: + if has_extra_parameters: + print( + f" Package '{x[0]}' has version '{x[1]}' and can be updated to version '{x[3]}'" + ) + non_excluded_packages.append(x[0]) + +if not has_extra_parameters: + print(len(non_excluded_packages)) diff --git a/utils/extract_python_version_from_pipfile.py b/utils/extract_python_version_from_pipfile.py new file mode 100644 index 0000000..409dff2 --- /dev/null +++ b/utils/extract_python_version_from_pipfile.py @@ -0,0 +1,29 @@ +""" +Module to extract the Python version from a Pipfile. +""" + +import re +import sys + +# pylint: disable=broad-exception-caught +try: + with open("Pipfile", "r", encoding="utf-8") as readme_file: + line_in_file = readme_file.read().split("\n") + + requires_index = line_in_file.index("[requires]") + + PYTHON_VERSION_REGEX = r"^python_version\s=\s\"3\.(\d+)\"$" + version_regex_match = re.match( + PYTHON_VERSION_REGEX, line_in_file[requires_index + 1] + ) + assert ( + version_regex_match is not None + ), "Python version line did not follow the requires line." + print(f"3.{version_regex_match.group(1)}") + +except BaseException as this_exception: # noqa: B036 + print(f"Exception: {this_exception}") + sys.exit(1) +# pylint: enable=broad-exception-caught + +sys.exit(0) diff --git a/utils/generate_dependencies_file.py b/utils/generate_dependencies_file.py new file mode 100644 index 0000000..7349d28 --- /dev/null +++ b/utils/generate_dependencies_file.py @@ -0,0 +1,174 @@ +"""Module to generate a combined dependencies file from pre-commit and Pipfile.""" + +import json +import os +import subprocess +import sys +from dataclasses import dataclass +from typing import Dict, List, Optional, cast + +from pip_check_updates.parser import load_dependencies + + +@dataclass +class Icons: + """Dataclass to hold the different strings that pre-commit-update can output for the current state.""" + + icon: str + icon_alt: str + text: str + + +icons_map = { + "exclude": Icons(icon="★", icon_alt="*", text="[exclude]"), + "keep": Icons(icon="◉", icon_alt="●", text="[keep]"), + "no_update": Icons(icon="✔", icon_alt="√", text="[no-update]"), + "update": Icons(icon="✘", icon_alt="×", text="[update]"), + "warning": Icons(icon="⚠", icon_alt="▲", text="[warning]"), +} + + +def __match_icons(first_column_value: str) -> Optional[str]: + return next( + ( + i + for i, matching_icons in icons_map.items() + if first_column_value + in (matching_icons.icon, matching_icons.icon_alt, matching_icons.text) + ), + None, + ) + + +def __load_precommit_packages_and_versions(error_messages: List[str]) -> Dict[str, str]: + + package_version_list: List[List[str]] = [] + try: + with subprocess.Popen( + ["pre-commit-update", "--dry-run", "--verbose"], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, + ) as p: + status_code = p.wait() + if status_code in [0, 1]: + __load_precommit_packages_and_versions_translate_ouptut( + p.stdout.read(), package_version_list + ) + else: + formatted_error = ( + f"Pre-commit update command failed with status code {status_code}:" + ) + for i in p.stderr.read().split("\n"): + i = i.strip() + formatted_error += f"\n {i}" + error_messages.append(formatted_error) + + except OSError as this_exception: + formatted_error = ( + f"Pre-commit update command failed to run: {str(this_exception)}." + ) + error_messages.append(formatted_error) + + package_version_map: Dict[str, str] = {} + for i in package_version_list: + package_name = i[1] + old_version = i[2] + if package_name in package_version_map: + registered_version = package_version_map[package_name] + if registered_version != old_version: + error_messages.append( + f"Pre-commit Conflict detected within file `.pre-commit-config.yaml` for package '{package_name}': '{registered_version}' vs '{old_version}'" + ) + else: + package_version_map[package_name] = old_version + + return package_version_map + + +def __load_precommit_packages_and_versions_translate_ouptut( + data: str, version_list: List[List[str]] +) -> None: + + for next_line in data.split("\n"): + next_line = next_line.strip() + if not next_line: + continue + split_line = list(next_line.split(" ")) + matched_icon = __match_icons(split_line[0]) + assert ( + matched_icon + ), f"Unrecognized icon in pre-commit output: '{split_line[0]}'" + split_line[0] = matched_icon + assert split_line[2] == "-" + del split_line[2] + if len(split_line) > 3 and split_line[3] == "->": + del split_line[3] + version_list.append(split_line) + + +# pylint: disable=broad-exception-caught +def __load_pipfile_packages_and_versions(error_messages: List[str]) -> Dict[str, str]: + pipfile_map: Dict[str, str] = {} + try: + pipfile_dependencies = cast( + List[List[str]], load_dependencies("Pipfile", False, []) + ) + for next_dependency in pipfile_dependencies: + pipfile_map[next_dependency[1]] = next_dependency[2] + except BaseException as this_exception: # noqa: B036 + error_messages.append(f"Failed to load Pipfile: {str(this_exception)}") + return pipfile_map + + +# pylint: enable=broad-exception-caught + +# pylint: disable=broad-exception-caught + + +def __abc(): + error_messages: List[str] = [] + + pre_commit_map = __load_precommit_packages_and_versions(error_messages) + pipefile_map = __load_pipfile_packages_and_versions(error_messages) + if error_messages: + error_messages.append( + "Errors detected during load. Unable to continue with merge." + ) + else: + for pre_commit_key, pre_commit_value in pre_commit_map.items(): + if ( + pre_commit_key in pipefile_map + and pre_commit_value != pipefile_map[pre_commit_key] + ): + error_messages.append( + f"Conflict detected for package '{pre_commit_key}': pre-commit version '{pre_commit_value}' vs Pipfile version '{pipefile_map[pre_commit_key]}'" + ) + pipefile_map[pre_commit_key] = pre_commit_value + if error_messages: + error_messages.append( + "Errors detected during merge. Unable to continue with output." + ) + if not error_messages: + try: + with open( + os.path.join(".", "publish", "dependencies.json"), + "wt", + encoding="utf-8", + ) as output_file: + json.dump(pipefile_map, output_file, indent=4) + except BaseException as this_exception: # noqa: B036 + error_messages.append( + f"Failed to write combined dependencies file: {str(this_exception)}" + ) + + if error_messages: + print("\n".join(error_messages)) + sys.exit(1) + + +# pylint: enable=broad-exception-caught + + +if __name__ == "__main__": + __abc() diff --git a/utils/generate_requirements_file.py b/utils/generate_requirements_file.py new file mode 100644 index 0000000..7e84f7a --- /dev/null +++ b/utils/generate_requirements_file.py @@ -0,0 +1,96 @@ +""" +Module to generate a targetted requirements.txt file from a Pipfile. Only the [packages] sectopmn +or [dev-packages] section is exported, and only the package names listed in the file are exported. + +Other tools will export all packages (listed and discovered) to a requirements.txt file. +""" + +import argparse +import configparser +from typing import Dict, List, Tuple, cast + +import toml +from pip_check_updates.parser import load_dependencies + +# pylint: disable=broad-exception-caught + + +def __load_pipfile_packages_and_versions( + error_list: List[str], +) -> Tuple[Dict[str, str], List[str], List[str]]: + pipfile_map: Dict[str, str] = {} + package_list = [] + dev_package_list = [] + try: + pipfile_dependencies = cast( + List[List[str]], load_dependencies("Pipfile", False, []) + ) + for next_dependency in pipfile_dependencies: + pipfile_map[next_dependency[1]] = next_dependency[2] + + with open("Pipfile", "rt", encoding="utf-8") as f: + config = toml.load(f) + package_list: List[str] = list(config["packages"].keys()) + dev_package_list: List[str] = list(config["dev-packages"].keys()) + except BaseException as this_exception: # noqa: B036 + error_list.append(f"Failed to load Pipfile: {str(this_exception)}") + return pipfile_map, package_list, dev_package_list + + +# pylint: enable=broad-exception-caught + + +def __handle_arguments(): + parser = argparse.ArgumentParser( + description="Analyze PyTest tests to determine if extra coverage is present." + ) + parser.add_argument( + "-d", + "--dev", + dest="export_dev_packages", + action="store_true", + default=False, + help="output the dev-packages section instead of packages section", + ) + + return parser.parse_args() + + +def __load_package_exclude_list_from_properties_file(use_dev_list: bool) -> List[str]: + + with open("project.properties", "r", encoding="utf-8") as file: + text = file.read() + config = configparser.RawConfigParser() + config.read_string(f"[main]\n{text}") + ss = config.get( + "main", + ( + "PACKAGE_UPDATE_DEV_EXCLUDE_LIST" + if use_dev_list + else "PACKAGE_UPDATE_EXCLUDE_LIST" + ), + fallback="", + ).split(",") + return [i.strip() for i in ss] + + +if __name__ == "__main__": + error_messages: List[str] = [] + + parsed_args = __handle_arguments() + + tt = __load_package_exclude_list_from_properties_file( + parsed_args.export_dev_packages + ) + + pipefile_map, package_name_list, dev_package_name_list = ( + __load_pipfile_packages_and_versions(error_messages) + ) + + for package_name in ( + dev_package_name_list if parsed_args.export_dev_packages else package_name_list + ): + if package_name in tt: + continue + print(f"{package_name}=={pipefile_map[package_name]}") + print("", flush=True) diff --git a/utils/verify_install_requirements.py b/utils/verify_install_requirements.py index 540f73c..71da077 100644 --- a/utils/verify_install_requirements.py +++ b/utils/verify_install_requirements.py @@ -59,14 +59,14 @@ def __read_requirements_file() -> Dict[str, Tuple[str, str]]: pipfile_map = __read_pipfile() print(pipfile_map) -ERRORS_FOUND = 0 +errors_found = 0 for next_requirement_name, next_requirement_value in requirements_map.items(): print(f"Verifying install requirement package '{next_requirement_name}'.") if next_requirement_name not in pipfile_map: print( f" Install requirement package '{next_requirement_name}' not found in Pipfile." ) - ERRORS_FOUND += 1 + errors_found += 1 else: pipfile_value = pipfile_map[next_requirement_name] pipfile_value = pipfile_value[1:-1] @@ -75,7 +75,7 @@ def __read_requirements_file() -> Dict[str, Tuple[str, str]]: print( f" Pipfile package '{next_requirement_name}' has a value of '{pipfile_value}' that does not equal the install requirement package of '{next_requirement_value}'." ) - ERRORS_FOUND += 1 + errors_found += 1 else: print(f" Install requirement package '{next_requirement_name}' verified.") @@ -85,10 +85,10 @@ def __read_requirements_file() -> Dict[str, Tuple[str, str]]: print( f" Pipfile package '{next_pipfile_name}' not found in install requirements." ) - ERRORS_FOUND += 1 + errors_found += 1 else: print(f" Pipfile package '{next_pipfile_name}' verified.") -print(f"Errors found: {ERRORS_FOUND}") -if ERRORS_FOUND > 0: +print(f"Errors found: {errors_found}") +if errors_found > 0: sys.exit(1)