From d664e0a816446b3e0a6924b57447fd2bd07d9cd2 Mon Sep 17 00:00:00 2001 From: Sean Stewart Date: Thu, 25 Jul 2024 12:24:47 -0400 Subject: [PATCH] docs: Scaffold support for api docs. --- docs/css/typelib.css | 42 + docs/index.md | 17 + mkdocs.yml | 128 +++ poetry.lock | 1378 ++++++++++++++++++++++++++--- pyproject.toml | 9 + scripts/gen_ref_pages.py | 35 + src/typelib/binding.py | 66 +- src/typelib/codec.py | 55 +- src/typelib/constants.py | 6 +- src/typelib/graph.py | 43 +- src/typelib/interchange.py | 47 +- src/typelib/marshal/__init__.py | 47 + src/typelib/marshal/api.py | 13 +- src/typelib/marshal/routines.py | 44 +- src/typelib/py/classes.py | 32 +- src/typelib/py/compat.py | 2 - src/typelib/py/contrib.py | 2 - src/typelib/py/frames.py | 17 +- src/typelib/py/future.py | 31 +- src/typelib/py/inspection.py | 137 ++- src/typelib/py/refs.py | 23 +- src/typelib/serdes.py | 62 +- src/typelib/unmarshal/__init__.py | 35 + src/typelib/unmarshal/api.py | 4 +- src/typelib/unmarshal/routines.py | 331 +++---- 25 files changed, 2101 insertions(+), 505 deletions(-) create mode 100644 docs/css/typelib.css create mode 100644 docs/index.md create mode 100644 mkdocs.yml create mode 100644 scripts/gen_ref_pages.py diff --git a/docs/css/typelib.css b/docs/css/typelib.css new file mode 100644 index 0000000..dd0927f --- /dev/null +++ b/docs/css/typelib.css @@ -0,0 +1,42 @@ +/* Indentation. */ +div.doc-contents:not(.first) { + padding-left: 25px; + border-left: .05rem solid var(--md-typeset-table-color); +} + +/* Mark external links as such. */ +a.external::after, +a.autorefs-external::after { + /* https://primer.style/octicons/arrow-up-right-24 */ + mask-image: url('data:image/svg+xml,'); + -webkit-mask-image: url('data:image/svg+xml,'); + content: ' '; + + display: inline-block; + vertical-align: middle; + position: relative; + + height: 1em; + width: 1em; + background-color: var(--md-typeset-a-color); +} + +a.external:hover::after, +a.autorefs-external:hover::after { + background-color: var(--md-accent-fg-color); +} + +/* Avoid breaking parameters name, etc. in table cells. */ +td code { + word-break: normal !important; +} + +/*[data-md-color-scheme="default"] {*/ +/* --doc-symbol-parameter-fg-color: #d3a81b;*/ +/* --doc-symbol-parameter-bg-color: #d3a81b1a;*/ +/*}*/ + +/*[data-md-color-scheme="slate"] {*/ +/* --doc-symbol-parameter-fg-color: #dfbe50;*/ +/* --doc-symbol-parameter-bg-color: #dfbe501a;*/ +/*}*/ \ No newline at end of file diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..000ea34 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,17 @@ +# Welcome to MkDocs + +For full documentation visit [mkdocs.org](https://www.mkdocs.org). + +## Commands + +* `mkdocs new [dir-name]` - Create a new project. +* `mkdocs serve` - Start the live-reloading docs server. +* `mkdocs build` - Build the documentation site. +* `mkdocs -h` - Print help message and exit. + +## Project layout + + mkdocs.yml # The configuration file. + docs/ + index.md # The documentation homepage. + ... # Other markdown pages, images and other files. diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..d3cbaa8 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,128 @@ +#file: noinspection YAMLSchemaValidation +site_name: typelib +site_url: https://pages.github.io/python-typelib +repo_name: seandstewart/python-typelib +repo_url: https://github.com/seandstewart/python-typelib +watch: [mkdocs.yml, README.md, CHANGELOG.md, src/typelib, docs] +theme: + name: material + features: + - search.highlight + - search.share + - search.suggest + - navigation.instant + - navigation.instant.progress + - navigation.tabs + - navigation.top + - toc.integrate + - toc.follow + - content.code.select + - content.code.copy + - content.code.annotate + palette: + # Palette toggle for automatic mode + - media: "(prefers-color-scheme)" + toggle: + icon: material/brightness-auto + name: Switch to light mode + + # Palette toggle for light mode + - media: "(prefers-color-scheme: light)" + scheme: default + primary: white + accent: black + toggle: + icon: material/brightness-7 + name: Switch to dark mode + + # Palette toggle for dark mode + - media: "(prefers-color-scheme: dark)" + scheme: slate + primary: black + accent: white + toggle: + icon: material/brightness-4 + name: Switch to system preference + font: + text: "IBM Plex Mono" + code: "Fira Code" + +extra_css: + - css/typelib.css + +plugins: + - gen-files: + scripts: + - scripts/gen_ref_pages.py + - awesome-pages + - literate-nav: + nav_file: SUMMARY.md + - mkdocstrings: + enable_inventory: true + handlers: + python: + import: + - https://docs.python.org/3/objects.inv + options: + docstring_options: + ignore_init_summary: true + docstring_section_style: list + heading_level: 1 + inherited_members: true + merge_init_into_class: true + parameter_headings: true + separate_signature: true + show_root_heading: true + show_root_full_path: false + show_signature_annotations: true + show_symbol_type_heading: true + show_symbol_type_toc: true + signature_crossrefs: true + summary: true + - open-in-new-tab + - tags + - social + - search + - autorefs + +markdown_extensions: + - abbr + - admonition + - attr_list + - footnotes + - md_in_html + - pymdownx.arithmatex + - pymdownx.betterem: + smart_enable: all + - pymdownx.caret + - pymdownx.critic + - pymdownx.details + - pymdownx.emoji: + emoji_index: !!python/name:material.extensions.emoji.twemoji + emoji_generator: !!python/name:material.extensions.emoji.to_svg + - pymdownx.highlight: + pygments_lang_class: true + anchor_linenums: true + line_spans: __span + - pymdownx.magiclink + - pymdownx.mark + - pymdownx.smartsymbols + - pymdownx.superfences: + custom_fences: + - name: mermaid + class: mermaid + format: !!python/name:pymdownx.superfences.fence_code_format + - pymdownx.tabbed: + alternate_style: true + - pymdownx.tasklist: + custom_checkbox: true + - pymdownx.tilde + - toc: + permalink: true + permalink_title: Anchor link to this section for reference + + +extra: + version: + provider: mike + diff --git a/poetry.lock b/poetry.lock index 75e9033..b5f0660 100644 --- a/poetry.lock +++ b/poetry.lock @@ -11,17 +11,169 @@ files = [ {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, ] +[[package]] +name = "babel" +version = "2.15.0" +description = "Internationalization utilities" +optional = false +python-versions = ">=3.8" +files = [ + {file = "Babel-2.15.0-py3-none-any.whl", hash = "sha256:08706bdad8d0a3413266ab61bd6c34d0c28d6e1e7badf40a2cebe67644e2e1fb"}, + {file = "babel-2.15.0.tar.gz", hash = "sha256:8daf0e265d05768bc6c7a314cf1321e9a123afc328cc635c18622a2f30a04413"}, +] + +[package.extras] +dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] + +[[package]] +name = "backports-strenum" +version = "1.3.1" +description = "Base class for creating enumerated constants that are also subclasses of str" +optional = false +python-versions = ">=3.8.6,<3.11" +files = [ + {file = "backports_strenum-1.3.1-py3-none-any.whl", hash = "sha256:cdcfe36dc897e2615dc793b7d3097f54d359918fc448754a517e6f23044ccf83"}, + {file = "backports_strenum-1.3.1.tar.gz", hash = "sha256:77c52407342898497714f0596e86188bb7084f89063226f4ba66863482f42414"}, +] + +[[package]] +name = "bracex" +version = "2.4" +description = "Bash style brace expander." +optional = false +python-versions = ">=3.8" +files = [ + {file = "bracex-2.4-py3-none-any.whl", hash = "sha256:efdc71eff95eaff5e0f8cfebe7d01adf2c8637c8c92edaf63ef348c241a82418"}, + {file = "bracex-2.4.tar.gz", hash = "sha256:a27eaf1df42cf561fed58b7a8f3fdf129d1ea16a81e1fadd1d17989bc6384beb"}, +] + [[package]] name = "cachetools" -version = "5.3.3" +version = "5.4.0" description = "Extensible memoizing collections and decorators" optional = false python-versions = ">=3.7" files = [ - {file = "cachetools-5.3.3-py3-none-any.whl", hash = "sha256:0abad1021d3f8325b2fc1d2e9c8b9c9d57b04c3932657a72465447332c24d945"}, - {file = "cachetools-5.3.3.tar.gz", hash = "sha256:ba29e2dfa0b8b556606f097407ed1aa62080ee108ab0dc5ec9d6a723a007d105"}, + {file = "cachetools-5.4.0-py3-none-any.whl", hash = "sha256:3ae3b49a3d5e28a77a0be2b37dbcb89005058959cb2323858c2657c4a8cab474"}, + {file = "cachetools-5.4.0.tar.gz", hash = "sha256:b8adc2e7c07f105ced7bc56dbb6dfbe7c4a00acce20e2227b3f355be89bc6827"}, +] + +[[package]] +name = "cairocffi" +version = "1.7.1" +description = "cffi-based cairo bindings for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "cairocffi-1.7.1-py3-none-any.whl", hash = "sha256:9803a0e11f6c962f3b0ae2ec8ba6ae45e957a146a004697a1ac1bbf16b073b3f"}, + {file = "cairocffi-1.7.1.tar.gz", hash = "sha256:2e48ee864884ec4a3a34bfa8c9ab9999f688286eb714a15a43ec9d068c36557b"}, ] +[package.dependencies] +cffi = ">=1.1.0" + +[package.extras] +doc = ["sphinx", "sphinx_rtd_theme"] +test = ["numpy", "pikepdf", "pytest", "ruff"] +xcb = ["xcffib (>=1.4.0)"] + +[[package]] +name = "cairosvg" +version = "2.7.1" +description = "A Simple SVG Converter based on Cairo" +optional = false +python-versions = ">=3.5" +files = [ + {file = "CairoSVG-2.7.1-py3-none-any.whl", hash = "sha256:8a5222d4e6c3f86f1f7046b63246877a63b49923a1cd202184c3a634ef546b3b"}, + {file = "CairoSVG-2.7.1.tar.gz", hash = "sha256:432531d72347291b9a9ebfb6777026b607563fd8719c46ee742db0aef7271ba0"}, +] + +[package.dependencies] +cairocffi = "*" +cssselect2 = "*" +defusedxml = "*" +pillow = "*" +tinycss2 = "*" + +[package.extras] +doc = ["sphinx", "sphinx-rtd-theme"] +test = ["flake8", "isort", "pytest"] + +[[package]] +name = "certifi" +version = "2024.7.4" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.6" +files = [ + {file = "certifi-2024.7.4-py3-none-any.whl", hash = "sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90"}, + {file = "certifi-2024.7.4.tar.gz", hash = "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b"}, +] + +[[package]] +name = "cffi" +version = "1.16.0" +description = "Foreign Function Interface for Python calling C code." +optional = false +python-versions = ">=3.8" +files = [ + {file = "cffi-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088"}, + {file = "cffi-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614"}, + {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743"}, + {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d"}, + {file = "cffi-1.16.0-cp310-cp310-win32.whl", hash = "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a"}, + {file = "cffi-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1"}, + {file = "cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404"}, + {file = "cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e"}, + {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc"}, + {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb"}, + {file = "cffi-1.16.0-cp311-cp311-win32.whl", hash = "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab"}, + {file = "cffi-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba"}, + {file = "cffi-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956"}, + {file = "cffi-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969"}, + {file = "cffi-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520"}, + {file = "cffi-1.16.0-cp312-cp312-win32.whl", hash = "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b"}, + {file = "cffi-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235"}, + {file = "cffi-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324"}, + {file = "cffi-1.16.0-cp38-cp38-win32.whl", hash = "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a"}, + {file = "cffi-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36"}, + {file = "cffi-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed"}, + {file = "cffi-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098"}, + {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000"}, + {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe"}, + {file = "cffi-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4"}, + {file = "cffi-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8"}, + {file = "cffi-1.16.0.tar.gz", hash = "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0"}, +] + +[package.dependencies] +pycparser = "*" + [[package]] name = "cfgv" version = "3.4.0" @@ -44,6 +196,119 @@ files = [ {file = "chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7"}, ] +[[package]] +name = "charset-normalizer" +version = "3.3.2" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, + {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, +] + +[[package]] +name = "click" +version = "8.1.7" +description = "Composable command line interface toolkit" +optional = false +python-versions = ">=3.7" +files = [ + {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, + {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + [[package]] name = "colorama" version = "0.4.6" @@ -57,63 +322,63 @@ files = [ [[package]] name = "coverage" -version = "7.5.3" +version = "7.6.0" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.8" files = [ - {file = "coverage-7.5.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a6519d917abb15e12380406d721e37613e2a67d166f9fb7e5a8ce0375744cd45"}, - {file = "coverage-7.5.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:aea7da970f1feccf48be7335f8b2ca64baf9b589d79e05b9397a06696ce1a1ec"}, - {file = "coverage-7.5.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:923b7b1c717bd0f0f92d862d1ff51d9b2b55dbbd133e05680204465f454bb286"}, - {file = "coverage-7.5.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62bda40da1e68898186f274f832ef3e759ce929da9a9fd9fcf265956de269dbc"}, - {file = "coverage-7.5.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8b7339180d00de83e930358223c617cc343dd08e1aa5ec7b06c3a121aec4e1d"}, - {file = "coverage-7.5.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:25a5caf742c6195e08002d3b6c2dd6947e50efc5fc2c2205f61ecb47592d2d83"}, - {file = "coverage-7.5.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:05ac5f60faa0c704c0f7e6a5cbfd6f02101ed05e0aee4d2822637a9e672c998d"}, - {file = "coverage-7.5.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:239a4e75e09c2b12ea478d28815acf83334d32e722e7433471fbf641c606344c"}, - {file = "coverage-7.5.3-cp310-cp310-win32.whl", hash = "sha256:a5812840d1d00eafae6585aba38021f90a705a25b8216ec7f66aebe5b619fb84"}, - {file = "coverage-7.5.3-cp310-cp310-win_amd64.whl", hash = "sha256:33ca90a0eb29225f195e30684ba4a6db05dbef03c2ccd50b9077714c48153cac"}, - {file = "coverage-7.5.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f81bc26d609bf0fbc622c7122ba6307993c83c795d2d6f6f6fd8c000a770d974"}, - {file = "coverage-7.5.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7cec2af81f9e7569280822be68bd57e51b86d42e59ea30d10ebdbb22d2cb7232"}, - {file = "coverage-7.5.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55f689f846661e3f26efa535071775d0483388a1ccfab899df72924805e9e7cd"}, - {file = "coverage-7.5.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:50084d3516aa263791198913a17354bd1dc627d3c1639209640b9cac3fef5807"}, - {file = "coverage-7.5.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:341dd8f61c26337c37988345ca5c8ccabeff33093a26953a1ac72e7d0103c4fb"}, - {file = "coverage-7.5.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ab0b028165eea880af12f66086694768f2c3139b2c31ad5e032c8edbafca6ffc"}, - {file = "coverage-7.5.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:5bc5a8c87714b0c67cfeb4c7caa82b2d71e8864d1a46aa990b5588fa953673b8"}, - {file = "coverage-7.5.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:38a3b98dae8a7c9057bd91fbf3415c05e700a5114c5f1b5b0ea5f8f429ba6614"}, - {file = "coverage-7.5.3-cp311-cp311-win32.whl", hash = "sha256:fcf7d1d6f5da887ca04302db8e0e0cf56ce9a5e05f202720e49b3e8157ddb9a9"}, - {file = "coverage-7.5.3-cp311-cp311-win_amd64.whl", hash = "sha256:8c836309931839cca658a78a888dab9676b5c988d0dd34ca247f5f3e679f4e7a"}, - {file = "coverage-7.5.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:296a7d9bbc598e8744c00f7a6cecf1da9b30ae9ad51c566291ff1314e6cbbed8"}, - {file = "coverage-7.5.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:34d6d21d8795a97b14d503dcaf74226ae51eb1f2bd41015d3ef332a24d0a17b3"}, - {file = "coverage-7.5.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e317953bb4c074c06c798a11dbdd2cf9979dbcaa8ccc0fa4701d80042d4ebf1"}, - {file = "coverage-7.5.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:705f3d7c2b098c40f5b81790a5fedb274113373d4d1a69e65f8b68b0cc26f6db"}, - {file = "coverage-7.5.3-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1196e13c45e327d6cd0b6e471530a1882f1017eb83c6229fc613cd1a11b53cd"}, - {file = "coverage-7.5.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:015eddc5ccd5364dcb902eaecf9515636806fa1e0d5bef5769d06d0f31b54523"}, - {file = "coverage-7.5.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:fd27d8b49e574e50caa65196d908f80e4dff64d7e592d0c59788b45aad7e8b35"}, - {file = "coverage-7.5.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:33fc65740267222fc02975c061eb7167185fef4cc8f2770267ee8bf7d6a42f84"}, - {file = "coverage-7.5.3-cp312-cp312-win32.whl", hash = "sha256:7b2a19e13dfb5c8e145c7a6ea959485ee8e2204699903c88c7d25283584bfc08"}, - {file = "coverage-7.5.3-cp312-cp312-win_amd64.whl", hash = "sha256:0bbddc54bbacfc09b3edaec644d4ac90c08ee8ed4844b0f86227dcda2d428fcb"}, - {file = "coverage-7.5.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f78300789a708ac1f17e134593f577407d52d0417305435b134805c4fb135adb"}, - {file = "coverage-7.5.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b368e1aee1b9b75757942d44d7598dcd22a9dbb126affcbba82d15917f0cc155"}, - {file = "coverage-7.5.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f836c174c3a7f639bded48ec913f348c4761cbf49de4a20a956d3431a7c9cb24"}, - {file = "coverage-7.5.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:244f509f126dc71369393ce5fea17c0592c40ee44e607b6d855e9c4ac57aac98"}, - {file = "coverage-7.5.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4c2872b3c91f9baa836147ca33650dc5c172e9273c808c3c3199c75490e709d"}, - {file = "coverage-7.5.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:dd4b3355b01273a56b20c219e74e7549e14370b31a4ffe42706a8cda91f19f6d"}, - {file = "coverage-7.5.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:f542287b1489c7a860d43a7d8883e27ca62ab84ca53c965d11dac1d3a1fab7ce"}, - {file = "coverage-7.5.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:75e3f4e86804023e991096b29e147e635f5e2568f77883a1e6eed74512659ab0"}, - {file = "coverage-7.5.3-cp38-cp38-win32.whl", hash = "sha256:c59d2ad092dc0551d9f79d9d44d005c945ba95832a6798f98f9216ede3d5f485"}, - {file = "coverage-7.5.3-cp38-cp38-win_amd64.whl", hash = "sha256:fa21a04112c59ad54f69d80e376f7f9d0f5f9123ab87ecd18fbb9ec3a2beed56"}, - {file = "coverage-7.5.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f5102a92855d518b0996eb197772f5ac2a527c0ec617124ad5242a3af5e25f85"}, - {file = "coverage-7.5.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d1da0a2e3b37b745a2b2a678a4c796462cf753aebf94edcc87dcc6b8641eae31"}, - {file = "coverage-7.5.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8383a6c8cefba1b7cecc0149415046b6fc38836295bc4c84e820872eb5478b3d"}, - {file = "coverage-7.5.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9aad68c3f2566dfae84bf46295a79e79d904e1c21ccfc66de88cd446f8686341"}, - {file = "coverage-7.5.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e079c9ec772fedbade9d7ebc36202a1d9ef7291bc9b3a024ca395c4d52853d7"}, - {file = "coverage-7.5.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bde997cac85fcac227b27d4fb2c7608a2c5f6558469b0eb704c5726ae49e1c52"}, - {file = "coverage-7.5.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:990fb20b32990b2ce2c5f974c3e738c9358b2735bc05075d50a6f36721b8f303"}, - {file = "coverage-7.5.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3d5a67f0da401e105753d474369ab034c7bae51a4c31c77d94030d59e41df5bd"}, - {file = "coverage-7.5.3-cp39-cp39-win32.whl", hash = "sha256:e08c470c2eb01977d221fd87495b44867a56d4d594f43739a8028f8646a51e0d"}, - {file = "coverage-7.5.3-cp39-cp39-win_amd64.whl", hash = "sha256:1d2a830ade66d3563bb61d1e3c77c8def97b30ed91e166c67d0632c018f380f0"}, - {file = "coverage-7.5.3-pp38.pp39.pp310-none-any.whl", hash = "sha256:3538d8fb1ee9bdd2e2692b3b18c22bb1c19ffbefd06880f5ac496e42d7bb3884"}, - {file = "coverage-7.5.3.tar.gz", hash = "sha256:04aefca5190d1dc7a53a4c1a5a7f8568811306d7a8ee231c42fb69215571944f"}, + {file = "coverage-7.6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dff044f661f59dace805eedb4a7404c573b6ff0cdba4a524141bc63d7be5c7fd"}, + {file = "coverage-7.6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a8659fd33ee9e6ca03950cfdcdf271d645cf681609153f218826dd9805ab585c"}, + {file = "coverage-7.6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7792f0ab20df8071d669d929c75c97fecfa6bcab82c10ee4adb91c7a54055463"}, + {file = "coverage-7.6.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d4b3cd1ca7cd73d229487fa5caca9e4bc1f0bca96526b922d61053ea751fe791"}, + {file = "coverage-7.6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7e128f85c0b419907d1f38e616c4f1e9f1d1b37a7949f44df9a73d5da5cd53c"}, + {file = "coverage-7.6.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a94925102c89247530ae1dab7dc02c690942566f22e189cbd53579b0693c0783"}, + {file = "coverage-7.6.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:dcd070b5b585b50e6617e8972f3fbbee786afca71b1936ac06257f7e178f00f6"}, + {file = "coverage-7.6.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d50a252b23b9b4dfeefc1f663c568a221092cbaded20a05a11665d0dbec9b8fb"}, + {file = "coverage-7.6.0-cp310-cp310-win32.whl", hash = "sha256:0e7b27d04131c46e6894f23a4ae186a6a2207209a05df5b6ad4caee6d54a222c"}, + {file = "coverage-7.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:54dece71673b3187c86226c3ca793c5f891f9fc3d8aa183f2e3653da18566169"}, + {file = "coverage-7.6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c7b525ab52ce18c57ae232ba6f7010297a87ced82a2383b1afd238849c1ff933"}, + {file = "coverage-7.6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bea27c4269234e06f621f3fac3925f56ff34bc14521484b8f66a580aacc2e7d"}, + {file = "coverage-7.6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed8d1d1821ba5fc88d4a4f45387b65de52382fa3ef1f0115a4f7a20cdfab0e94"}, + {file = "coverage-7.6.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01c322ef2bbe15057bc4bf132b525b7e3f7206f071799eb8aa6ad1940bcf5fb1"}, + {file = "coverage-7.6.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:03cafe82c1b32b770a29fd6de923625ccac3185a54a5e66606da26d105f37dac"}, + {file = "coverage-7.6.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0d1b923fc4a40c5832be4f35a5dab0e5ff89cddf83bb4174499e02ea089daf57"}, + {file = "coverage-7.6.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4b03741e70fb811d1a9a1d75355cf391f274ed85847f4b78e35459899f57af4d"}, + {file = "coverage-7.6.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a73d18625f6a8a1cbb11eadc1d03929f9510f4131879288e3f7922097a429f63"}, + {file = "coverage-7.6.0-cp311-cp311-win32.whl", hash = "sha256:65fa405b837060db569a61ec368b74688f429b32fa47a8929a7a2f9b47183713"}, + {file = "coverage-7.6.0-cp311-cp311-win_amd64.whl", hash = "sha256:6379688fb4cfa921ae349c76eb1a9ab26b65f32b03d46bb0eed841fd4cb6afb1"}, + {file = "coverage-7.6.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f7db0b6ae1f96ae41afe626095149ecd1b212b424626175a6633c2999eaad45b"}, + {file = "coverage-7.6.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bbdf9a72403110a3bdae77948b8011f644571311c2fb35ee15f0f10a8fc082e8"}, + {file = "coverage-7.6.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cc44bf0315268e253bf563f3560e6c004efe38f76db03a1558274a6e04bf5d5"}, + {file = "coverage-7.6.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da8549d17489cd52f85a9829d0e1d91059359b3c54a26f28bec2c5d369524807"}, + {file = "coverage-7.6.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0086cd4fc71b7d485ac93ca4239c8f75732c2ae3ba83f6be1c9be59d9e2c6382"}, + {file = "coverage-7.6.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1fad32ee9b27350687035cb5fdf9145bc9cf0a094a9577d43e909948ebcfa27b"}, + {file = "coverage-7.6.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:044a0985a4f25b335882b0966625270a8d9db3d3409ddc49a4eb00b0ef5e8cee"}, + {file = "coverage-7.6.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:76d5f82213aa78098b9b964ea89de4617e70e0d43e97900c2778a50856dac605"}, + {file = "coverage-7.6.0-cp312-cp312-win32.whl", hash = "sha256:3c59105f8d58ce500f348c5b56163a4113a440dad6daa2294b5052a10db866da"}, + {file = "coverage-7.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:ca5d79cfdae420a1d52bf177de4bc2289c321d6c961ae321503b2ca59c17ae67"}, + {file = "coverage-7.6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d39bd10f0ae453554798b125d2f39884290c480f56e8a02ba7a6ed552005243b"}, + {file = "coverage-7.6.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:beb08e8508e53a568811016e59f3234d29c2583f6b6e28572f0954a6b4f7e03d"}, + {file = "coverage-7.6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2e16f4cd2bc4d88ba30ca2d3bbf2f21f00f382cf4e1ce3b1ddc96c634bc48ca"}, + {file = "coverage-7.6.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6616d1c9bf1e3faea78711ee42a8b972367d82ceae233ec0ac61cc7fec09fa6b"}, + {file = "coverage-7.6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad4567d6c334c46046d1c4c20024de2a1c3abc626817ae21ae3da600f5779b44"}, + {file = "coverage-7.6.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d17c6a415d68cfe1091d3296ba5749d3d8696e42c37fca5d4860c5bf7b729f03"}, + {file = "coverage-7.6.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:9146579352d7b5f6412735d0f203bbd8d00113a680b66565e205bc605ef81bc6"}, + {file = "coverage-7.6.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:cdab02a0a941af190df8782aafc591ef3ad08824f97850b015c8c6a8b3877b0b"}, + {file = "coverage-7.6.0-cp38-cp38-win32.whl", hash = "sha256:df423f351b162a702c053d5dddc0fc0ef9a9e27ea3f449781ace5f906b664428"}, + {file = "coverage-7.6.0-cp38-cp38-win_amd64.whl", hash = "sha256:f2501d60d7497fd55e391f423f965bbe9e650e9ffc3c627d5f0ac516026000b8"}, + {file = "coverage-7.6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7221f9ac9dad9492cecab6f676b3eaf9185141539d5c9689d13fd6b0d7de840c"}, + {file = "coverage-7.6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ddaaa91bfc4477d2871442bbf30a125e8fe6b05da8a0015507bfbf4718228ab2"}, + {file = "coverage-7.6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4cbe651f3904e28f3a55d6f371203049034b4ddbce65a54527a3f189ca3b390"}, + {file = "coverage-7.6.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:831b476d79408ab6ccfadaaf199906c833f02fdb32c9ab907b1d4aa0713cfa3b"}, + {file = "coverage-7.6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46c3d091059ad0b9c59d1034de74a7f36dcfa7f6d3bde782c49deb42438f2450"}, + {file = "coverage-7.6.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:4d5fae0a22dc86259dee66f2cc6c1d3e490c4a1214d7daa2a93d07491c5c04b6"}, + {file = "coverage-7.6.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:07ed352205574aad067482e53dd606926afebcb5590653121063fbf4e2175166"}, + {file = "coverage-7.6.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:49c76cdfa13015c4560702574bad67f0e15ca5a2872c6a125f6327ead2b731dd"}, + {file = "coverage-7.6.0-cp39-cp39-win32.whl", hash = "sha256:482855914928c8175735a2a59c8dc5806cf7d8f032e4820d52e845d1f731dca2"}, + {file = "coverage-7.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:543ef9179bc55edfd895154a51792b01c017c87af0ebaae092720152e19e42ca"}, + {file = "coverage-7.6.0-pp38.pp39.pp310-none-any.whl", hash = "sha256:6fe885135c8a479d3e37a7aae61cbd3a0fb2deccb4dda3c25f92a49189f766d6"}, + {file = "coverage-7.6.0.tar.gz", hash = "sha256:289cc803fa1dc901f84701ac10c9ee873619320f2f9aff38794db4a4a0268d51"}, ] [package.dependencies] @@ -122,6 +387,36 @@ tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.1 [package.extras] toml = ["tomli"] +[[package]] +name = "cssselect2" +version = "0.7.0" +description = "CSS selectors for Python ElementTree" +optional = false +python-versions = ">=3.7" +files = [ + {file = "cssselect2-0.7.0-py3-none-any.whl", hash = "sha256:fd23a65bfd444595913f02fc71f6b286c29261e354c41d722ca7a261a49b5969"}, + {file = "cssselect2-0.7.0.tar.gz", hash = "sha256:1ccd984dab89fc68955043aca4e1b03e0cf29cad9880f6e28e3ba7a74b14aa5a"}, +] + +[package.dependencies] +tinycss2 = "*" +webencodings = "*" + +[package.extras] +doc = ["sphinx", "sphinx_rtd_theme"] +test = ["flake8", "isort", "pytest"] + +[[package]] +name = "defusedxml" +version = "0.7.1" +description = "XML bomb protection for Python stdlib modules" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"}, + {file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"}, +] + [[package]] name = "distlib" version = "0.3.8" @@ -135,13 +430,13 @@ files = [ [[package]] name = "exceptiongroup" -version = "1.2.1" +version = "1.2.2" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" files = [ - {file = "exceptiongroup-1.2.1-py3-none-any.whl", hash = "sha256:5258b9ed329c5bbdd31a309f53cbfb0b155341807f6ff7606a1e801a891b29ad"}, - {file = "exceptiongroup-1.2.1.tar.gz", hash = "sha256:a4785e48b045528f5bfe627b6ad554ff32def154f42372786903b7abcfe1aa16"}, + {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, + {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, ] [package.extras] @@ -149,13 +444,13 @@ test = ["pytest (>=6)"] [[package]] name = "filelock" -version = "3.15.3" +version = "3.15.4" description = "A platform independent file lock." optional = false python-versions = ">=3.8" files = [ - {file = "filelock-3.15.3-py3-none-any.whl", hash = "sha256:0151273e5b5d6cf753a61ec83b3a9b7d8821c39ae9af9d7ecf2f9e2f17404103"}, - {file = "filelock-3.15.3.tar.gz", hash = "sha256:e1199bf5194a2277273dacd50269f0d87d0682088a3c561c15674ea9005d8635"}, + {file = "filelock-3.15.4-py3-none-any.whl", hash = "sha256:6ca1fffae96225dab4c6eaf1c4f4f28cd2568d3ec2a44e15a08520504de468e7"}, + {file = "filelock-3.15.4.tar.gz", hash = "sha256:2207938cbc1844345cb01a5a95524dae30f0ce089eba5b00378295a17e3e90cb"}, ] [package.extras] @@ -163,6 +458,23 @@ docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1 testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-asyncio (>=0.21)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)", "virtualenv (>=20.26.2)"] typing = ["typing-extensions (>=4.8)"] +[[package]] +name = "ghp-import" +version = "2.1.0" +description = "Copy your docs directly to the gh-pages branch." +optional = false +python-versions = "*" +files = [ + {file = "ghp-import-2.1.0.tar.gz", hash = "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343"}, + {file = "ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619"}, +] + +[package.dependencies] +python-dateutil = ">=2.8.1" + +[package.extras] +dev = ["flake8", "markdown", "twine", "wheel"] + [[package]] name = "git-changelog" version = "2.5.2" @@ -181,20 +493,83 @@ packaging = ">=24.0" semver = ">=2.13" tomli = {version = ">=2.0", markers = "python_version < \"3.11\""} +[[package]] +name = "griffe" +version = "0.48.0" +description = "Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API." +optional = false +python-versions = ">=3.8" +files = [ + {file = "griffe-0.48.0-py3-none-any.whl", hash = "sha256:f944c6ff7bd31cf76f264adcd6ab8f3d00a2f972ae5cc8db2d7b6dcffeff65a2"}, + {file = "griffe-0.48.0.tar.gz", hash = "sha256:f099461c02f016b6be4af386d5aa92b01fb4efe6c1c2c360dda9a5d0a863bb7f"}, +] + +[package.dependencies] +backports-strenum = {version = ">=1.3", markers = "python_version < \"3.11\""} +colorama = ">=0.4" + [[package]] name = "identify" -version = "2.5.36" +version = "2.6.0" description = "File identification library for Python" optional = false python-versions = ">=3.8" files = [ - {file = "identify-2.5.36-py2.py3-none-any.whl", hash = "sha256:37d93f380f4de590500d9dba7db359d0d3da95ffe7f9de1753faa159e71e7dfa"}, - {file = "identify-2.5.36.tar.gz", hash = "sha256:e5e00f54165f9047fbebeb4a560f9acfb8af4c88232be60a488e9b68d122745d"}, + {file = "identify-2.6.0-py2.py3-none-any.whl", hash = "sha256:e79ae4406387a9d300332b5fd366d8994f1525e8414984e1a59e058b2eda2dd0"}, + {file = "identify-2.6.0.tar.gz", hash = "sha256:cb171c685bdc31bcc4c1734698736a7d5b6c8bf2e0c15117f4d469c8640ae5cf"}, ] [package.extras] license = ["ukkonen"] +[[package]] +name = "idna" +version = "3.7" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.5" +files = [ + {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"}, + {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, +] + +[[package]] +name = "importlib-metadata" +version = "8.0.0" +description = "Read metadata from Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "importlib_metadata-8.0.0-py3-none-any.whl", hash = "sha256:15584cf2b1bf449d98ff8a6ff1abef57bf20f3ac6454f431736cd3e660921b2f"}, + {file = "importlib_metadata-8.0.0.tar.gz", hash = "sha256:188bd24e4c346d3f0a933f275c2fec67050326a856b9a359881d7c2a697e8812"}, +] + +[package.dependencies] +zipp = ">=0.5" + +[package.extras] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +perf = ["ipython"] +test = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-perf (>=0.9.2)", "pytest-ruff (>=0.2.1)"] + +[[package]] +name = "importlib-resources" +version = "6.4.0" +description = "Read resources from Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "importlib_resources-6.4.0-py3-none-any.whl", hash = "sha256:50d10f043df931902d4194ea07ec57960f66a80449ff867bfe782b4c486ba78c"}, + {file = "importlib_resources-6.4.0.tar.gz", hash = "sha256:cdb2b453b8046ca4e3798eb1d84f3cce1446a0e8e7b5ef4efb600f19fc398145"}, +] + +[package.dependencies] +zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["jaraco.test (>=5.4)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-ruff (>=0.2.1)", "zipp (>=3.17)"] + [[package]] name = "inflection" version = "0.5.1" @@ -234,6 +609,24 @@ MarkupSafe = ">=2.0" [package.extras] i18n = ["Babel (>=2.7)"] +[[package]] +name = "markdown" +version = "3.6" +description = "Python implementation of John Gruber's Markdown." +optional = false +python-versions = ">=3.8" +files = [ + {file = "Markdown-3.6-py3-none-any.whl", hash = "sha256:48f276f4d8cfb8ce6527c8f79e2ee29708508bf4d40aa410fbc3b4ee832c850f"}, + {file = "Markdown-3.6.tar.gz", hash = "sha256:ed4f41f6daecbeeb96e576ce414c41d2d876daa9a16cb35fa8ed8c2ddfad0224"}, +] + +[package.dependencies] +importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} + +[package.extras] +docs = ["mdx-gh-links (>=0.2)", "mkdocs (>=1.5)", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-nature (>=0.6)", "mkdocs-section-index", "mkdocstrings[python]"] +testing = ["coverage", "pyyaml"] + [[package]] name = "markupsafe" version = "2.1.5" @@ -303,6 +696,264 @@ files = [ {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, ] +[[package]] +name = "mergedeep" +version = "1.3.4" +description = "A deep merge function for 🐍." +optional = false +python-versions = ">=3.6" +files = [ + {file = "mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307"}, + {file = "mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8"}, +] + +[[package]] +name = "mike" +version = "2.1.2" +description = "Manage multiple versions of your MkDocs-powered documentation" +optional = false +python-versions = "*" +files = [ + {file = "mike-2.1.2-py3-none-any.whl", hash = "sha256:d61d9b423ab412d634ca2bd520136d5114e3cc73f4bbd1aa6a0c6625c04918c0"}, + {file = "mike-2.1.2.tar.gz", hash = "sha256:d59cc8054c50f9c8a046cfd47f9b700cf9ff1b2b19f420bd8812ca6f94fa8bd3"}, +] + +[package.dependencies] +importlib-metadata = "*" +importlib-resources = "*" +jinja2 = ">=2.7" +mkdocs = ">=1.0" +pyparsing = ">=3.0" +pyyaml = ">=5.1" +pyyaml-env-tag = "*" +verspec = "*" + +[package.extras] +dev = ["coverage", "flake8 (>=3.0)", "flake8-quotes", "shtab"] +test = ["coverage", "flake8 (>=3.0)", "flake8-quotes", "shtab"] + +[[package]] +name = "mkdocs" +version = "1.6.0" +description = "Project documentation with Markdown." +optional = false +python-versions = ">=3.8" +files = [ + {file = "mkdocs-1.6.0-py3-none-any.whl", hash = "sha256:1eb5cb7676b7d89323e62b56235010216319217d4af5ddc543a91beb8d125ea7"}, + {file = "mkdocs-1.6.0.tar.gz", hash = "sha256:a73f735824ef83a4f3bcb7a231dcab23f5a838f88b7efc54a0eef5fbdbc3c512"}, +] + +[package.dependencies] +click = ">=7.0" +colorama = {version = ">=0.4", markers = "platform_system == \"Windows\""} +ghp-import = ">=1.0" +importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} +jinja2 = ">=2.11.1" +markdown = ">=3.3.6" +markupsafe = ">=2.0.1" +mergedeep = ">=1.3.4" +mkdocs-get-deps = ">=0.2.0" +packaging = ">=20.5" +pathspec = ">=0.11.1" +pyyaml = ">=5.1" +pyyaml-env-tag = ">=0.1" +watchdog = ">=2.0" + +[package.extras] +i18n = ["babel (>=2.9.0)"] +min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-import (==1.0)", "importlib-metadata (==4.4)", "jinja2 (==2.11.1)", "markdown (==3.3.6)", "markupsafe (==2.0.1)", "mergedeep (==1.3.4)", "mkdocs-get-deps (==0.2.0)", "packaging (==20.5)", "pathspec (==0.11.1)", "pyyaml (==5.1)", "pyyaml-env-tag (==0.1)", "watchdog (==2.0)"] + +[[package]] +name = "mkdocs-autorefs" +version = "1.0.1" +description = "Automatically link across pages in MkDocs." +optional = false +python-versions = ">=3.8" +files = [ + {file = "mkdocs_autorefs-1.0.1-py3-none-any.whl", hash = "sha256:aacdfae1ab197780fb7a2dac92ad8a3d8f7ca8049a9cbe56a4218cd52e8da570"}, + {file = "mkdocs_autorefs-1.0.1.tar.gz", hash = "sha256:f684edf847eced40b570b57846b15f0bf57fb93ac2c510450775dcf16accb971"}, +] + +[package.dependencies] +Markdown = ">=3.3" +markupsafe = ">=2.0.1" +mkdocs = ">=1.1" + +[[package]] +name = "mkdocs-awesome-pages-plugin" +version = "2.9.2" +description = "An MkDocs plugin that simplifies configuring page titles and their order" +optional = false +python-versions = ">=3.7" +files = [ + {file = "mkdocs_awesome_pages_plugin-2.9.2-py3-none-any.whl", hash = "sha256:9c795587695bd1ee85a8b7e43293005418df5a8b9ef296a3e628be427b693b4d"}, + {file = "mkdocs_awesome_pages_plugin-2.9.2.tar.gz", hash = "sha256:c3f7d366ecfe99b64524c49a84d8e13c576c19a918ea2e6f59bb486a259313af"}, +] + +[package.dependencies] +mkdocs = ">=1" +natsort = ">=8.1.0" +wcmatch = ">=7" + +[[package]] +name = "mkdocs-gen-files" +version = "0.5.0" +description = "MkDocs plugin to programmatically generate documentation pages during the build" +optional = false +python-versions = ">=3.7" +files = [ + {file = "mkdocs_gen_files-0.5.0-py3-none-any.whl", hash = "sha256:7ac060096f3f40bd19039e7277dd3050be9a453c8ac578645844d4d91d7978ea"}, + {file = "mkdocs_gen_files-0.5.0.tar.gz", hash = "sha256:4c7cf256b5d67062a788f6b1d035e157fc1a9498c2399be9af5257d4ff4d19bc"}, +] + +[package.dependencies] +mkdocs = ">=1.0.3" + +[[package]] +name = "mkdocs-get-deps" +version = "0.2.0" +description = "MkDocs extension that lists all dependencies according to a mkdocs.yml file" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mkdocs_get_deps-0.2.0-py3-none-any.whl", hash = "sha256:2bf11d0b133e77a0dd036abeeb06dec8775e46efa526dc70667d8863eefc6134"}, + {file = "mkdocs_get_deps-0.2.0.tar.gz", hash = "sha256:162b3d129c7fad9b19abfdcb9c1458a651628e4b1dea628ac68790fb3061c60c"}, +] + +[package.dependencies] +importlib-metadata = {version = ">=4.3", markers = "python_version < \"3.10\""} +mergedeep = ">=1.3.4" +platformdirs = ">=2.2.0" +pyyaml = ">=5.1" + +[[package]] +name = "mkdocs-literate-nav" +version = "0.6.1" +description = "MkDocs plugin to specify the navigation in Markdown instead of YAML" +optional = false +python-versions = ">=3.7" +files = [ + {file = "mkdocs_literate_nav-0.6.1-py3-none-any.whl", hash = "sha256:e70bdc4a07050d32da79c0b697bd88e9a104cf3294282e9cb20eec94c6b0f401"}, + {file = "mkdocs_literate_nav-0.6.1.tar.gz", hash = "sha256:78a7ab6d878371728acb0cdc6235c9b0ffc6e83c997b037f4a5c6ff7cef7d759"}, +] + +[package.dependencies] +mkdocs = ">=1.0.3" + +[[package]] +name = "mkdocs-material" +version = "9.5.29" +description = "Documentation that simply works" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mkdocs_material-9.5.29-py3-none-any.whl", hash = "sha256:afc1f508e2662ded95f0a35a329e8a5acd73ee88ca07ba73836eb6fcdae5d8b4"}, + {file = "mkdocs_material-9.5.29.tar.gz", hash = "sha256:3e977598ec15a4ddad5c4dfc9e08edab6023edb51e88f0729bd27be77e3d322a"}, +] + +[package.dependencies] +babel = ">=2.10,<3.0" +cairosvg = {version = ">=2.6,<3.0", optional = true, markers = "extra == \"imaging\""} +colorama = ">=0.4,<1.0" +jinja2 = ">=3.0,<4.0" +markdown = ">=3.2,<4.0" +mkdocs = ">=1.6,<2.0" +mkdocs-material-extensions = ">=1.3,<2.0" +paginate = ">=0.5,<1.0" +pillow = {version = ">=10.2,<11.0", optional = true, markers = "extra == \"imaging\""} +pygments = ">=2.16,<3.0" +pymdown-extensions = ">=10.2,<11.0" +regex = ">=2022.4" +requests = ">=2.26,<3.0" + +[package.extras] +git = ["mkdocs-git-committers-plugin-2 (>=1.1,<2.0)", "mkdocs-git-revision-date-localized-plugin (>=1.2.4,<2.0)"] +imaging = ["cairosvg (>=2.6,<3.0)", "pillow (>=10.2,<11.0)"] +recommended = ["mkdocs-minify-plugin (>=0.7,<1.0)", "mkdocs-redirects (>=1.2,<2.0)", "mkdocs-rss-plugin (>=1.6,<2.0)"] + +[[package]] +name = "mkdocs-material-extensions" +version = "1.3.1" +description = "Extension pack for Python Markdown and MkDocs Material." +optional = false +python-versions = ">=3.8" +files = [ + {file = "mkdocs_material_extensions-1.3.1-py3-none-any.whl", hash = "sha256:adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31"}, + {file = "mkdocs_material_extensions-1.3.1.tar.gz", hash = "sha256:10c9511cea88f568257f960358a467d12b970e1f7b2c0e5fb2bb48cab1928443"}, +] + +[[package]] +name = "mkdocs-open-in-new-tab" +version = "1.0.3" +description = "MkDocs plugin to open outgoing links and PDFs in new tab." +optional = false +python-versions = ">=3.7" +files = [ + {file = "mkdocs-open-in-new-tab-1.0.3.tar.gz", hash = "sha256:a40231901b12f01a1d4b798112712d475741356e550d8f3adf3ca23e332a7d2c"}, + {file = "mkdocs_open_in_new_tab-1.0.3-py3-none-any.whl", hash = "sha256:e2ddfa02f53d7c16d8430f5c0b3d98c4b98c82e1b8aa6fbdc91c78e89bbeb5f1"}, +] + +[package.dependencies] +mkdocs = "*" + +[[package]] +name = "mkdocs-section-index" +version = "0.3.9" +description = "MkDocs plugin to allow clickable sections that lead to an index page" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mkdocs_section_index-0.3.9-py3-none-any.whl", hash = "sha256:5e5eb288e8d7984d36c11ead5533f376fdf23498f44e903929d72845b24dfe34"}, + {file = "mkdocs_section_index-0.3.9.tar.gz", hash = "sha256:b66128d19108beceb08b226ee1ba0981840d14baf8a652b6c59e650f3f92e4f8"}, +] + +[package.dependencies] +mkdocs = ">=1.2" + +[[package]] +name = "mkdocstrings" +version = "0.25.1" +description = "Automatic documentation from sources, for MkDocs." +optional = false +python-versions = ">=3.8" +files = [ + {file = "mkdocstrings-0.25.1-py3-none-any.whl", hash = "sha256:da01fcc2670ad61888e8fe5b60afe9fee5781017d67431996832d63e887c2e51"}, + {file = "mkdocstrings-0.25.1.tar.gz", hash = "sha256:c3a2515f31577f311a9ee58d089e4c51fc6046dbd9e9b4c3de4c3194667fe9bf"}, +] + +[package.dependencies] +click = ">=7.0" +importlib-metadata = {version = ">=4.6", markers = "python_version < \"3.10\""} +Jinja2 = ">=2.11.1" +Markdown = ">=3.3" +MarkupSafe = ">=1.1" +mkdocs = ">=1.4" +mkdocs-autorefs = ">=0.3.1" +mkdocstrings-python = {version = ">=0.5.2", optional = true, markers = "extra == \"python\""} +platformdirs = ">=2.2.0" +pymdown-extensions = ">=6.3" +typing-extensions = {version = ">=4.1", markers = "python_version < \"3.10\""} + +[package.extras] +crystal = ["mkdocstrings-crystal (>=0.3.4)"] +python = ["mkdocstrings-python (>=0.5.2)"] +python-legacy = ["mkdocstrings-python-legacy (>=0.2.1)"] + +[[package]] +name = "mkdocstrings-python" +version = "1.10.5" +description = "A Python handler for mkdocstrings." +optional = false +python-versions = ">=3.8" +files = [ + {file = "mkdocstrings_python-1.10.5-py3-none-any.whl", hash = "sha256:92e3c588ef1b41151f55281d075de7558dd8092e422cb07a65b18ee2b0863ebb"}, + {file = "mkdocstrings_python-1.10.5.tar.gz", hash = "sha256:acdc2a98cd9d46c7ece508193a16ca03ccabcb67520352b7449f84b57c162bdf"}, +] + +[package.dependencies] +griffe = ">=0.47" +mkdocstrings = ">=0.25" + [[package]] name = "more-itertools" version = "10.3.0" @@ -314,6 +965,21 @@ files = [ {file = "more_itertools-10.3.0-py3-none-any.whl", hash = "sha256:ea6a02e24a9161e51faad17a8782b92a0df82c12c1c8886fec7f0c3fa1a1b320"}, ] +[[package]] +name = "natsort" +version = "8.4.0" +description = "Simple yet flexible natural sorting in Python." +optional = false +python-versions = ">=3.7" +files = [ + {file = "natsort-8.4.0-py3-none-any.whl", hash = "sha256:4732914fb471f56b5cce04d7bae6f164a592c7712e1c85f9ef585e197299521c"}, + {file = "natsort-8.4.0.tar.gz", hash = "sha256:45312c4a0e5507593da193dedd04abb1469253b601ecaf63445ad80f0a1ea581"}, +] + +[package.extras] +fast = ["fastnumbers (>=2.0.0)"] +icu = ["PyICU (>=1.0.0)"] + [[package]] name = "nodeenv" version = "1.9.1" @@ -327,57 +993,62 @@ files = [ [[package]] name = "orjson" -version = "3.10.5" +version = "3.10.6" description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" optional = false python-versions = ">=3.8" files = [ - {file = "orjson-3.10.5-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:545d493c1f560d5ccfc134803ceb8955a14c3fcb47bbb4b2fee0232646d0b932"}, - {file = "orjson-3.10.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4324929c2dd917598212bfd554757feca3e5e0fa60da08be11b4aa8b90013c1"}, - {file = "orjson-3.10.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8c13ca5e2ddded0ce6a927ea5a9f27cae77eee4c75547b4297252cb20c4d30e6"}, - {file = "orjson-3.10.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b6c8e30adfa52c025f042a87f450a6b9ea29649d828e0fec4858ed5e6caecf63"}, - {file = "orjson-3.10.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:338fd4f071b242f26e9ca802f443edc588fa4ab60bfa81f38beaedf42eda226c"}, - {file = "orjson-3.10.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6970ed7a3126cfed873c5d21ece1cd5d6f83ca6c9afb71bbae21a0b034588d96"}, - {file = "orjson-3.10.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:235dadefb793ad12f7fa11e98a480db1f7c6469ff9e3da5e73c7809c700d746b"}, - {file = "orjson-3.10.5-cp310-none-win32.whl", hash = "sha256:be79e2393679eda6a590638abda16d167754393f5d0850dcbca2d0c3735cebe2"}, - {file = "orjson-3.10.5-cp310-none-win_amd64.whl", hash = "sha256:c4a65310ccb5c9910c47b078ba78e2787cb3878cdded1702ac3d0da71ddc5228"}, - {file = "orjson-3.10.5-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:cdf7365063e80899ae3a697def1277c17a7df7ccfc979990a403dfe77bb54d40"}, - {file = "orjson-3.10.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b68742c469745d0e6ca5724506858f75e2f1e5b59a4315861f9e2b1df77775a"}, - {file = "orjson-3.10.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7d10cc1b594951522e35a3463da19e899abe6ca95f3c84c69e9e901e0bd93d38"}, - {file = "orjson-3.10.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dcbe82b35d1ac43b0d84072408330fd3295c2896973112d495e7234f7e3da2e1"}, - {file = "orjson-3.10.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c0eb7e0c75e1e486c7563fe231b40fdd658a035ae125c6ba651ca3b07936f5"}, - {file = "orjson-3.10.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:53ed1c879b10de56f35daf06dbc4a0d9a5db98f6ee853c2dbd3ee9d13e6f302f"}, - {file = "orjson-3.10.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:099e81a5975237fda3100f918839af95f42f981447ba8f47adb7b6a3cdb078fa"}, - {file = "orjson-3.10.5-cp311-none-win32.whl", hash = "sha256:1146bf85ea37ac421594107195db8bc77104f74bc83e8ee21a2e58596bfb2f04"}, - {file = "orjson-3.10.5-cp311-none-win_amd64.whl", hash = "sha256:36a10f43c5f3a55c2f680efe07aa93ef4a342d2960dd2b1b7ea2dd764fe4a37c"}, - {file = "orjson-3.10.5-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:68f85ecae7af14a585a563ac741b0547a3f291de81cd1e20903e79f25170458f"}, - {file = "orjson-3.10.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28afa96f496474ce60d3340fe8d9a263aa93ea01201cd2bad844c45cd21f5268"}, - {file = "orjson-3.10.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9cd684927af3e11b6e754df80b9ffafd9fb6adcaa9d3e8fdd5891be5a5cad51e"}, - {file = "orjson-3.10.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d21b9983da032505f7050795e98b5d9eee0df903258951566ecc358f6696969"}, - {file = "orjson-3.10.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ad1de7fef79736dde8c3554e75361ec351158a906d747bd901a52a5c9c8d24b"}, - {file = "orjson-3.10.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2d97531cdfe9bdd76d492e69800afd97e5930cb0da6a825646667b2c6c6c0211"}, - {file = "orjson-3.10.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d69858c32f09c3e1ce44b617b3ebba1aba030e777000ebdf72b0d8e365d0b2b3"}, - {file = "orjson-3.10.5-cp312-none-win32.whl", hash = "sha256:64c9cc089f127e5875901ac05e5c25aa13cfa5dbbbd9602bda51e5c611d6e3e2"}, - {file = "orjson-3.10.5-cp312-none-win_amd64.whl", hash = "sha256:b2efbd67feff8c1f7728937c0d7f6ca8c25ec81373dc8db4ef394c1d93d13dc5"}, - {file = "orjson-3.10.5-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:03b565c3b93f5d6e001db48b747d31ea3819b89abf041ee10ac6988886d18e01"}, - {file = "orjson-3.10.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:584c902ec19ab7928fd5add1783c909094cc53f31ac7acfada817b0847975f26"}, - {file = "orjson-3.10.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5a35455cc0b0b3a1eaf67224035f5388591ec72b9b6136d66b49a553ce9eb1e6"}, - {file = "orjson-3.10.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1670fe88b116c2745a3a30b0f099b699a02bb3482c2591514baf5433819e4f4d"}, - {file = "orjson-3.10.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:185c394ef45b18b9a7d8e8f333606e2e8194a50c6e3c664215aae8cf42c5385e"}, - {file = "orjson-3.10.5-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:ca0b3a94ac8d3886c9581b9f9de3ce858263865fdaa383fbc31c310b9eac07c9"}, - {file = "orjson-3.10.5-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:dfc91d4720d48e2a709e9c368d5125b4b5899dced34b5400c3837dadc7d6271b"}, - {file = "orjson-3.10.5-cp38-none-win32.whl", hash = "sha256:c05f16701ab2a4ca146d0bca950af254cb7c02f3c01fca8efbbad82d23b3d9d4"}, - {file = "orjson-3.10.5-cp38-none-win_amd64.whl", hash = "sha256:8a11d459338f96a9aa7f232ba95679fc0c7cedbd1b990d736467894210205c09"}, - {file = "orjson-3.10.5-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:85c89131d7b3218db1b24c4abecea92fd6c7f9fab87441cfc342d3acc725d807"}, - {file = "orjson-3.10.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb66215277a230c456f9038d5e2d84778141643207f85336ef8d2a9da26bd7ca"}, - {file = "orjson-3.10.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:51bbcdea96cdefa4a9b4461e690c75ad4e33796530d182bdd5c38980202c134a"}, - {file = "orjson-3.10.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbead71dbe65f959b7bd8cf91e0e11d5338033eba34c114f69078d59827ee139"}, - {file = "orjson-3.10.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5df58d206e78c40da118a8c14fc189207fffdcb1f21b3b4c9c0c18e839b5a214"}, - {file = "orjson-3.10.5-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c4057c3b511bb8aef605616bd3f1f002a697c7e4da6adf095ca5b84c0fd43595"}, - {file = "orjson-3.10.5-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b39e006b00c57125ab974362e740c14a0c6a66ff695bff44615dcf4a70ce2b86"}, - {file = "orjson-3.10.5-cp39-none-win32.whl", hash = "sha256:eded5138cc565a9d618e111c6d5c2547bbdd951114eb822f7f6309e04db0fb47"}, - {file = "orjson-3.10.5-cp39-none-win_amd64.whl", hash = "sha256:cc28e90a7cae7fcba2493953cff61da5a52950e78dc2dacfe931a317ee3d8de7"}, - {file = "orjson-3.10.5.tar.gz", hash = "sha256:7a5baef8a4284405d96c90c7c62b755e9ef1ada84c2406c24a9ebec86b89f46d"}, + {file = "orjson-3.10.6-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:fb0ee33124db6eaa517d00890fc1a55c3bfe1cf78ba4a8899d71a06f2d6ff5c7"}, + {file = "orjson-3.10.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c1c4b53b24a4c06547ce43e5fee6ec4e0d8fe2d597f4647fc033fd205707365"}, + {file = "orjson-3.10.6-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eadc8fd310edb4bdbd333374f2c8fec6794bbbae99b592f448d8214a5e4050c0"}, + {file = "orjson-3.10.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:61272a5aec2b2661f4fa2b37c907ce9701e821b2c1285d5c3ab0207ebd358d38"}, + {file = "orjson-3.10.6-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57985ee7e91d6214c837936dc1608f40f330a6b88bb13f5a57ce5257807da143"}, + {file = "orjson-3.10.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:633a3b31d9d7c9f02d49c4ab4d0a86065c4a6f6adc297d63d272e043472acab5"}, + {file = "orjson-3.10.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1c680b269d33ec444afe2bdc647c9eb73166fa47a16d9a75ee56a374f4a45f43"}, + {file = "orjson-3.10.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f759503a97a6ace19e55461395ab0d618b5a117e8d0fbb20e70cfd68a47327f2"}, + {file = "orjson-3.10.6-cp310-none-win32.whl", hash = "sha256:95a0cce17f969fb5391762e5719575217bd10ac5a189d1979442ee54456393f3"}, + {file = "orjson-3.10.6-cp310-none-win_amd64.whl", hash = "sha256:df25d9271270ba2133cc88ee83c318372bdc0f2cd6f32e7a450809a111efc45c"}, + {file = "orjson-3.10.6-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:b1ec490e10d2a77c345def52599311849fc063ae0e67cf4f84528073152bb2ba"}, + {file = "orjson-3.10.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55d43d3feb8f19d07e9f01e5b9be4f28801cf7c60d0fa0d279951b18fae1932b"}, + {file = "orjson-3.10.6-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac3045267e98fe749408eee1593a142e02357c5c99be0802185ef2170086a863"}, + {file = "orjson-3.10.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c27bc6a28ae95923350ab382c57113abd38f3928af3c80be6f2ba7eb8d8db0b0"}, + {file = "orjson-3.10.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d27456491ca79532d11e507cadca37fb8c9324a3976294f68fb1eff2dc6ced5a"}, + {file = "orjson-3.10.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05ac3d3916023745aa3b3b388e91b9166be1ca02b7c7e41045da6d12985685f0"}, + {file = "orjson-3.10.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1335d4ef59ab85cab66fe73fd7a4e881c298ee7f63ede918b7faa1b27cbe5212"}, + {file = "orjson-3.10.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4bbc6d0af24c1575edc79994c20e1b29e6fb3c6a570371306db0993ecf144dc5"}, + {file = "orjson-3.10.6-cp311-none-win32.whl", hash = "sha256:450e39ab1f7694465060a0550b3f6d328d20297bf2e06aa947b97c21e5241fbd"}, + {file = "orjson-3.10.6-cp311-none-win_amd64.whl", hash = "sha256:227df19441372610b20e05bdb906e1742ec2ad7a66ac8350dcfd29a63014a83b"}, + {file = "orjson-3.10.6-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:ea2977b21f8d5d9b758bb3f344a75e55ca78e3ff85595d248eee813ae23ecdfb"}, + {file = "orjson-3.10.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b6f3d167d13a16ed263b52dbfedff52c962bfd3d270b46b7518365bcc2121eed"}, + {file = "orjson-3.10.6-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f710f346e4c44a4e8bdf23daa974faede58f83334289df80bc9cd12fe82573c7"}, + {file = "orjson-3.10.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7275664f84e027dcb1ad5200b8b18373e9c669b2a9ec33d410c40f5ccf4b257e"}, + {file = "orjson-3.10.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0943e4c701196b23c240b3d10ed8ecd674f03089198cf503105b474a4f77f21f"}, + {file = "orjson-3.10.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:446dee5a491b5bc7d8f825d80d9637e7af43f86a331207b9c9610e2f93fee22a"}, + {file = "orjson-3.10.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:64c81456d2a050d380786413786b057983892db105516639cb5d3ee3c7fd5148"}, + {file = "orjson-3.10.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:960db0e31c4e52fa0fc3ecbaea5b2d3b58f379e32a95ae6b0ebeaa25b93dfd34"}, + {file = "orjson-3.10.6-cp312-none-win32.whl", hash = "sha256:a6ea7afb5b30b2317e0bee03c8d34c8181bc5a36f2afd4d0952f378972c4efd5"}, + {file = "orjson-3.10.6-cp312-none-win_amd64.whl", hash = "sha256:874ce88264b7e655dde4aeaacdc8fd772a7962faadfb41abe63e2a4861abc3dc"}, + {file = "orjson-3.10.6-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:66680eae4c4e7fc193d91cfc1353ad6d01b4801ae9b5314f17e11ba55e934183"}, + {file = "orjson-3.10.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:caff75b425db5ef8e8f23af93c80f072f97b4fb3afd4af44482905c9f588da28"}, + {file = "orjson-3.10.6-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3722fddb821b6036fd2a3c814f6bd9b57a89dc6337b9924ecd614ebce3271394"}, + {file = "orjson-3.10.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c2c116072a8533f2fec435fde4d134610f806bdac20188c7bd2081f3e9e0133f"}, + {file = "orjson-3.10.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6eeb13218c8cf34c61912e9df2de2853f1d009de0e46ea09ccdf3d757896af0a"}, + {file = "orjson-3.10.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:965a916373382674e323c957d560b953d81d7a8603fbeee26f7b8248638bd48b"}, + {file = "orjson-3.10.6-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:03c95484d53ed8e479cade8628c9cea00fd9d67f5554764a1110e0d5aa2de96e"}, + {file = "orjson-3.10.6-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:e060748a04cccf1e0a6f2358dffea9c080b849a4a68c28b1b907f272b5127e9b"}, + {file = "orjson-3.10.6-cp38-none-win32.whl", hash = "sha256:738dbe3ef909c4b019d69afc19caf6b5ed0e2f1c786b5d6215fbb7539246e4c6"}, + {file = "orjson-3.10.6-cp38-none-win_amd64.whl", hash = "sha256:d40f839dddf6a7d77114fe6b8a70218556408c71d4d6e29413bb5f150a692ff7"}, + {file = "orjson-3.10.6-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:697a35a083c4f834807a6232b3e62c8b280f7a44ad0b759fd4dce748951e70db"}, + {file = "orjson-3.10.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd502f96bf5ea9a61cbc0b2b5900d0dd68aa0da197179042bdd2be67e51a1e4b"}, + {file = "orjson-3.10.6-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f215789fb1667cdc874c1b8af6a84dc939fd802bf293a8334fce185c79cd359b"}, + {file = "orjson-3.10.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a2debd8ddce948a8c0938c8c93ade191d2f4ba4649a54302a7da905a81f00b56"}, + {file = "orjson-3.10.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5410111d7b6681d4b0d65e0f58a13be588d01b473822483f77f513c7f93bd3b2"}, + {file = "orjson-3.10.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb1f28a137337fdc18384079fa5726810681055b32b92253fa15ae5656e1dddb"}, + {file = "orjson-3.10.6-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:bf2fbbce5fe7cd1aa177ea3eab2b8e6a6bc6e8592e4279ed3db2d62e57c0e1b2"}, + {file = "orjson-3.10.6-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:79b9b9e33bd4c517445a62b90ca0cc279b0f1f3970655c3df9e608bc3f91741a"}, + {file = "orjson-3.10.6-cp39-none-win32.whl", hash = "sha256:30b0a09a2014e621b1adf66a4f705f0809358350a757508ee80209b2d8dae219"}, + {file = "orjson-3.10.6-cp39-none-win_amd64.whl", hash = "sha256:49e3bc615652617d463069f91b867a4458114c5b104e13b7ae6872e5f79d0844"}, + {file = "orjson-3.10.6.tar.gz", hash = "sha256:e54b63d0a7c6c54a5f5f726bc93a2078111ef060fec4ecbf34c5db800ca3b3a7"}, ] [[package]] @@ -391,6 +1062,27 @@ files = [ {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, ] +[[package]] +name = "paginate" +version = "0.5.6" +description = "Divides large result sets into pages for easier browsing" +optional = false +python-versions = "*" +files = [ + {file = "paginate-0.5.6.tar.gz", hash = "sha256:5e6007b6a9398177a7e1648d04fdd9f8c9766a1a945bceac82f1929e8c78af2d"}, +] + +[[package]] +name = "pathspec" +version = "0.12.1" +description = "Utility library for gitignore style pattern matching of file paths." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, + {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, +] + [[package]] name = "pendulum" version = "3.0.0" @@ -490,6 +1182,103 @@ tzdata = ">=2020.1" [package.extras] test = ["time-machine (>=2.6.0)"] +[[package]] +name = "pillow" +version = "10.4.0" +description = "Python Imaging Library (Fork)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pillow-10.4.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:4d9667937cfa347525b319ae34375c37b9ee6b525440f3ef48542fcf66f2731e"}, + {file = "pillow-10.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:543f3dc61c18dafb755773efc89aae60d06b6596a63914107f75459cf984164d"}, + {file = "pillow-10.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7928ecbf1ece13956b95d9cbcfc77137652b02763ba384d9ab508099a2eca856"}, + {file = "pillow-10.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4d49b85c4348ea0b31ea63bc75a9f3857869174e2bf17e7aba02945cd218e6f"}, + {file = "pillow-10.4.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:6c762a5b0997f5659a5ef2266abc1d8851ad7749ad9a6a5506eb23d314e4f46b"}, + {file = "pillow-10.4.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:a985e028fc183bf12a77a8bbf36318db4238a3ded7fa9df1b9a133f1cb79f8fc"}, + {file = "pillow-10.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:812f7342b0eee081eaec84d91423d1b4650bb9828eb53d8511bcef8ce5aecf1e"}, + {file = "pillow-10.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ac1452d2fbe4978c2eec89fb5a23b8387aba707ac72810d9490118817d9c0b46"}, + {file = "pillow-10.4.0-cp310-cp310-win32.whl", hash = "sha256:bcd5e41a859bf2e84fdc42f4edb7d9aba0a13d29a2abadccafad99de3feff984"}, + {file = "pillow-10.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:ecd85a8d3e79cd7158dec1c9e5808e821feea088e2f69a974db5edf84dc53141"}, + {file = "pillow-10.4.0-cp310-cp310-win_arm64.whl", hash = "sha256:ff337c552345e95702c5fde3158acb0625111017d0e5f24bf3acdb9cc16b90d1"}, + {file = "pillow-10.4.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:0a9ec697746f268507404647e531e92889890a087e03681a3606d9b920fbee3c"}, + {file = "pillow-10.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dfe91cb65544a1321e631e696759491ae04a2ea11d36715eca01ce07284738be"}, + {file = "pillow-10.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5dc6761a6efc781e6a1544206f22c80c3af4c8cf461206d46a1e6006e4429ff3"}, + {file = "pillow-10.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e84b6cc6a4a3d76c153a6b19270b3526a5a8ed6b09501d3af891daa2a9de7d6"}, + {file = "pillow-10.4.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:bbc527b519bd3aa9d7f429d152fea69f9ad37c95f0b02aebddff592688998abe"}, + {file = "pillow-10.4.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:76a911dfe51a36041f2e756b00f96ed84677cdeb75d25c767f296c1c1eda1319"}, + {file = "pillow-10.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:59291fb29317122398786c2d44427bbd1a6d7ff54017075b22be9d21aa59bd8d"}, + {file = "pillow-10.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:416d3a5d0e8cfe4f27f574362435bc9bae57f679a7158e0096ad2beb427b8696"}, + {file = "pillow-10.4.0-cp311-cp311-win32.whl", hash = "sha256:7086cc1d5eebb91ad24ded9f58bec6c688e9f0ed7eb3dbbf1e4800280a896496"}, + {file = "pillow-10.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cbed61494057c0f83b83eb3a310f0bf774b09513307c434d4366ed64f4128a91"}, + {file = "pillow-10.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:f5f0c3e969c8f12dd2bb7e0b15d5c468b51e5017e01e2e867335c81903046a22"}, + {file = "pillow-10.4.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:673655af3eadf4df6b5457033f086e90299fdd7a47983a13827acf7459c15d94"}, + {file = "pillow-10.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:866b6942a92f56300012f5fbac71f2d610312ee65e22f1aa2609e491284e5597"}, + {file = "pillow-10.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29dbdc4207642ea6aad70fbde1a9338753d33fb23ed6956e706936706f52dd80"}, + {file = "pillow-10.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf2342ac639c4cf38799a44950bbc2dfcb685f052b9e262f446482afaf4bffca"}, + {file = "pillow-10.4.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:f5b92f4d70791b4a67157321c4e8225d60b119c5cc9aee8ecf153aace4aad4ef"}, + {file = "pillow-10.4.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:86dcb5a1eb778d8b25659d5e4341269e8590ad6b4e8b44d9f4b07f8d136c414a"}, + {file = "pillow-10.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:780c072c2e11c9b2c7ca37f9a2ee8ba66f44367ac3e5c7832afcfe5104fd6d1b"}, + {file = "pillow-10.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:37fb69d905be665f68f28a8bba3c6d3223c8efe1edf14cc4cfa06c241f8c81d9"}, + {file = "pillow-10.4.0-cp312-cp312-win32.whl", hash = "sha256:7dfecdbad5c301d7b5bde160150b4db4c659cee2b69589705b6f8a0c509d9f42"}, + {file = "pillow-10.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:1d846aea995ad352d4bdcc847535bd56e0fd88d36829d2c90be880ef1ee4668a"}, + {file = "pillow-10.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:e553cad5179a66ba15bb18b353a19020e73a7921296a7979c4a2b7f6a5cd57f9"}, + {file = "pillow-10.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8bc1a764ed8c957a2e9cacf97c8b2b053b70307cf2996aafd70e91a082e70df3"}, + {file = "pillow-10.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6209bb41dc692ddfee4942517c19ee81b86c864b626dbfca272ec0f7cff5d9fb"}, + {file = "pillow-10.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bee197b30783295d2eb680b311af15a20a8b24024a19c3a26431ff83eb8d1f70"}, + {file = "pillow-10.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ef61f5dd14c300786318482456481463b9d6b91ebe5ef12f405afbba77ed0be"}, + {file = "pillow-10.4.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:297e388da6e248c98bc4a02e018966af0c5f92dfacf5a5ca22fa01cb3179bca0"}, + {file = "pillow-10.4.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:e4db64794ccdf6cb83a59d73405f63adbe2a1887012e308828596100a0b2f6cc"}, + {file = "pillow-10.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bd2880a07482090a3bcb01f4265f1936a903d70bc740bfcb1fd4e8a2ffe5cf5a"}, + {file = "pillow-10.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4b35b21b819ac1dbd1233317adeecd63495f6babf21b7b2512d244ff6c6ce309"}, + {file = "pillow-10.4.0-cp313-cp313-win32.whl", hash = "sha256:551d3fd6e9dc15e4c1eb6fc4ba2b39c0c7933fa113b220057a34f4bb3268a060"}, + {file = "pillow-10.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:030abdbe43ee02e0de642aee345efa443740aa4d828bfe8e2eb11922ea6a21ea"}, + {file = "pillow-10.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:5b001114dd152cfd6b23befeb28d7aee43553e2402c9f159807bf55f33af8a8d"}, + {file = "pillow-10.4.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:8d4d5063501b6dd4024b8ac2f04962d661222d120381272deea52e3fc52d3736"}, + {file = "pillow-10.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7c1ee6f42250df403c5f103cbd2768a28fe1a0ea1f0f03fe151c8741e1469c8b"}, + {file = "pillow-10.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b15e02e9bb4c21e39876698abf233c8c579127986f8207200bc8a8f6bb27acf2"}, + {file = "pillow-10.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a8d4bade9952ea9a77d0c3e49cbd8b2890a399422258a77f357b9cc9be8d680"}, + {file = "pillow-10.4.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:43efea75eb06b95d1631cb784aa40156177bf9dd5b4b03ff38979e048258bc6b"}, + {file = "pillow-10.4.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:950be4d8ba92aca4b2bb0741285a46bfae3ca699ef913ec8416c1b78eadd64cd"}, + {file = "pillow-10.4.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d7480af14364494365e89d6fddc510a13e5a2c3584cb19ef65415ca57252fb84"}, + {file = "pillow-10.4.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:73664fe514b34c8f02452ffb73b7a92c6774e39a647087f83d67f010eb9a0cf0"}, + {file = "pillow-10.4.0-cp38-cp38-win32.whl", hash = "sha256:e88d5e6ad0d026fba7bdab8c3f225a69f063f116462c49892b0149e21b6c0a0e"}, + {file = "pillow-10.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:5161eef006d335e46895297f642341111945e2c1c899eb406882a6c61a4357ab"}, + {file = "pillow-10.4.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:0ae24a547e8b711ccaaf99c9ae3cd975470e1a30caa80a6aaee9a2f19c05701d"}, + {file = "pillow-10.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:298478fe4f77a4408895605f3482b6cc6222c018b2ce565c2b6b9c354ac3229b"}, + {file = "pillow-10.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:134ace6dc392116566980ee7436477d844520a26a4b1bd4053f6f47d096997fd"}, + {file = "pillow-10.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:930044bb7679ab003b14023138b50181899da3f25de50e9dbee23b61b4de2126"}, + {file = "pillow-10.4.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:c76e5786951e72ed3686e122d14c5d7012f16c8303a674d18cdcd6d89557fc5b"}, + {file = "pillow-10.4.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:b2724fdb354a868ddf9a880cb84d102da914e99119211ef7ecbdc613b8c96b3c"}, + {file = "pillow-10.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dbc6ae66518ab3c5847659e9988c3b60dc94ffb48ef9168656e0019a93dbf8a1"}, + {file = "pillow-10.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:06b2f7898047ae93fad74467ec3d28fe84f7831370e3c258afa533f81ef7f3df"}, + {file = "pillow-10.4.0-cp39-cp39-win32.whl", hash = "sha256:7970285ab628a3779aecc35823296a7869f889b8329c16ad5a71e4901a3dc4ef"}, + {file = "pillow-10.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:961a7293b2457b405967af9c77dcaa43cc1a8cd50d23c532e62d48ab6cdd56f5"}, + {file = "pillow-10.4.0-cp39-cp39-win_arm64.whl", hash = "sha256:32cda9e3d601a52baccb2856b8ea1fc213c90b340c542dcef77140dfa3278a9e"}, + {file = "pillow-10.4.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:5b4815f2e65b30f5fbae9dfffa8636d992d49705723fe86a3661806e069352d4"}, + {file = "pillow-10.4.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:8f0aef4ef59694b12cadee839e2ba6afeab89c0f39a3adc02ed51d109117b8da"}, + {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9f4727572e2918acaa9077c919cbbeb73bd2b3ebcfe033b72f858fc9fbef0026"}, + {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff25afb18123cea58a591ea0244b92eb1e61a1fd497bf6d6384f09bc3262ec3e"}, + {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:dc3e2db6ba09ffd7d02ae9141cfa0ae23393ee7687248d46a7507b75d610f4f5"}, + {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:02a2be69f9c9b8c1e97cf2713e789d4e398c751ecfd9967c18d0ce304efbf885"}, + {file = "pillow-10.4.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:0755ffd4a0c6f267cccbae2e9903d95477ca2f77c4fcf3a3a09570001856c8a5"}, + {file = "pillow-10.4.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:a02364621fe369e06200d4a16558e056fe2805d3468350df3aef21e00d26214b"}, + {file = "pillow-10.4.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:1b5dea9831a90e9d0721ec417a80d4cbd7022093ac38a568db2dd78363b00908"}, + {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9b885f89040bb8c4a1573566bbb2f44f5c505ef6e74cec7ab9068c900047f04b"}, + {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87dd88ded2e6d74d31e1e0a99a726a6765cda32d00ba72dc37f0651f306daaa8"}, + {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:2db98790afc70118bd0255c2eeb465e9767ecf1f3c25f9a1abb8ffc8cfd1fe0a"}, + {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f7baece4ce06bade126fb84b8af1c33439a76d8a6fd818970215e0560ca28c27"}, + {file = "pillow-10.4.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:cfdd747216947628af7b259d274771d84db2268ca062dd5faf373639d00113a3"}, + {file = "pillow-10.4.0.tar.gz", hash = "sha256:166c1cd4d24309b30d61f79f4a9114b7b2313d7450912277855ff5dfd7cd4a06"}, +] + +[package.extras] +docs = ["furo", "olefile", "sphinx (>=7.3)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinxext-opengraph"] +fpx = ["olefile"] +mic = ["olefile"] +tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] +typing = ["typing-extensions"] +xmp = ["defusedxml"] + [[package]] name = "platformdirs" version = "4.2.2" @@ -539,34 +1328,91 @@ nodeenv = ">=0.11.1" pyyaml = ">=5.1" virtualenv = ">=20.10.0" +[[package]] +name = "pycparser" +version = "2.22" +description = "C parser in Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, + {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, +] + +[[package]] +name = "pygments" +version = "2.18.0" +description = "Pygments is a syntax highlighting package written in Python." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"}, + {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"}, +] + +[package.extras] +windows-terminal = ["colorama (>=0.4.6)"] + +[[package]] +name = "pymdown-extensions" +version = "10.8.1" +description = "Extension pack for Python Markdown." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pymdown_extensions-10.8.1-py3-none-any.whl", hash = "sha256:f938326115884f48c6059c67377c46cf631c733ef3629b6eed1349989d1b30cb"}, + {file = "pymdown_extensions-10.8.1.tar.gz", hash = "sha256:3ab1db5c9e21728dabf75192d71471f8e50f216627e9a1fa9535ecb0231b9940"}, +] + +[package.dependencies] +markdown = ">=3.6" +pyyaml = "*" + +[package.extras] +extra = ["pygments (>=2.12)"] + +[[package]] +name = "pyparsing" +version = "3.1.2" +description = "pyparsing module - Classes and methods to define and execute parsing grammars" +optional = false +python-versions = ">=3.6.8" +files = [ + {file = "pyparsing-3.1.2-py3-none-any.whl", hash = "sha256:f9db75911801ed778fe61bb643079ff86601aca99fcae6345aa67292038fb742"}, + {file = "pyparsing-3.1.2.tar.gz", hash = "sha256:a1bac0ce561155ecc3ed78ca94d3c9378656ad4c94c1270de543f621420f94ad"}, +] + +[package.extras] +diagrams = ["jinja2", "railroad-diagrams"] + [[package]] name = "pyproject-api" -version = "1.6.1" +version = "1.7.1" description = "API to interact with the python pyproject.toml based projects" optional = false python-versions = ">=3.8" files = [ - {file = "pyproject_api-1.6.1-py3-none-any.whl", hash = "sha256:4c0116d60476b0786c88692cf4e325a9814965e2469c5998b830bba16b183675"}, - {file = "pyproject_api-1.6.1.tar.gz", hash = "sha256:1817dc018adc0d1ff9ca1ed8c60e1623d5aaca40814b953af14a9cf9a5cae538"}, + {file = "pyproject_api-1.7.1-py3-none-any.whl", hash = "sha256:2dc1654062c2b27733d8fd4cdda672b22fe8741ef1dde8e3a998a9547b071eeb"}, + {file = "pyproject_api-1.7.1.tar.gz", hash = "sha256:7ebc6cd10710f89f4cf2a2731710a98abce37ebff19427116ff2174c9236a827"}, ] [package.dependencies] -packaging = ">=23.1" +packaging = ">=24.1" tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} [package.extras] -docs = ["furo (>=2023.8.19)", "sphinx (<7.2)", "sphinx-autodoc-typehints (>=1.24)"] -testing = ["covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)", "setuptools (>=68.1.2)", "wheel (>=0.41.2)"] +docs = ["furo (>=2024.5.6)", "sphinx-autodoc-typehints (>=2.2.1)"] +testing = ["covdefaults (>=2.3)", "pytest (>=8.2.2)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "setuptools (>=70.1)"] [[package]] name = "pytest" -version = "8.2.2" +version = "8.3.1" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" files = [ - {file = "pytest-8.2.2-py3-none-any.whl", hash = "sha256:c434598117762e2bd304e526244f67bf66bbd7b5d6cf22138be51ff661980343"}, - {file = "pytest-8.2.2.tar.gz", hash = "sha256:de4bb8104e201939ccdc688b27a89a7be2079b22e2bd2b07f806b6ba71117977"}, + {file = "pytest-8.3.1-py3-none-any.whl", hash = "sha256:e9600ccf4f563976e2c99fa02c7624ab938296551f280835ee6516df8bc4ae8c"}, + {file = "pytest-8.3.1.tar.gz", hash = "sha256:7e8e5c5abd6e93cb1cc151f23e57adc31fcf8cfd2a3ff2da63e23f732de35db6"}, ] [package.dependencies] @@ -574,7 +1420,7 @@ colorama = {version = "*", markers = "sys_platform == \"win32\""} exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} iniconfig = "*" packaging = "*" -pluggy = ">=1.5,<2.0" +pluggy = ">=1.5,<2" tomli = {version = ">=1", markers = "python_version < \"3.11\""} [package.extras] @@ -686,6 +1532,129 @@ files = [ {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, ] +[[package]] +name = "pyyaml-env-tag" +version = "0.1" +description = "A custom YAML tag for referencing environment variables in YAML files. " +optional = false +python-versions = ">=3.6" +files = [ + {file = "pyyaml_env_tag-0.1-py3-none-any.whl", hash = "sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069"}, + {file = "pyyaml_env_tag-0.1.tar.gz", hash = "sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb"}, +] + +[package.dependencies] +pyyaml = "*" + +[[package]] +name = "regex" +version = "2024.5.15" +description = "Alternative regular expression module, to replace re." +optional = false +python-versions = ">=3.8" +files = [ + {file = "regex-2024.5.15-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a81e3cfbae20378d75185171587cbf756015ccb14840702944f014e0d93ea09f"}, + {file = "regex-2024.5.15-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7b59138b219ffa8979013be7bc85bb60c6f7b7575df3d56dc1e403a438c7a3f6"}, + {file = "regex-2024.5.15-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a0bd000c6e266927cb7a1bc39d55be95c4b4f65c5be53e659537537e019232b1"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5eaa7ddaf517aa095fa8da0b5015c44d03da83f5bd49c87961e3c997daed0de7"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba68168daedb2c0bab7fd7e00ced5ba90aebf91024dea3c88ad5063c2a562cca"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6e8d717bca3a6e2064fc3a08df5cbe366369f4b052dcd21b7416e6d71620dca1"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1337b7dbef9b2f71121cdbf1e97e40de33ff114801263b275aafd75303bd62b5"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f9ebd0a36102fcad2f03696e8af4ae682793a5d30b46c647eaf280d6cfb32796"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9efa1a32ad3a3ea112224897cdaeb6aa00381627f567179c0314f7b65d354c62"}, + {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1595f2d10dff3d805e054ebdc41c124753631b6a471b976963c7b28543cf13b0"}, + {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b802512f3e1f480f41ab5f2cfc0e2f761f08a1f41092d6718868082fc0d27143"}, + {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:a0981022dccabca811e8171f913de05720590c915b033b7e601f35ce4ea7019f"}, + {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:19068a6a79cf99a19ccefa44610491e9ca02c2be3305c7760d3831d38a467a6f"}, + {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1b5269484f6126eee5e687785e83c6b60aad7663dafe842b34691157e5083e53"}, + {file = "regex-2024.5.15-cp310-cp310-win32.whl", hash = "sha256:ada150c5adfa8fbcbf321c30c751dc67d2f12f15bd183ffe4ec7cde351d945b3"}, + {file = "regex-2024.5.15-cp310-cp310-win_amd64.whl", hash = "sha256:ac394ff680fc46b97487941f5e6ae49a9f30ea41c6c6804832063f14b2a5a145"}, + {file = "regex-2024.5.15-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f5b1dff3ad008dccf18e652283f5e5339d70bf8ba7c98bf848ac33db10f7bc7a"}, + {file = "regex-2024.5.15-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c6a2b494a76983df8e3d3feea9b9ffdd558b247e60b92f877f93a1ff43d26656"}, + {file = "regex-2024.5.15-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a32b96f15c8ab2e7d27655969a23895eb799de3665fa94349f3b2fbfd547236f"}, + {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:10002e86e6068d9e1c91eae8295ef690f02f913c57db120b58fdd35a6bb1af35"}, + {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ec54d5afa89c19c6dd8541a133be51ee1017a38b412b1321ccb8d6ddbeb4cf7d"}, + {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:10e4ce0dca9ae7a66e6089bb29355d4432caed736acae36fef0fdd7879f0b0cb"}, + {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3e507ff1e74373c4d3038195fdd2af30d297b4f0950eeda6f515ae3d84a1770f"}, + {file = "regex-2024.5.15-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d1f059a4d795e646e1c37665b9d06062c62d0e8cc3c511fe01315973a6542e40"}, + {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0721931ad5fe0dda45d07f9820b90b2148ccdd8e45bb9e9b42a146cb4f695649"}, + {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:833616ddc75ad595dee848ad984d067f2f31be645d603e4d158bba656bbf516c"}, + {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:287eb7f54fc81546346207c533ad3c2c51a8d61075127d7f6d79aaf96cdee890"}, + {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:19dfb1c504781a136a80ecd1fff9f16dddf5bb43cec6871778c8a907a085bb3d"}, + {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:119af6e56dce35e8dfb5222573b50c89e5508d94d55713c75126b753f834de68"}, + {file = "regex-2024.5.15-cp311-cp311-win32.whl", hash = "sha256:1c1c174d6ec38d6c8a7504087358ce9213d4332f6293a94fbf5249992ba54efa"}, + {file = "regex-2024.5.15-cp311-cp311-win_amd64.whl", hash = "sha256:9e717956dcfd656f5055cc70996ee2cc82ac5149517fc8e1b60261b907740201"}, + {file = "regex-2024.5.15-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:632b01153e5248c134007209b5c6348a544ce96c46005d8456de1d552455b014"}, + {file = "regex-2024.5.15-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e64198f6b856d48192bf921421fdd8ad8eb35e179086e99e99f711957ffedd6e"}, + {file = "regex-2024.5.15-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68811ab14087b2f6e0fc0c2bae9ad689ea3584cad6917fc57be6a48bbd012c49"}, + {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8ec0c2fea1e886a19c3bee0cd19d862b3aa75dcdfb42ebe8ed30708df64687a"}, + {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d0c0c0003c10f54a591d220997dd27d953cd9ccc1a7294b40a4be5312be8797b"}, + {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2431b9e263af1953c55abbd3e2efca67ca80a3de8a0437cb58e2421f8184717a"}, + {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a605586358893b483976cffc1723fb0f83e526e8f14c6e6614e75919d9862cf"}, + {file = "regex-2024.5.15-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:391d7f7f1e409d192dba8bcd42d3e4cf9e598f3979cdaed6ab11288da88cb9f2"}, + {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9ff11639a8d98969c863d4617595eb5425fd12f7c5ef6621a4b74b71ed8726d5"}, + {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4eee78a04e6c67e8391edd4dad3279828dd66ac4b79570ec998e2155d2e59fd5"}, + {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8fe45aa3f4aa57faabbc9cb46a93363edd6197cbc43523daea044e9ff2fea83e"}, + {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:d0a3d8d6acf0c78a1fff0e210d224b821081330b8524e3e2bc5a68ef6ab5803d"}, + {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c486b4106066d502495b3025a0a7251bf37ea9540433940a23419461ab9f2a80"}, + {file = "regex-2024.5.15-cp312-cp312-win32.whl", hash = "sha256:c49e15eac7c149f3670b3e27f1f28a2c1ddeccd3a2812cba953e01be2ab9b5fe"}, + {file = "regex-2024.5.15-cp312-cp312-win_amd64.whl", hash = "sha256:673b5a6da4557b975c6c90198588181029c60793835ce02f497ea817ff647cb2"}, + {file = "regex-2024.5.15-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:87e2a9c29e672fc65523fb47a90d429b70ef72b901b4e4b1bd42387caf0d6835"}, + {file = "regex-2024.5.15-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c3bea0ba8b73b71b37ac833a7f3fd53825924165da6a924aec78c13032f20850"}, + {file = "regex-2024.5.15-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bfc4f82cabe54f1e7f206fd3d30fda143f84a63fe7d64a81558d6e5f2e5aaba9"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5bb9425fe881d578aeca0b2b4b3d314ec88738706f66f219c194d67179337cb"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:64c65783e96e563103d641760664125e91bd85d8e49566ee560ded4da0d3e704"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cf2430df4148b08fb4324b848672514b1385ae3807651f3567871f130a728cc3"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5397de3219a8b08ae9540c48f602996aa6b0b65d5a61683e233af8605c42b0f2"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:455705d34b4154a80ead722f4f185b04c4237e8e8e33f265cd0798d0e44825fa"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b2b6f1b3bb6f640c1a92be3bbfbcb18657b125b99ecf141fb3310b5282c7d4ed"}, + {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:3ad070b823ca5890cab606c940522d05d3d22395d432f4aaaf9d5b1653e47ced"}, + {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:5b5467acbfc153847d5adb21e21e29847bcb5870e65c94c9206d20eb4e99a384"}, + {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:e6662686aeb633ad65be2a42b4cb00178b3fbf7b91878f9446075c404ada552f"}, + {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:2b4c884767504c0e2401babe8b5b7aea9148680d2e157fa28f01529d1f7fcf67"}, + {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:3cd7874d57f13bf70078f1ff02b8b0aa48d5b9ed25fc48547516c6aba36f5741"}, + {file = "regex-2024.5.15-cp38-cp38-win32.whl", hash = "sha256:e4682f5ba31f475d58884045c1a97a860a007d44938c4c0895f41d64481edbc9"}, + {file = "regex-2024.5.15-cp38-cp38-win_amd64.whl", hash = "sha256:d99ceffa25ac45d150e30bd9ed14ec6039f2aad0ffa6bb87a5936f5782fc1569"}, + {file = "regex-2024.5.15-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:13cdaf31bed30a1e1c2453ef6015aa0983e1366fad2667657dbcac7b02f67133"}, + {file = "regex-2024.5.15-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cac27dcaa821ca271855a32188aa61d12decb6fe45ffe3e722401fe61e323cd1"}, + {file = "regex-2024.5.15-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7dbe2467273b875ea2de38ded4eba86cbcbc9a1a6d0aa11dcf7bd2e67859c435"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64f18a9a3513a99c4bef0e3efd4c4a5b11228b48aa80743be822b71e132ae4f5"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d347a741ea871c2e278fde6c48f85136c96b8659b632fb57a7d1ce1872547600"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1878b8301ed011704aea4c806a3cadbd76f84dece1ec09cc9e4dc934cfa5d4da"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4babf07ad476aaf7830d77000874d7611704a7fcf68c9c2ad151f5d94ae4bfc4"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:35cb514e137cb3488bce23352af3e12fb0dbedd1ee6e60da053c69fb1b29cc6c"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cdd09d47c0b2efee9378679f8510ee6955d329424c659ab3c5e3a6edea696294"}, + {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:72d7a99cd6b8f958e85fc6ca5b37c4303294954eac1376535b03c2a43eb72629"}, + {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:a094801d379ab20c2135529948cb84d417a2169b9bdceda2a36f5f10977ebc16"}, + {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:c0c18345010870e58238790a6779a1219b4d97bd2e77e1140e8ee5d14df071aa"}, + {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:16093f563098448ff6b1fa68170e4acbef94e6b6a4e25e10eae8598bb1694b5d"}, + {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e38a7d4e8f633a33b4c7350fbd8bad3b70bf81439ac67ac38916c4a86b465456"}, + {file = "regex-2024.5.15-cp39-cp39-win32.whl", hash = "sha256:71a455a3c584a88f654b64feccc1e25876066c4f5ef26cd6dd711308aa538694"}, + {file = "regex-2024.5.15-cp39-cp39-win_amd64.whl", hash = "sha256:cab12877a9bdafde5500206d1020a584355a97884dfd388af3699e9137bf7388"}, + {file = "regex-2024.5.15.tar.gz", hash = "sha256:d3ee02d9e5f482cc8309134a91eeaacbdd2261ba111b0fef3748eeb4913e6a2c"}, +] + +[[package]] +name = "requests" +version = "2.32.3" +description = "Python HTTP for Humans." +optional = false +python-versions = ">=3.8" +files = [ + {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, + {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, +] + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<4" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<3" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + [[package]] name = "semver" version = "3.0.2" @@ -708,6 +1677,24 @@ files = [ {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, ] +[[package]] +name = "tinycss2" +version = "1.3.0" +description = "A tiny CSS parser" +optional = false +python-versions = ">=3.8" +files = [ + {file = "tinycss2-1.3.0-py3-none-any.whl", hash = "sha256:54a8dbdffb334d536851be0226030e9505965bb2f30f21a4a82c55fb2a80fae7"}, + {file = "tinycss2-1.3.0.tar.gz", hash = "sha256:152f9acabd296a8375fbca5b84c961ff95971fcfc32e79550c8df8e29118c54d"}, +] + +[package.dependencies] +webencodings = ">=0.4" + +[package.extras] +doc = ["sphinx", "sphinx_rtd_theme"] +test = ["pytest", "ruff"] + [[package]] name = "tomli" version = "2.0.1" @@ -721,30 +1708,30 @@ files = [ [[package]] name = "tox" -version = "4.15.1" +version = "4.16.0" description = "tox is a generic virtualenv management and test command line tool" optional = false python-versions = ">=3.8" files = [ - {file = "tox-4.15.1-py3-none-any.whl", hash = "sha256:f00a5dc4222b358e69694e47e3da0227ac41253509bca9f45aa8f012053e8d9d"}, - {file = "tox-4.15.1.tar.gz", hash = "sha256:53a092527d65e873e39213ebd4bd027a64623320b6b0326136384213f95b7076"}, + {file = "tox-4.16.0-py3-none-any.whl", hash = "sha256:61e101061b977b46cf00093d4319438055290ad0009f84497a07bf2d2d7a06d0"}, + {file = "tox-4.16.0.tar.gz", hash = "sha256:43499656f9949edb681c0f907f86fbfee98677af9919d8b11ae5ad77cb800748"}, ] [package.dependencies] -cachetools = ">=5.3.2" +cachetools = ">=5.3.3" chardet = ">=5.2" colorama = ">=0.4.6" -filelock = ">=3.13.1" -packaging = ">=23.2" -platformdirs = ">=4.1" -pluggy = ">=1.3" -pyproject-api = ">=1.6.1" +filelock = ">=3.15.4" +packaging = ">=24.1" +platformdirs = ">=4.2.2" +pluggy = ">=1.5" +pyproject-api = ">=1.7.1" tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} -virtualenv = ">=20.25" +virtualenv = ">=20.26.3" [package.extras] -docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-argparse-cli (>=1.11.1)", "sphinx-autodoc-typehints (>=1.25.2)", "sphinx-copybutton (>=0.5.2)", "sphinx-inline-tabs (>=2023.4.21)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.11)"] -testing = ["build[virtualenv] (>=1.0.3)", "covdefaults (>=2.3)", "detect-test-pollution (>=1.2)", "devpi-process (>=1)", "diff-cover (>=8.0.2)", "distlib (>=0.3.8)", "flaky (>=3.7)", "hatch-vcs (>=0.4)", "hatchling (>=1.21)", "psutil (>=5.9.7)", "pytest (>=7.4.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-xdist (>=3.5)", "re-assert (>=1.1)", "time-machine (>=2.13)", "wheel (>=0.42)"] +docs = ["furo (>=2024.5.6)", "sphinx (>=7.3.7)", "sphinx-argparse-cli (>=1.16)", "sphinx-autodoc-typehints (>=2.2.2)", "sphinx-copybutton (>=0.5.2)", "sphinx-inline-tabs (>=2023.4.21)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.11)"] +testing = ["build[virtualenv] (>=1.2.1)", "covdefaults (>=2.3)", "detect-test-pollution (>=1.2)", "devpi-process (>=1)", "diff-cover (>=9.1)", "distlib (>=0.3.8)", "flaky (>=3.8.1)", "hatch-vcs (>=0.4)", "hatchling (>=1.25)", "psutil (>=6)", "pytest (>=8.2.2)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "pytest-xdist (>=3.6.1)", "re-assert (>=1.1)", "setuptools (>=70.2)", "time-machine (>=2.14.2)", "wheel (>=0.43)"] [[package]] name = "typing-extensions" @@ -768,15 +1755,46 @@ files = [ {file = "tzdata-2024.1.tar.gz", hash = "sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd"}, ] +[[package]] +name = "urllib3" +version = "2.2.2" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=3.8" +files = [ + {file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"}, + {file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"}, +] + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +h2 = ["h2 (>=4,<5)"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] + +[[package]] +name = "verspec" +version = "0.1.0" +description = "Flexible version handling" +optional = false +python-versions = "*" +files = [ + {file = "verspec-0.1.0-py3-none-any.whl", hash = "sha256:741877d5633cc9464c45a469ae2a31e801e6dbbaa85b9675d481cda100f11c31"}, + {file = "verspec-0.1.0.tar.gz", hash = "sha256:c4504ca697b2056cdb4bfa7121461f5a0e81809255b41c03dda4ba823637c01e"}, +] + +[package.extras] +test = ["coverage", "flake8 (>=3.7)", "mypy", "pretend", "pytest"] + [[package]] name = "virtualenv" -version = "20.26.2" +version = "20.26.3" description = "Virtual Python Environment builder" optional = false python-versions = ">=3.7" files = [ - {file = "virtualenv-20.26.2-py3-none-any.whl", hash = "sha256:a624db5e94f01ad993d476b9ee5346fdf7b9de43ccaee0e0197012dc838a0e9b"}, - {file = "virtualenv-20.26.2.tar.gz", hash = "sha256:82bf0f4eebbb78d36ddaee0283d43fe5736b53880b8a8cdcd37390a07ac3741c"}, + {file = "virtualenv-20.26.3-py3-none-any.whl", hash = "sha256:8cc4a31139e796e9a7de2cd5cf2489de1217193116a8fd42328f1bd65f434589"}, + {file = "virtualenv-20.26.3.tar.gz", hash = "sha256:4c43a2a236279d9ea36a0d76f98d84bd6ca94ac4e0f4a3b9d46d05e10fea542a"}, ] [package.dependencies] @@ -788,10 +1806,94 @@ platformdirs = ">=3.9.1,<5" docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"] +[[package]] +name = "watchdog" +version = "4.0.1" +description = "Filesystem events monitoring" +optional = false +python-versions = ">=3.8" +files = [ + {file = "watchdog-4.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:da2dfdaa8006eb6a71051795856bedd97e5b03e57da96f98e375682c48850645"}, + {file = "watchdog-4.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e93f451f2dfa433d97765ca2634628b789b49ba8b504fdde5837cdcf25fdb53b"}, + {file = "watchdog-4.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ef0107bbb6a55f5be727cfc2ef945d5676b97bffb8425650dadbb184be9f9a2b"}, + {file = "watchdog-4.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:17e32f147d8bf9657e0922c0940bcde863b894cd871dbb694beb6704cfbd2fb5"}, + {file = "watchdog-4.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:03e70d2df2258fb6cb0e95bbdbe06c16e608af94a3ffbd2b90c3f1e83eb10767"}, + {file = "watchdog-4.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:123587af84260c991dc5f62a6e7ef3d1c57dfddc99faacee508c71d287248459"}, + {file = "watchdog-4.0.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:093b23e6906a8b97051191a4a0c73a77ecc958121d42346274c6af6520dec175"}, + {file = "watchdog-4.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:611be3904f9843f0529c35a3ff3fd617449463cb4b73b1633950b3d97fa4bfb7"}, + {file = "watchdog-4.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:62c613ad689ddcb11707f030e722fa929f322ef7e4f18f5335d2b73c61a85c28"}, + {file = "watchdog-4.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:d4925e4bf7b9bddd1c3de13c9b8a2cdb89a468f640e66fbfabaf735bd85b3e35"}, + {file = "watchdog-4.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cad0bbd66cd59fc474b4a4376bc5ac3fc698723510cbb64091c2a793b18654db"}, + {file = "watchdog-4.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a3c2c317a8fb53e5b3d25790553796105501a235343f5d2bf23bb8649c2c8709"}, + {file = "watchdog-4.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c9904904b6564d4ee8a1ed820db76185a3c96e05560c776c79a6ce5ab71888ba"}, + {file = "watchdog-4.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:667f3c579e813fcbad1b784db7a1aaa96524bed53437e119f6a2f5de4db04235"}, + {file = "watchdog-4.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d10a681c9a1d5a77e75c48a3b8e1a9f2ae2928eda463e8d33660437705659682"}, + {file = "watchdog-4.0.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0144c0ea9997b92615af1d94afc0c217e07ce2c14912c7b1a5731776329fcfc7"}, + {file = "watchdog-4.0.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:998d2be6976a0ee3a81fb8e2777900c28641fb5bfbd0c84717d89bca0addcdc5"}, + {file = "watchdog-4.0.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e7921319fe4430b11278d924ef66d4daa469fafb1da679a2e48c935fa27af193"}, + {file = "watchdog-4.0.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:f0de0f284248ab40188f23380b03b59126d1479cd59940f2a34f8852db710625"}, + {file = "watchdog-4.0.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:bca36be5707e81b9e6ce3208d92d95540d4ca244c006b61511753583c81c70dd"}, + {file = "watchdog-4.0.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:ab998f567ebdf6b1da7dc1e5accfaa7c6992244629c0fdaef062f43249bd8dee"}, + {file = "watchdog-4.0.1-py3-none-manylinux2014_aarch64.whl", hash = "sha256:dddba7ca1c807045323b6af4ff80f5ddc4d654c8bce8317dde1bd96b128ed253"}, + {file = "watchdog-4.0.1-py3-none-manylinux2014_armv7l.whl", hash = "sha256:4513ec234c68b14d4161440e07f995f231be21a09329051e67a2118a7a612d2d"}, + {file = "watchdog-4.0.1-py3-none-manylinux2014_i686.whl", hash = "sha256:4107ac5ab936a63952dea2a46a734a23230aa2f6f9db1291bf171dac3ebd53c6"}, + {file = "watchdog-4.0.1-py3-none-manylinux2014_ppc64.whl", hash = "sha256:6e8c70d2cd745daec2a08734d9f63092b793ad97612470a0ee4cbb8f5f705c57"}, + {file = "watchdog-4.0.1-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:f27279d060e2ab24c0aa98363ff906d2386aa6c4dc2f1a374655d4e02a6c5e5e"}, + {file = "watchdog-4.0.1-py3-none-manylinux2014_s390x.whl", hash = "sha256:f8affdf3c0f0466e69f5b3917cdd042f89c8c63aebdb9f7c078996f607cdb0f5"}, + {file = "watchdog-4.0.1-py3-none-manylinux2014_x86_64.whl", hash = "sha256:ac7041b385f04c047fcc2951dc001671dee1b7e0615cde772e84b01fbf68ee84"}, + {file = "watchdog-4.0.1-py3-none-win32.whl", hash = "sha256:206afc3d964f9a233e6ad34618ec60b9837d0582b500b63687e34011e15bb429"}, + {file = "watchdog-4.0.1-py3-none-win_amd64.whl", hash = "sha256:7577b3c43e5909623149f76b099ac49a1a01ca4e167d1785c76eb52fa585745a"}, + {file = "watchdog-4.0.1-py3-none-win_ia64.whl", hash = "sha256:d7b9f5f3299e8dd230880b6c55504a1f69cf1e4316275d1b215ebdd8187ec88d"}, + {file = "watchdog-4.0.1.tar.gz", hash = "sha256:eebaacf674fa25511e8867028d281e602ee6500045b57f43b08778082f7f8b44"}, +] + +[package.extras] +watchmedo = ["PyYAML (>=3.10)"] + +[[package]] +name = "wcmatch" +version = "8.5.2" +description = "Wildcard/glob file name matcher." +optional = false +python-versions = ">=3.8" +files = [ + {file = "wcmatch-8.5.2-py3-none-any.whl", hash = "sha256:17d3ad3758f9d0b5b4dedc770b65420d4dac62e680229c287bf24c9db856a478"}, + {file = "wcmatch-8.5.2.tar.gz", hash = "sha256:a70222b86dea82fb382dd87b73278c10756c138bd6f8f714e2183128887b9eb2"}, +] + +[package.dependencies] +bracex = ">=2.1.1" + +[[package]] +name = "webencodings" +version = "0.5.1" +description = "Character encoding aliases for legacy web content" +optional = false +python-versions = "*" +files = [ + {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, + {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, +] + +[[package]] +name = "zipp" +version = "3.19.2" +description = "Backport of pathlib-compatible object wrapper for zip files" +optional = false +python-versions = ">=3.8" +files = [ + {file = "zipp-3.19.2-py3-none-any.whl", hash = "sha256:f091755f667055f2d02b32c53771a7a6c8b47e1fdbc4b72a8b9072b3eef8015c"}, + {file = "zipp-3.19.2.tar.gz", hash = "sha256:bf1dcf6450f873a13e952a29504887c89e6de7506209e5b1bcc3460135d4de19"}, +] + +[package.extras] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] + [extras] json = ["orjson"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "697fac0372295a08b8339894d4858522486dd09f87c21ecb17d4cc9a3cfcbda9" +content-hash = "25cc2bb106fa88ba100919cb558a5df184a1aaab3636c8fb4d7130686229fca2" diff --git a/pyproject.toml b/pyproject.toml index d435255..4b09c91 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,6 +50,15 @@ pytest-parametrize-suite = "^23.1.1" pre-commit = "^3.7" [tool.poetry.group.docs.dependencies] +mkdocs-material = {extras = ["imaging"], version = "^9.5.29"} +mkdocstrings = {extras = ["python"], version = "^0.25"} +mkdocs-awesome-pages-plugin = "^2.9" +mkdocs-gen-files = "^0.5" +pymdown-extensions = "^10" +mike = "^2" +mkdocs-section-index = "^0.3.9" +mkdocs-literate-nav = "^0.6.1" +mkdocs-open-in-new-tab = "^1.0.3" [tool.poetry.group.dev.dependencies] diff --git a/scripts/gen_ref_pages.py b/scripts/gen_ref_pages.py new file mode 100644 index 0000000..4e356a8 --- /dev/null +++ b/scripts/gen_ref_pages.py @@ -0,0 +1,35 @@ +"""Generate the code reference pages and navigation.""" + +from pathlib import Path + +import mkdocs_gen_files + +nav = mkdocs_gen_files.Nav() + +root = Path(__file__).parent.parent +src = root / "src" + +for path in sorted(src.rglob("*.py")): + module_path = path.relative_to(src).with_suffix("") + doc_path = path.relative_to(src).with_suffix(".md") + full_doc_path = Path("reference", doc_path) + + parts = tuple(module_path.parts) + + if parts[-1] == "__init__": + parts = parts[:-1] + doc_path = doc_path.with_name("index.md") + full_doc_path = full_doc_path.with_name("index.md") + elif parts[-1] == "__main__": + continue + + nav[parts] = doc_path.as_posix() + + with mkdocs_gen_files.open(full_doc_path, "w") as fd: + ident = ".".join(parts) + fd.write(f"::: {ident}") + + mkdocs_gen_files.set_edit_path(full_doc_path, path.relative_to(root)) + +with mkdocs_gen_files.open("reference/SUMMARY.md", "w") as nav_file: + nav_file.writelines(nav.build_literate_nav()) diff --git a/src/typelib/binding.py b/src/typelib/binding.py index 51d34a9..7da07bd 100644 --- a/src/typelib/binding.py +++ b/src/typelib/binding.py @@ -1,4 +1,17 @@ -"""Utilities for automatic unmarshalling of inputs for a callable object's signature.""" +"""Utilities for automatic unmarshalling of inputs for a callable object's signature. + +Examples: Typical Usage + >>> from typelib import binding + >>> + >>> def foo(val: int) -> int: + ... return val * 2 + ... + >>> bound = binding.bind(foo) + >>> bound("2") + 4 + >>> bound.call("3") + '33' +""" from __future__ import annotations @@ -22,14 +35,18 @@ def bind(obj: tp.Callable[P, R]) -> BoundRoutine[P, R]: """Create a type-enforced, bound routine for a callable object. - Notes: - In contrast to :py:func:`~typelib.binding.wrap`, this function creates a new, - type-enforced :py:class:`~typelib.binding.BoundRoutine` instance. Rather than - masquerading as the given :py:param:`obj`, we encapsulate it in the routine + Note: + In contrast to [`typelib.binding.wrap`][], this function creates a new, + type-enforced [`BoundRoutine`][typelib.binding.BoundRoutine] instance. Rather than + masquerading as the given `obj`, we encapsulate it in the routine instance, which is more obvious and provides developers with the ability to side-step type enforcement when it is deemed unnecessary, which should be most of the time if your code is strongly typed and statically analyzed. + Tip: TL;DR + This function returns an object that walks like your duck and quacks like your duck, + but doesn't look like your duck. + Args: obj: The callable object to bind. """ @@ -44,17 +61,20 @@ def bind(obj: tp.Callable[P, R]) -> BoundRoutine[P, R]: def wrap(obj: tp.Callable[P, R]) -> tp.Callable[..., R]: """Wrap a callable object for runtime type coercion of inputs. - Notes: + Note: If a class is given, we will attempt to wrap the init method. - Warnings: + Warning: This is a useful feature. It is also very *surprising*. By wrapping a callable in this decorator, we end up with *implicit* behavior that's not obvious to the caller or a fellow developer. - You're encouraged to prefer :py:func:`~typelib.binding.bind` for similar + You're encouraged to prefer [`typelib.binding.bind`][] for similar functionality, less the implicit nature, especially when a class is given. + Tip: TL;DR + This function returns an object walks, quacks, and tries to look like your duck. + Args: obj: The callable object to wrap. Maybe be a function, a callable class instance, or a class. @@ -77,10 +97,17 @@ def binding_wrapper(*args: tp.Any, __binding=binding, **kwargs: tp.Any) -> R: @classes.slotted(dict=False, weakref=True) @dataclasses.dataclass class BoundRoutine(tp.Generic[P, R]): + """A type-enforced, bound routine for a callable object.""" + call: tp.Callable[P, R] + """The callable object.""" binding: AbstractBinding[P] + """The parameter->type binding.""" def __call__(self, *args: tp.Any, **kwargs: tp.Any) -> R: + """Binding an input to the parameters of `call`, + + then call the callable and return the result.""" bargs, bkwargs = self.binding(args=args, kwargs=kwargs) return self.call(*bargs, **bkwargs) @@ -140,21 +167,22 @@ def _get_binding(obj: tp.Callable) -> AbstractBinding: class AbstractBinding(abc.ABC, tp.Generic[P]): """The abstract base class for all type-enforced bindings. - Notes: + Note: "Bindings" are callables which leverage the type annotations in a signature to unmarshal inputs. We differentiate each subclass based upon the possible combinations of parameter kinds: - - Positional-only arguments - - Keyword-only arguments - - Positional-or-Keyword arguments - - Variable-positional arguments (`*args`) - - Variable-keyword arguments (`**kwargs`) - - This allows us to micro-optimize the call for each subclasses to exactly what is - necessary for the that combination, which can lead to a significant speedup at - runtime. + + - Positional-only arguments + - Keyword-only arguments + - Positional-or-Keyword arguments + - Variable-positional arguments (`*args`) + - Variable-keyword arguments (`**kwargs`) + + This allows us to micro-optimize the call for each subclass to exactly what is + necessary for the that combination, which can lead to a significant speedup in + hot loops. """ __slots__ = ("binding", "signature", "varkwd", "varpos", "startpos") @@ -192,7 +220,7 @@ def __repr__(self): def __call__( self, args: tuple[tp.Any], kwargs: dict[str, tp.Any] ) -> tuple[P.args, P.kwargs]: - """Inspect the given :py:param:`args` and :py:param:`kwargs` and unmarshal them. + """Inspect the given `args` and `kwargs` and unmarshal them. Args: args: The positional arguments. diff --git a/src/typelib/codec.py b/src/typelib/codec.py index bd6699f..2a0ee2f 100644 --- a/src/typelib/codec.py +++ b/src/typelib/codec.py @@ -1,14 +1,27 @@ -"""Interfaces for managing type-enforced wire protocols (codecs).""" +"""Interfaces for managing type-enforced wire protocols (codecs). + +Tip: + It shouldn't be necessary to create your own [`Codec`][] instances, you can instead + rely upon the higher-level API provided by [`interchange.protocol`][typelib.interchange.protocol]. + + Use this module for type annotations, if you need. + +See Also: + - [`interchange.protocol`][typelib.interchange.protocol] +""" from __future__ import annotations import abc +import dataclasses import typing as t from typelib import marshal, serdes, unmarshal __all__ = ("AbstractCodec", "Codec") +from typelib.py import classes + T = t.TypeVar("T") @@ -16,10 +29,10 @@ class AbstractCodec(abc.ABC, t.Generic[T]): """The abstract interface for defining a wire protocol (codec). Developers may define custom codecs with this interface which are compatible with - :py:func:`typelib.interchange.protocol`. + [`typelib.interchange.protocol`][]. See Also: - * :py:func:`typelib.interchange.protocol` + * [`typelib.interchange.protocol`][] """ def encode(self, value: T) -> bytes: ... @@ -27,6 +40,8 @@ def encode(self, value: T) -> bytes: ... def decode(self, value: bytes) -> T: ... +@classes.slotted(dict=False, weakref=True) +@dataclasses.dataclass(frozen=True) class Codec(AbstractCodec[T], t.Generic[T]): """A standard wire protocol (codec). @@ -35,29 +50,24 @@ class Codec(AbstractCodec[T], t.Generic[T]): to/from your in-memory data models. See Also: - * :py:func:`typelib.interchange.protocol` + * :[`typelib.interchange.protocol`][] """ - __slots__ = ("marshaller", "unmarshaller", "encoder", "decoder") - - def __init__( - self, - *, - marshaller: marshal.AbstractMarshaller[T], - unmarshaller: unmarshal.AbstractUnmarshaller[T], - encoder: EncoderT, - decoder: DecoderT, - ): - self.marshaller = marshaller - self.unmarshaller = unmarshaller - self.encoder = encoder - self.decoder = decoder + marshaller: marshal.AbstractMarshaller[T] + """The marshaller used to convert an instance of `T` to a serializable object.""" + unmarshaller: unmarshal.AbstractUnmarshaller[T] + """The unmarshaller used to convert a deserialized object into an instance of `T`.""" + encoder: EncoderT + """The encoder used to serialize a marshalled `T` into bytes.""" + decoder: DecoderT + """The decoder used to deserialize a bytes-like object into a Python data structure for marshalling into `T`.""" def encode(self, value: T) -> bytes: """Encode an instance of `T` to bytes. - We will first marshal the given instance using :py:attr:`marshaller`, then - encode the marshalled data into bytes using :py:attr:`encoder`. + We will first marshal the given instance using the + [`marshaller`][typelib.codec.Codec.marshaller], then encode the marshalled data + into bytes using the [`encoder`][typelib.codec.Codec.encoder]. Args: value: The instance to encode. @@ -69,8 +79,9 @@ def encode(self, value: T) -> bytes: def decode(self, value: bytes) -> T: """Decode an instance of `T` from bytes. - We will first decode the data from bytes using :py:attr:`decoder`, then - unmarshal the data into an instance of `T` using :py:attr:`unmarshaller`. + We will first decode the data from bytes using the + [`decoder`][typelib.codec.Codec.decoder], then unmarshal the data into an + instance of `T` using [`unmarshaller`][typelib.codec.Codec.unmarshaller]. Args: value: The bytes to decode. diff --git a/src/typelib/constants.py b/src/typelib/constants.py index 98a2f4a..ec0b3bb 100644 --- a/src/typelib/constants.py +++ b/src/typelib/constants.py @@ -1,9 +1,11 @@ """Constants used throughout the library.""" +import typing as t + class empty: """A singleton for signalling no input.""" -DEFAULT_ENCODING = "utf-8" -PKG_NAME = __name__.split(".", maxsplit=1)[0] +DEFAULT_ENCODING: t.Final[str] = "utf-8" +PKG_NAME: t.Final[str] = __name__.split(".", maxsplit=1)[0] diff --git a/src/typelib/graph.py b/src/typelib/graph.py index 1207b7a..4db1234 100644 --- a/src/typelib/graph.py +++ b/src/typelib/graph.py @@ -1,4 +1,19 @@ -"""Utilities for working with types as graphs.""" +"""Utilities for working with types as graphs. + +Examples: Typical Usage + >>> import dataclasses + >>> from typelib import graph + >>> graph.static_order(dict[str, str]) + [TypeNode(type=, var=None, cyclic=False), TypeNode(type=dict[str, str], var=None, cyclic=False)] + >>> + >>> @dataclasses.dataclass + ... class Class: + ... attr: str + ... + >>> graph.static_order(Class) + [TypeNode(type=, var='attr', cyclic=False), TypeNode(type=, var=None, cyclic=False)] + +""" from __future__ import annotations @@ -23,7 +38,7 @@ def static_order( Args: t: The type to extract an ordered stack from. - Notes: + Note: The order of types is guaranteed to rank from edges to root. If there are multiple edges, the order of those edges is not guaranteed. @@ -31,7 +46,7 @@ def static_order( multiple times at runtime, which would be wasted effort, as types don't change at runtime. - To avoid memoization, you can make use of :py:func:`itertypes`. + To avoid memoization, you can make use of [`itertypes`][typelib.graph.itertypes]. """ # We want to leverage the cache if possible, hence the recursive call. # Shouldn't actually recurse more than once or twice. @@ -54,14 +69,15 @@ def itertypes( t: The "root" type. Yields: - :py:class:`TypeNode` + [`TypeNode`][typelib.graph.TypeNode] - Notes: + Note: We will build a graph of types with the given type `t` as the root node, then iterate from the outermost leaves back to the root using BFS. - This is computationally expensive, so you are encouraged to use :py:func:`static_order` - instead of :py:func:`itertypes`. + This is computationally expensive, so you are encouraged to use + [`static_order`][typelib.graph.static_order] instead of + [`itertypes`][typelib.graph.itertypes]. """ if inspection.istypealiastype(t): t = t.__value__ @@ -80,13 +96,13 @@ def get_type_graph(t: type) -> graphlib.TopologicalSorter[TypeNode]: t: A type annotation. Returns: - :py:class:`graphlib.TopologicalSorter` + [`graphlib.TopologicalSorter`][] - Notes: + Note: A key aspect of building a directed graph of a given type is pre-emptive detection and termination of cycles in the graph. If we detect a cycle, we - will wrap the type in a :py:class:`typing.ForwardRef` and mark the - :py:class:`TypeNode` instance as `cyclic=True`. + will wrap the type in a [`typing.ForwardRef`][] and mark the + [`TypeNode`][typelib.graph.TypeNode] instance as `cyclic=True`. Consumers of the graph can "delay" the resolution of a forward reference until the graph's `static_order()` has been exhausted, at which point they have @@ -151,9 +167,14 @@ def get_type_graph(t: type) -> graphlib.TopologicalSorter[TypeNode]: @classes.slotted(dict=False, weakref=True) @dataclasses.dataclass(unsafe_hash=True) class TypeNode: + """A "node" in a type graph.""" + type: typing.Any + """The type annotation for this node.""" var: str | None = None + """The variable or parameter name associated to the type annotation for this node.""" cyclic: bool = dataclasses.field(default=False, hash=False, compare=False) + """Whether this type annotation is cyclic.""" def _level(t: typing.Any) -> typing.Iterable[tuple[str | None, type]]: diff --git a/src/typelib/interchange.py b/src/typelib/interchange.py index f404633..9c40584 100644 --- a/src/typelib/interchange.py +++ b/src/typelib/interchange.py @@ -1,4 +1,21 @@ -"""Interface for marshalling, unmarshalling, encoding, and decoding data to and from a bound type.""" +"""Interface for marshalling, unmarshalling, encoding, and decoding data to and from a bound type. + +Examples: Typical Usage + >>> import dataclasses + >>> from typelib import interchange + >>> + >>> @dataclasses.dataclass + ... class Class: + ... attr: str + ... + >>> protocol = interchange.protocol(Class) + >>> protocol.unmarshal({"attr": "value"}) + Class(attr="value") + >>> protocol.codec.decode(b'{"attr": "value"}') + Class(attr="value") + >>> protocol.codec.encode(Class(attr="value")) + b'{"attr":"value"}' +""" from __future__ import annotations @@ -23,29 +40,29 @@ def protocol( encoder: mcodec.EncoderT = compat.json.dumps, decoder: mcodec.DecoderT = compat.json.loads, ) -> InterchangeProtocol[T]: - """Factory function for creating an :py:class:`InterchangeProtocol` instance. + """Factory function for creating an [`InterchangeProtocol`][typelib.interchange.InterchangeProtocol] instance. - Notes: - In the simplest case, all that needs be provided is :py:param:`t`. We will + Note: + In the simplest case, all that needs be provided is `t`. We will generate a marshaller, unmarshaller and codec. In most cases, you probably don't need to override the default marshaller and unmarshaller behavior. - If no :py:param:`codec` is passed, we create a :py:class:`typelib.codec.Codec` - instance with :py:param:`marshaller`, :py:param:`unmarshaller`, :py:param:`encoder` - and :py:param:`decoder`. This codec instance combines your marshalling protocol - and your wire protocol, allowing you to pass instances of :py:param:`t` directly - to :py:meth:`~typelib.codec.Codec.encode` and recieve instances of :py:param:`t` - directly from :py:meth:`~typelib.codec.Codec.decode`. + If no `codec` is passed, we create a [`Codec`][typelib.codec.Codec] + instance with `marshaller`, `unmarshaller`, `encoder` + and `decoder`. This codec instance combines your marshalling protocol + and your wire protocol, allowing you to pass instances of `t` directly + to [`Codec.encode`][typelib.codec.Codec.encode] and receive instances of `t` + directly from [`Codec.decode`][typelib.codec.Codec.decode]. - The :py:param:`encoder` and :py:param:`decoder` default to JSON, using either - stdlib :py:mod:`json` or :py:mod:`orjson` if available. + The `encoder` and `decoder` default to JSON, using either + stdlib [`json`][] or [`orjson`](https://github.com/ijl/orjson) if available. You can customize your wire protocol in two ways: - 1. Pass in a custom :py:class:`typelib.codec.AbstractCodec` instance. + 1. Pass in a custom [`AbstractCodec`][typelib.codec.AbstractCodec] instance. * This will override the behavior described above. Useful when you have your own optimized path for your wire protocol and don't desire our marshalling capabilities. - 2. Pass in custom :py:param:`encoder` and :py:param:`decoder` values. + 2. Pass in custom `encoder` and `decoder` values. * This will follow the behavior described above. Useful when you use a wire protocol other than JSON. @@ -59,7 +76,7 @@ def protocol( See Also: - * :py:mod:`typelib.codec` + * [`typelib.codec`][] """ marshal = marshaller or mmarshal.marshaller(typ=t) unmarshal = unmarshaller or munmarshal.unmarshaller(typ=t) diff --git a/src/typelib/marshal/__init__.py b/src/typelib/marshal/__init__.py index f4cd396..944dc11 100644 --- a/src/typelib/marshal/__init__.py +++ b/src/typelib/marshal/__init__.py @@ -1,2 +1,49 @@ +"""Support for marshalling Python data structures into primitive equivalents. + +Notes: + "Marshalling" your data structure prepares it to be serialized into binary and sent + over the wire, but *does not* serialize it. We keep these stages isolated to ensure + maximum flexibility and simplicity. + + We ensure that your marshalled data is compatible with Python's built-in + [`json`][] module. This provides maximum compatibility with most serialization + protocols by limiting the output to simple Python builtin types: + + - [`bool`][] + - [`int`][] + - [`float`][] + - [`str`][] + - [`None`][] + - [`list`][] + - [`dict`][] + +Tip: + You are safe to use this package directly, but we encourage you to work with the + higher-level API provided by the [`interchange`][typelib.interchange] module. + +Examples: Typical Usage + >>> import dataclasses + >>> import decimal + >>> from typelib import marshal + >>> + >>> @dataclasses.dataclass(slots=True, weakref_slot=True, kw_only=True) + ... class Struct: + ... key: str + ... number: decimal.Decimal + ... + >>> + >>> data = Struct(key="some-key", number=decimal.Decimal("1.0")) + >>> marshal.marshal(data) + {'key': 'some-key', 'number': '1.0'} + >>> marshaller = marshal.marshaller(Struct) + >>> marshaller(data) + {'key': 'some-key', 'number': '1.0'} + +See Also: + * [`marshal`][typelib.marshal.marshal] + * [`marshaller`][typelib.marshal.marshaller] + * [`interchange.protocol`][typelib.interchange.protocol] +""" + from typelib.marshal.api import * from typelib.marshal.routines import * diff --git a/src/typelib/marshal/api.py b/src/typelib/marshal/api.py index 5f6dde1..0524f4c 100644 --- a/src/typelib/marshal/api.py +++ b/src/typelib/marshal/api.py @@ -20,12 +20,13 @@ def marshal( value: tp.Any, *, t: type[T] | refs.ForwardRef | str | None = None ) -> serdes.MarshalledValueT: - """Marshal :py:param:`value` from :py:param:`typ` into :py:class:~typelib.serdes.MarshalledValueT`. + """Marshal `value` from `typ` into [`MarshalledValueT`][typelib.serdes.MarshalledValueT]. Args: - value: The value to reduce to a simple, encodable type. - t: The type to use for building the marshaller (optional). - If not provided, we'll default to the type of the input value. + value: The value to reduce to a simple, encode-able type. + t: + The type to use for building the marshaller (optional). + If not provided, we'll default to the type of the input value. """ typ = value.__class__ if t is None else t routine: routines.AbstractMarshaller[T] = marshaller(typ) @@ -40,8 +41,8 @@ def marshaller( """Get a marshaller routine for a given type. Args: - typ: The type annotation to generate an marshaller for. - May be a type, type alias, :py:class:`typing.ForwardRef`, or string reference. + typ: The type annotation to generate a marshaller for. + May be a type, type alias, [`typing.ForwardRef`][], or string reference. """ nodes = graph.static_order(typ) context: dict[type | graph.TypeNode, routines.AbstractMarshaller] = ( diff --git a/src/typelib/marshal/routines.py b/src/typelib/marshal/routines.py index 8152b9c..4d20d0c 100644 --- a/src/typelib/marshal/routines.py +++ b/src/typelib/marshal/routines.py @@ -56,8 +56,8 @@ class AbstractMarshaller(abc.ABC, tp.Generic[T]): Attributes: t: The root type of this marshaller. - origin: If :py:attr:`t` is a generic, this will be an actionable runtime type - related to `t`, otherwise it is the same as :py:attr:`t`. + origin: If `t` is a generic, this will be an actionable runtime type + related to `t`, otherwise it is the same as `t`. context: The complete type context for this unmarshaller. var: If this unmarshaller is used in a nested context, this will reference the field/parameter/index at which this unmarshaller should be used. @@ -156,7 +156,7 @@ def __call__(self, val: T) -> str: class PatternMarshaller(AbstractMarshaller[PatternT]): - """A marshaller that converts a :py:class:`re.Pattern` to a string.""" + """A marshaller that converts a [`re.Pattern`][] to a string.""" def __call__(self, val: PatternT) -> str: """Marshal a compiled regex pattern into a string. @@ -176,7 +176,7 @@ class ToISOTimeMarshaller(AbstractMarshaller[DateOrTimeT], tp.Generic[DateOrTime """A marshaller that converts any date/time object to a ISO time string. See Also: - - :py:func:`typelib.serdes.isoformat` + - [`typelib.serdes.isoformat`] """ def __call__(self, val: DateOrTimeT) -> str: @@ -205,7 +205,7 @@ def __call__(self, val: DateOrTimeT) -> str: class LiteralMarshaller(AbstractMarshaller[LiteralT], tp.Generic[LiteralT]): - """A marshaller that enforces the given value be one of the values in the defined :py:class:`typing.Literal`""" + """A marshaller that enforces the given value be one of the values in the defined [`typing.Literal`][]""" __slots__ = ("values",) @@ -227,7 +227,7 @@ def __call__(self, val: LiteralT) -> serdes.MarshalledValueT: val: The value to enforce. Raises: - ValueError: If :py:param:`val` is not a member of the bound `Literal` type. + ValueError: If `val` is not a member of the bound `Literal` type. """ if val in self.values: return val # type: ignore[return-value] @@ -242,7 +242,7 @@ class UnionMarshaller(AbstractMarshaller[UnionT], tp.Generic[UnionT]): """A marshaller for dumping a given value via one of the types in the defined bound union. See Also: - - :py:class:`~typelib.unmarshal.routines.UnionUnmarshaller` + - [`UnionUnmarshaller`][typelib.unmarshal.routines.UnionUnmarshaller] """ __slots__ = ("stack", "ordered_routines") @@ -280,10 +280,10 @@ def __call__(self, val: UnionT) -> serdes.MarshalledValueT: class MappingMarshaller(AbstractMarshaller[MappingT], tp.Generic[MappingT]): - """A marshaller for dumping any mapping into a simple :py:class:`builtins.dict`.""" + """A marshaller for dumping any mapping into a simple [`dict`][].""" def __call__(self, val: MappingT) -> MarshalledMappingT: - """Marshal a mapping into a simple :py:class:`builtins.dict`. + """Marshal a mapping into a simple [`dict`][]. Args: val: The mapping object to marshal. @@ -295,10 +295,10 @@ def __call__(self, val: MappingT) -> MarshalledMappingT: class IterableMarshaller(AbstractMarshaller[IterableT], tp.Generic[IterableT]): - """A marshaller for dumping any iterable into a simple :py:class:`builtins.list`.""" + """A marshaller for dumping any iterable into a simple [`list`][].""" def __call__(self, val: IterableT) -> MarshalledIterableT: - """Marshal an iterable into a simple :py:class:`builtins.list`. + """Marshal an iterable into a simple [`list`][]. Args: val: The iterable to marshal. @@ -307,12 +307,12 @@ def __call__(self, val: IterableT) -> MarshalledIterableT: class SubscriptedMappingMarshaller(AbstractMarshaller[MappingT], tp.Generic[MappingT]): - """A marshaller for dumping a subscripted mapping into a simple :py:class:`builtins.dict`. + """A marshaller for dumping a subscripted mapping into a simple [`dict`][]. Keys are marshalled according to the defined key-type, values according to the defined value-type. See Also: - - :py:class:`~typelib.unmarshal.routines.SubscriptedMappingUnmarshaller` + - [`SubscriptedMappingUnmarshaller`][typelib.unmarshal.routines.SubscriptedMappingUnmarshaller] """ __slots__ = ( @@ -342,12 +342,12 @@ def __call__(self, val: MappingT) -> MarshalledMappingT: class SubscriptedIterableMarshaller( AbstractMarshaller[IterableT], tp.Generic[IterableT] ): - """A marshaller for dumping a subscripted iterable into a simple :py:class:`builtins.list`. + """A marshaller for dumping a subscripted iterable into a simple [`list`][]. Values are marshalled according to the defined value-type. See Also: - - :py:class:`~typelib.unmarshal.routines.SubscriptedIterableUnmarshaller` + - [`SubscriptedIterableUnmarshaller`][typelib.unmarshal.routines.SubscriptedIterableUnmarshaller] """ __slots__ = ("values",) @@ -368,7 +368,7 @@ def __init__( self.values = context[value_t] def __call__(self, val: IterableT) -> MarshalledIterableT: - """Marshal an iterable into a simple :py:class:`builtins.list`. + """Marshal an iterable into a simple [`list`][]. Args: val: The iterable to marshal. @@ -379,12 +379,12 @@ def __call__(self, val: IterableT) -> MarshalledIterableT: class FixedTupleMarshaller(AbstractMarshaller[compat.TupleT]): - """A marshaller for dumping a "fixed" tuple to a simple :py:class:`builtins.list`. + """A marshaller for dumping a "fixed" tuple to a simple [`list`][]. Values are marshalled according to the value-type in the order they are defined. See Also: - - :py:class:`~typelib.unmarshal.routines.FixedTupleUnmarshaller` + - [`FixedTupleUnmarshaller`][typelib.unmarshal.routines.FixedTupleUnmarshaller] """ __slots__ = ("ordered_routines", "stack") @@ -404,7 +404,7 @@ def __init__( self.ordered_routines = [self.context[vt] for vt in self.stack] def __call__(self, val: compat.TupleT) -> MarshalledIterableT: - """Marshal a tuple into a simple :py:class:`builtins.list`. + """Marshal a tuple into a simple [`list`][]. Args: val: The tuple to marshal. @@ -419,10 +419,10 @@ def __call__(self, val: compat.TupleT) -> MarshalledIterableT: class StructuredTypeMarshaller(AbstractMarshaller[_ST]): - """A marshaller for dumping a structured (user-defined) type to a simple :py:class:`builtins.dict`. + """A marshaller for dumping a structured (user-defined) type to a simple [`dict`][]. See Also: - - :py:class:`~typelib.unmarshal.routines.StructuredTypeUnmarshaller` + - [`StructuredTypeUnmarshaller`][typelib.unmarshal.routines.StructuredTypeUnmarshaller] """ __slots__ = ("fields_by_var",) @@ -439,7 +439,7 @@ def __init__(self, t: type[_ST], context: ContextT, *, var: str | None = None): self.fields_by_var = {m.var: m for m in self.context.values() if m.var} def __call__(self, val: _ST) -> MarshalledMappingT: - """Marshal a structured type into a simple :py:class:`builtins.dict`. + """Marshal a structured type into a simple [`dict`][]. Args: val: The structured type to marshal. diff --git a/src/typelib/py/classes.py b/src/typelib/py/classes.py index ec215cd..b24c51c 100644 --- a/src/typelib/py/classes.py +++ b/src/typelib/py/classes.py @@ -1,4 +1,22 @@ -"""Vendored class decorators for dataclasses.""" +"""Vendored class decorators for dataclasses. + +Notes: + This module is unnecessary for Python versions >= 3.10. + +Info: Typical Usage + ```pycon + >>> import dataclasses + >>> from typelib.py import classes + >>> + >>> @classes.slotted + >>> @dataclasses.dataclass + >>> class Slotted: + ... attr: str + ... + >>> Slotted.__slots__ + ('attr',) + ``` +""" from __future__ import annotations @@ -30,9 +48,17 @@ def slotted( # noqa: C901 ) -> Callable[[_ClsT], _ClsT] | _ClsT: """Decorator to create a "slotted" version of the provided class. - Returns new class object as it's not possible to add __slots__ after class creation. + Args: + _cls: The class to decorate. + dict: Whether to add a slot for `__dict__`. + weakref: Whether to add a slot for `__weakref__`. - Source: https://github.com/starhel/dataslots/blob/master/src/dataslots/__init__.py + Warning: + This function returns new class object as it's not possible to add `__slots__` + after class creation. + + See Also: + - [dataslots](https://github.com/starhel/dataslots/blob/master/src/dataslots/__init__.py) """ def _slots_setstate(self, state): diff --git a/src/typelib/py/compat.py b/src/typelib/py/compat.py index 65a6bde..d9a2c30 100644 --- a/src/typelib/py/compat.py +++ b/src/typelib/py/compat.py @@ -1,5 +1,3 @@ -"""Compatibility layer for typing and Python features.""" - # flake8: noqa from __future__ import annotations diff --git a/src/typelib/py/contrib.py b/src/typelib/py/contrib.py index 0df086e..aa12b20 100644 --- a/src/typelib/py/contrib.py +++ b/src/typelib/py/contrib.py @@ -1,5 +1,3 @@ -"""Compatibility layer for third-party libraries.""" - from __future__ import annotations import typing diff --git a/src/typelib/py/frames.py b/src/typelib/py/frames.py index cd86aa5..1133997 100644 --- a/src/typelib/py/frames.py +++ b/src/typelib/py/frames.py @@ -1,4 +1,15 @@ -"""Utilities for working with stack traces and frames.""" +"""Utilities for working with stack traces and frames. + +Examples: Typical Usage + >>> import inspect + >>> from typelib.py import frames + >>> var = 1 + >>> frames.extract("var") + 1 + >>> current_frame = inspect.currentframe() + >>> frames.getcaller() == current_frame + True +""" from __future__ import annotations @@ -20,7 +31,7 @@ def extract(name: str, *, frame: types.FrameType = None) -> Any | None: Args: name: The name of the object to extract from the stacktrace. - frame: The :py:class:`types.FrameType` instance to start from (optional). + frame: The [`types.FrameType`][] instance to start from (optional). """ frame = frame or inspect.currentframe() seen: set[types.FrameType] = set() @@ -42,7 +53,7 @@ def getcaller(frame: types.FrameType = None) -> types.FrameType: If `frame` is not provided, this function will use the current frame. Args: - frame: The :py:class:`types.FrameType` instance to start from (optional). + frame: The [`types.FrameType`][] instance to start from (optional). """ frame = frame or inspect.currentframe() diff --git a/src/typelib/py/future.py b/src/typelib/py/future.py index 1856dd5..e52910c 100644 --- a/src/typelib/py/future.py +++ b/src/typelib/py/future.py @@ -1,4 +1,15 @@ -"""Utilities for maintaining runtime compatibility with emerging type annotation operations.""" +"""Utilities for maintaining runtime compatibility with emerging type annotation operations. + +Notes: + This module's functionality is unnecessary for Python versions >= 3.10 + +Examples: Typical Usage + >>> from typelib.py import future + >>> future.transform_annotation("str | int") + 'typing.Union[str, int]' + >>> future.transform_annotation("dict[str, int]") + 'typing.Dict[str, int]' +""" from __future__ import annotations @@ -13,16 +24,16 @@ @functools.cache def transform(annotation: str, *, union: str = "typing.Union") -> str: - """Transform a modern annotations into their :py:mod:`typing` equivalent: + """Transform a modern annotations into their [`typing`][] equivalent: - - :py:class:`types.UnionType` into a :py:class:`typing.Union` (``str | int`` -> ``typing.Union[str, int]``) - - builtin generics into typing generics (``dict[str, int]`` -> ``typing.Dict[str, int]``) + - [`types.UnionType`][] into a [`typing.Union`][] (`str | int` -> `typing.Union[str, int]`) + - builtin generics into typing generics (`dict[str, int]` -> `typing.Dict[str, int]`) Args: annotation: The annotation to transform, as a string. union: The name of the Union type to subscript (defaults `"typing.Union"`). - Notes: + Note: While this transformation requires your expression be valid Python syntax, it doesn't make sure the type annotation is valid. """ @@ -33,13 +44,13 @@ def transform(annotation: str, *, union: str = "typing.Union") -> str: class TransformAnnotation(ast.NodeTransformer): - """A :py:class:`ast.NodeTransformer` that transforms :py:class:`typing.Union`.""" + """A [`ast.NodeTransformer`][] that transforms [`typing.Union`][].""" def __init__(self, union: str = "typing.Union") -> None: self.union = union def visit_BinOp(self, node: ast.BinOp): - """Transform a :py:class:`ast.BinOp` to :py:class:`typing.Union`.""" + """Transform a [`ast.BinOp`][] to [`typing.Union`][].""" # Ignore anything but a bitwise OR `|` if not isinstance(node.op, ast.BitOr): return node @@ -63,7 +74,7 @@ def visit_BinOp(self, node: ast.BinOp): return union def visit_Name(self, node: ast.Name): - """Transform a builtin :py:class:`ast.Name` to the `typing` equivalent.""" + """Transform a builtin [`ast.Name`][] to the `typing` equivalent.""" # Re-write new-style builtin generics as old-style typing generics if node.id not in _GENERICS: return node @@ -73,7 +84,7 @@ def visit_Name(self, node: ast.Name): return new def visit_Subscript(self, node: ast.Subscript): - """Transform all subscripts within a :py:class:`ast.Subscript`.""" + """Transform all subscripts within a [`ast.Subscript`][].""" # Scan all subscripts to we transform nested new-style types. transformed = self.visit(node.slice) new = ast.Subscript( @@ -86,7 +97,7 @@ def visit_Subscript(self, node: ast.Subscript): return new def visit_Tuple(self, node: ast.Tuple): - """Transform all values within a :py:class:`ast.Tuple`.""" + """Transform all values within a [`ast.Tuple`][].""" # Scan all tuples to ensure we transform nested new-style types. transformed = [self.visit(n) for n in node.elts] new = ast.Tuple(elts=transformed, ctx=node.ctx) diff --git a/src/typelib/py/inspection.py b/src/typelib/py/inspection.py index d12de3d..de24ec6 100644 --- a/src/typelib/py/inspection.py +++ b/src/typelib/py/inspection.py @@ -1,4 +1,13 @@ -"""High-performance, Fine-grained runtime type inspections.""" +"""High-performance, Fine-grained runtime type inspections. + +Examples: Typical Usage + >>> from typelib.py import inspection + >>> inspection.ismappingtype(dict) + True + >>> inspection.isfixedtupletype(tuple[int, str]) + True + +""" from __future__ import annotations @@ -90,9 +99,10 @@ @compat.cache def origin(annotation: Any) -> Any: - """Get the highest-order 'origin'-type for subclasses of typing._SpecialForm. + """Get the highest-order 'origin'-type for a given type definition. - For the purposes of this library, if we can resolve to a builtin type, we will. + Tip: + For the purposes of this library, if we can resolve to a builtin type, we will. Examples: >>> from typelib.py import inspection @@ -156,16 +166,17 @@ def _check_generics(hint: Any): def get_args(annotation: Any) -> Tuple[Any, ...]: - """Get the args supplied to an annotation, normalizing :py:class:`typing.TypeVar`. + """Get the args supplied to an annotation, normalizing [`typing.TypeVar`][]. - Notes: + Note: TypeVar normalization follows this strategy: + -> If the TypeVar is bound - -> return the bound type - -> Else if the TypeVar has constraints - -> return a Union of the constraints + -----> return the bound type + -> Else If the TypeVar has constraints + -----> return a Union of the constraints -> Else - -> return Any + -----> return Any Examples: >>> from typelib.py import inspection @@ -193,8 +204,9 @@ def _normalize_typevars(*args: Any) -> Iterable: def normalize_typevar(tvar: TypeVar) -> type[Any]: """Reduce a TypeVar to a simple type. - Notes: + Note: TypeVar normalization follows this strategy: + -> If the TypeVar is bound -----> return the bound type -> Else If the TypeVar has constraints @@ -301,15 +313,16 @@ def signature(obj: Callable[..., Any] | type[Any]) -> inspect.Signature: def get_type_hints( obj: Union[type, Callable], exhaustive: bool = True ) -> dict[str, type[Any]]: - """Wrapper for :py:func:`typing.get_type_hints`. + """Wrapper for [`typing.get_type_hints`][]. - If :py:func:`typing.get_type_hints` raises `(NameError, TypeError)`, we will + If [`typing.get_type_hints`][] raises `([NameError][], [TypeError][])`, we will default to an empty dict. Args: obj: The object to inspect. - exhaustive: Whether to pull type hints from the signature of the object if - none can be found via :py:func:`typing.get_type_hints`. (defaults True) + exhaustive: + Whether to pull type hints from the signature of the object if + none can be found via [`typing.get_type_hints`][]. (defaults True) """ try: hints = typing.get_type_hints(obj) @@ -378,9 +391,9 @@ def simple_attributes(t: type) -> Tuple[str, ...]: def typed_dict_signature(obj: Callable) -> inspect.Signature: - """A little faker for getting the "signature" of a :py:class:`TypedDict`. + """A little faker for getting the "signature" of a [`typing.TypedDict`][]. - Notes: + Note: Technically, these are dicts at runtime, but we are enforcing a static shape, so we should be able to declare a matching signature for it. """ @@ -400,10 +413,10 @@ def typed_dict_signature(obj: Callable) -> inspect.Signature: ) -def tuple_signature(t: type[tuple]) -> inspect.Signature: - """A little faker for getting the "signature" of a :py:class:`tuple`. +def tuple_signature(t: type[compat.TupleT]) -> inspect.Signature: + """A little faker for getting the "signature" of a [`tuple`][]. - Notes: + Note: At runtime, tuples are just tuples, but we can make use of their type hints to define a predictable signature. """ @@ -426,6 +439,10 @@ def tuple_signature(t: type[tuple]) -> inspect.Signature: @compat.cache def safe_get_params(obj: type) -> Mapping[str, inspect.Parameter]: + """Try to extract the parameters of the given object. + + Return an empty mapping if we encounter an error. + """ params: Mapping[str, inspect.Parameter] try: if ismappingtype(obj) and not istypeddict(obj): @@ -442,20 +459,19 @@ def isbuiltintype( ) -> compat.TypeIs[type[BuiltIntypeT]]: """Check whether the provided object is a builtin-type. - Notes: + Note: Python stdlib and Python documentation have no "definitive list" of builtin-**types**, despite the fact that they are well-known. The closest we have is https://docs.python.org/3.7/library/functions.html, which clumps the builtin-types with builtin-functions. Despite clumping these types with functions in the documentation, these types eval as False when compared to - :py:class:`types.BuiltinFunctionType`, which is meant to be an alias for the + [`types.BuiltinFunctionType`][], which is meant to be an alias for the builtin-functions listed in the documentation. All this to say, here we are with a custom check to determine whether a type is a builtin. Examples: - >>> from typing import NewType, Mapping >>> isbuiltintype(str) True @@ -487,7 +503,6 @@ def isbuiltinsubtype(t: type) -> compat.TypeIs[type[BuiltIntypeT]]: """Check whether the provided type is a subclass of a builtin-type. Examples: - >>> from typing import NewType, Mapping >>> class SuperStr(str): ... ... @@ -524,7 +539,6 @@ def isbuiltininstance(o: Any) -> compat.TypeIs[BuiltIntypeT]: """Test whether an object is an instance of a builtin type. Examples: - >>> isbuiltininstance("") True """ @@ -538,13 +552,12 @@ def isstdlibinstance(o: Any) -> compat.TypeIs[STDLibtypeT]: @compat.cache def isoptionaltype(obj: type[_OT]) -> compat.TypeIs[type[Optional[_OT]]]: - """Test whether an annotation is :py:class`typing.Optional`, or can be treated as. + """Test whether an annotation is [`typing.Optional`][], or can be treated as. - :py:class:`typing.Optional` is an alias for `typing.Union[, None]`, so both are + [`typing.Optional`][] is an alias for `typing.Union[, None]`, so both are "optional". Examples: - >>> from typing import Optional, Union, Dict, Literal >>> isoptionaltype(Optional[str]) True @@ -575,10 +588,9 @@ def isuniontype(obj: type) -> compat.TypeIs[Union]: @compat.cache def isfinal(obj: type) -> bool: - """Test whether an annotation is :py:class:`typing.Final`. + """Test whether an annotation is [`typing.Final`][]. Examples: - >>> from typing import NewType >>> from typelib.py.compat import Final >>> isfinal(Final[str]) @@ -591,10 +603,9 @@ def isfinal(obj: type) -> bool: @compat.cache def isliteral(obj) -> bool: - """Test whether an annotation is :py:class:`typing.Literal`. + """Test whether an annotation is [`typing.Literal`][]. Examples: - >>> """ return origin(obj) is typing.Literal or ( @@ -609,7 +620,6 @@ def isdatetype( """Test whether this annotation is a a date/datetime object. Examples: - >>> import datetime >>> from typing import NewType >>> isdatetype(datetime.datetime) @@ -629,7 +639,6 @@ def isdatetimetype( """Test whether this annotation is a a date/datetime object. Examples: - >>> import datetime >>> from typing import NewType >>> isdatetype(datetime.datetime) @@ -647,7 +656,6 @@ def istimetype(obj: type) -> compat.TypeIs[type[datetime.time]]: """Test whether this annotation is a a date/datetime object. Examples: - >>> import datetime >>> from typing import NewType >>> istimetype(datetime.time) @@ -663,7 +671,6 @@ def istimedeltatype(obj: type) -> compat.TypeIs[type[datetime.timedelta]]: """Test whether this annotation is a a date/datetime object. Examples: - >>> import datetime >>> from typing import NewType >>> istimedeltatype(datetime.timedelta) @@ -679,7 +686,6 @@ def isdecimaltype(obj: type) -> compat.TypeIs[type[decimal.Decimal]]: """Test whether this annotation is a Decimal object. Examples: - >>> import decimal >>> from typing import NewType >>> isdecimaltype(decimal.Decimal) @@ -695,7 +701,6 @@ def isfractiontype(obj: type) -> compat.TypeIs[type[fractions.Fraction]]: """Test whether this annotation is a Decimal object. Examples: - >>> import fractions >>> from typing import NewType >>> isdecimaltype(fractions.Fraction) @@ -711,7 +716,6 @@ def isuuidtype(obj: type) -> compat.TypeIs[type[uuid.UUID]]: """Test whether this annotation is a a date/datetime object. Examples: - >>> import uuid >>> from typing import NewType >>> isuuidtype(uuid.UUID) @@ -731,7 +735,6 @@ def isiterabletype(obj: type) -> compat.TypeIs[type[Iterable]]: """Test whether the given type is iterable. Examples: - >>> from typing import Sequence, Collection >>> isiterabletype(Sequence[str]) True @@ -753,7 +756,6 @@ def isiteratortype(obj: type) -> compat.TypeIs[type[Iterator]]: """Check whether the given object is a subclass of an Iterator. Examples: - >>> def mygen(): yield 1 ... >>> isiteratortype(mygen().__class__) @@ -771,10 +773,9 @@ def isiteratortype(obj: type) -> compat.TypeIs[type[Iterator]]: @compat.cache def istupletype(obj: Callable[..., Any] | type[Any]) -> compat.TypeIs[type[tuple]]: - """Tests whether the given type is a subclass of :py:class:`tuple`. + """Tests whether the given type is a subclass of [`tuple`][]. Examples: - >>> from typing import NamedTuple, Tuple >>> class MyTup(NamedTuple): ... field: int @@ -792,12 +793,11 @@ def istupletype(obj: Callable[..., Any] | type[Any]) -> compat.TypeIs[type[tuple @compat.cache def iscollectiontype(obj: type) -> compat.TypeIs[type[Collection]]: - """Test whether this annotation is a subclass of :py:class:`typing.Collection`. + """Test whether this annotation is a subclass of [`typing.Collection`][]. Includes builtins. Examples: - >>> from typing import Collection, Mapping, NewType >>> iscollectiontype(Collection) True @@ -844,10 +844,9 @@ def issubscriptedcollectiontype( @compat.cache def ismappingtype(obj: type) -> compat.TypeIs[type[Mapping]]: - """Test whether this annotation is a subtype of :py:class:`typing.Mapping`. + """Test whether this annotation is a subtype of [`typing.Mapping`][]. Examples: - >>> from typing import Mapping, Dict, DefaultDict, NewType >>> ismappingtype(Mapping) True @@ -877,10 +876,9 @@ def ismappingtype(obj: type) -> compat.TypeIs[type[Mapping]]: @compat.cache def isenumtype(obj: type) -> compat.TypeIs[type[enum.Enum]]: - """Test whether this annotation is a subclass of :py:class:`enum.Enum` + """Test whether this annotation is a subclass of [`enum.Enum`][] Examples: - >>> import enum >>> >>> class FooNum(enum.Enum): ... @@ -896,7 +894,6 @@ def isclassvartype(obj: type) -> bool: """Test whether an annotation is a ClassVar annotation. Examples: - >>> from typing import ClassVar, NewType >>> isclassvartype(ClassVar[str]) True @@ -953,11 +950,10 @@ class _FrozenDataclass(typing.Protocol): def ishashable(obj: Any) -> compat.TypeIs[Hashable]: """Check whether an object is hashable. - An order of magnitude faster than :py:class:`isinstance` with - :py:class:`typing.Hashable` + An order of magnitude faster than [`isinstance`][] with + [`typing.Hashable`][] Examples: - >>> ishashable(str()) True >>> ishashable(frozenset()) @@ -970,10 +966,9 @@ def ishashable(obj: Any) -> compat.TypeIs[Hashable]: @compat.cache def istypeddict(obj: Any) -> bool: - """Check whether an object is a :py:class:`typing.TypedDict`. + """Check whether an object is a [`typing.TypedDict`][]. Examples: - >>> from typing import TypedDict >>> >>> class FooMap(TypedDict): @@ -991,10 +986,9 @@ def istypeddict(obj: Any) -> bool: @compat.cache def istypedtuple(obj: type) -> compat.TypeIs[type[NamedTuple]]: - """Check whether an object is a "typed" tuple (:py:class:`typing.NamedTuple`). + """Check whether an object is a "typed" tuple ([`typing.NamedTuple`][]). Examples: - >>> from typing import NamedTuple >>> >>> class FooTup(NamedTuple): @@ -1012,10 +1006,9 @@ def istypedtuple(obj: type) -> compat.TypeIs[type[NamedTuple]]: @compat.cache def isnamedtuple(obj: type) -> compat.TypeIs[type[NamedTuple]]: - """Check whether an object is a "named" tuple (:py:func:`collections.namedtuple`). + """Check whether an object is a "named" tuple ([`collections.namedtuple`][]). Examples: - >>> from collections import namedtuple >>> >>> FooTup = namedtuple("FooTup", ["bar"]) @@ -1027,10 +1020,9 @@ def isnamedtuple(obj: type) -> compat.TypeIs[type[NamedTuple]]: @compat.cache def isfixedtupletype(obj: type) -> compat.TypeIs[type[tuple]]: - """Check whether an object is a "fixed" tuple, e.g., tuple[int, int]. + """Check whether an object is a "fixed" tuple, e.g., `tuple[int, int]`. Examples: - >>> from typing import Tuple >>> >>> @@ -1047,12 +1039,12 @@ def isfixedtupletype(obj: type) -> compat.TypeIs[type[tuple]]: def isforwardref(obj: Any) -> compat.TypeIs[refs.ForwardRef]: - """Tests whether the given object is a :py:class:`typing.ForwardRef`.""" + """Tests whether the given object is a [`typing.ForwardRef`][].""" return obj.__class__ is refs.ForwardRef def isproperty(obj) -> compat.TypeIs[types.DynamicClassAttribute]: - """Test whether the given object is an instance of :py:class:`property` or :py:class:`functools.cached_property. + """Test whether the given object is an instance of [`property`] or [`functools.cached_property`][]. Examples: >>> import functools @@ -1076,10 +1068,9 @@ def isproperty(obj) -> compat.TypeIs[types.DynamicClassAttribute]: def isdescriptor(obj) -> compat.TypeIs[DescriptorT]: - """Test whether the given object is a :py:class:`types.GetSetDescriptortype` + """Test whether the given object is a [`types.GetSetDescriptortype`][] Examples: - >>> class StringDescriptor: ... __slots__ = ("value",) ... @@ -1137,7 +1128,6 @@ def issimpleattribute(v) -> bool: (e.g., not a function, class, or descriptor). Examples: - >>> class MyOperator: ... type = str ... @@ -1190,7 +1180,6 @@ def istexttype(t: type[Any]) -> compat.TypeIs[type[str | bytes | bytearray]]: """Test whether the given type is a subclass of text or bytes. Examples: - >>> class MyStr(str): ... ... >>> istexttype(MyStr) @@ -1204,7 +1193,6 @@ def isstringtype(t: type[Any]) -> compat.TypeIs[type[str | bytes | bytearray]]: """Test whether the given type is a subclass of text or bytes. Examples: - >>> class MyStr(str): ... ... >>> istexttype(MyStr) @@ -1218,7 +1206,6 @@ def isbytestype(t: type[Any]) -> compat.TypeIs[type[str | bytes | bytearray]]: """Test whether the given type is a subclass of text or bytes. Examples: - >>> class MyStr(str): ... ... >>> istexttype(MyStr) @@ -1229,7 +1216,7 @@ def isbytestype(t: type[Any]) -> compat.TypeIs[type[str | bytes | bytearray]]: @compat.cache def isnumbertype(t: type[Any]) -> compat.TypeIs[type[numbers.Number]]: - """Test whether `t` is a subclass of the :py:class:`numbers.Number` protocol. + """Test whether `t` is a subclass of the [`numbers.Number`][] protocol. Examples: >>> import decimal @@ -1246,7 +1233,7 @@ def isnumbertype(t: type[Any]) -> compat.TypeIs[type[numbers.Number]]: @compat.cache def isintegertype(t: type[Any]) -> compat.TypeIs[type[int]]: - """Test whether `t` is a subclass of the :py:class:`numbers.Number` protocol. + """Test whether `t` is a subclass of the [`numbers.Number`][] protocol. Examples: >>> import decimal @@ -1263,7 +1250,7 @@ def isintegertype(t: type[Any]) -> compat.TypeIs[type[int]]: @compat.cache def isfloattype(t: type[Any]) -> compat.TypeIs[type[float]]: - """Test whether `t` is a subclass of the :py:class:`numbers.Number` protocol. + """Test whether `t` is a subclass of the [`numbers.Number`][] protocol. Examples: >>> import decimal @@ -1413,7 +1400,7 @@ def isunresolvable(t: Any) -> bool: @compat.cache def isnonetype(t: Any) -> compat.TypeIs[None]: - """Detect if the given type is a :py:class:`NoneType`. + """Detect if the given type is a [`types.NoneType`][]. Examples: >>> isnonetype(None) @@ -1428,7 +1415,7 @@ def isnonetype(t: Any) -> compat.TypeIs[None]: @compat.cache def ispatterntype(t: Any) -> compat.TypeIs[re.Pattern]: - """Detect if the given type is a :py:class:`re.Pattern`. + """Detect if the given type is a [`re.Pattern`][]. Examples: >>> import re @@ -1442,7 +1429,7 @@ def ispatterntype(t: Any) -> compat.TypeIs[re.Pattern]: @compat.cache def ispathtype(t: Any) -> compat.TypeIs[pathlib.Path]: - """Detect if the given type is a :py:class:`pathlib.Path`. + """Detect if the given type is a [`pathlib.Path`][]. Examples: >>> import pathlib @@ -1456,7 +1443,7 @@ def ispathtype(t: Any) -> compat.TypeIs[pathlib.Path]: @compat.cache def istypealiastype(t: Any) -> compat.TypeIs[compat.TypeAliasType]: - """Detect if the given object is a :py:class:`typing.TypeAliasType`. + """Detect if the given object is a [`typing.TypeAliasType`][]. Examples: >>> type IntList = list[int] diff --git a/src/typelib/py/refs.py b/src/typelib/py/refs.py index f21dc71..130172e 100644 --- a/src/typelib/py/refs.py +++ b/src/typelib/py/refs.py @@ -1,4 +1,15 @@ -"""Utilities for working with :py:class:`typing.ForwardRef`.""" +"""Utilities for working with [`typing.ForwardRef`][]. + +This module allows the developer to create and evaluate [`typing.ForwardRef`][] instances +with additional logic to support forwards compatibility. + +Examples: Typical Usage + >>> from typelib.py import refs + >>> ref = refs.forwardref("str") + >>> cls = refs.evaluate(ref) + >>> cls is str + True +""" from __future__ import annotations @@ -21,7 +32,7 @@ def forwardref( module: typing.Any | None = None, is_class: bool = True, ) -> ForwardRef: - """Create a :py:class:`typing.ForwardRef` instance from a :py:param:`ref` string. + """Create a [`typing.ForwardRef`][] instance from a `ref` string. This wrapper function will attempt to determine the module name ahead of instantiation if not provided. This is important when resolving the reference to an actual type. @@ -64,10 +75,10 @@ def evaluate( localns: typing.Mapping[str, typing.Any] | None = None, recursive_guard: set | None = None, ) -> typing.Any: - """Evaluate the :py:class:`typing.ForwardRef` instance into a proper type. + """Evaluate the [`typing.ForwardRef`][] instance into a proper type. - Notes: - Most of the time you will not need to provide anything but :py:param:`ref`. + Note: + Most of the time you will not need to provide anything but `ref`. In Python 3.9, we will automatically transform "new-style" type hints into runtime-compatible type hints: @@ -75,7 +86,7 @@ def evaluate( - builtin generics (`dict[str, str]` -> `typing.Dict[str, str]`) Args: - ref: The :py:class:`typing.ForwardRef` instance to evaluate. + ref: The [`typing.ForwardRef`][] instance to evaluate. globalns: A mapping of global variable names to values (optional). localns: A mapping of local variable names to values (optional). recursive_guard: A set instance to prevent recursion during evaluation (optional). diff --git a/src/typelib/serdes.py b/src/typelib/serdes.py index ebd8274..d999b2d 100644 --- a/src/typelib/serdes.py +++ b/src/typelib/serdes.py @@ -1,4 +1,28 @@ -"""Utilities for type translation, serialization, and deserialization.""" +"""Utilities for type translation, serialization, and deserialization. + +Examples: Typical Usage + >>> from typelib import serdes + >>> + >>> serdes.load("1") + 1 + + >>> import datetime + >>> from typelib import serdes + >>> + >>> serdes.unixtime(datetime.datetime(2020, 1, 1)) + 1577854800.0 + >>> serdes.isoformat(datetime.timedelta(hours=1)) + 'PT1H' + + >>> import dataclasses + >>> @dataclasses.dataclass + ... class Class: + ... attr: str + ... + >>> instance = Class(attr="value") + >>> list(serdes.iteritems(instance)) + [('attr', 'value')] +""" from __future__ import annotations @@ -16,6 +40,18 @@ from typelib import constants from typelib.py import compat, inspection +__all__ = ( + "decode", + "isoformat", + "unixtime", + "dateparse", + "iteritems", + "itervalues", + "get_items_iter", + "strload", + "load", +) + @t.overload def decode( # type: ignore[overload-overlap] @@ -30,7 +66,7 @@ def decode(val: _T) -> _T: ... # type: ignore[overload-overlap] def decode(val: t.Any, *, encoding: str = constants.DEFAULT_ENCODING) -> t.Any: """Decode a bytes-like object into a str. - Notes: + Note: If a non-bytes-like object is passed, it will be returned unchanged. Args: @@ -48,11 +84,11 @@ def decode(val: t.Any, *, encoding: str = constants.DEFAULT_ENCODING) -> t.Any: def isoformat(dt: datetime.date | datetime.time | datetime.timedelta) -> str: """Format any date/time object into an ISO-8601 string. - Notes: + Note: While the standard library includes `isoformat()` methods for - :py:class:`datetime.date`, :py:class:`datetime.time`, & - :py:class:`datetime.datetime`, they do not include a method for serializing - :py:class:`datetime.timedelta`, even though durations are included in the + [`datetime.date`][], [`datetime.time`][], & + [`datetime.datetime`][], they do not include a method for serializing + [`datetime.timedelta`][], even though durations are included in the ISO 8601 specification. This function fills that gap. Examples: @@ -107,7 +143,7 @@ def isoformat(dt: datetime.date | datetime.time | datetime.timedelta) -> str: def unixtime(dt: datetime.date | datetime.time | datetime.timedelta) -> float: """Convert a date/time object to a unix timestamp. - Notes: + Note: Time is messy. Here is how we've decided to make this work: - `datetime.datetime` instances will preserve the current tzinfo (even if naive). @@ -215,7 +251,7 @@ def _normalize_number(*, numval: float, td: type[DateTimeT]) -> DateTimeT: def iteritems(val: t.Any) -> t.Iterable[tuple[t.Any, t.Any]]: """Iterate over (field, value) pairs for any object. - Notes: + Note: If the given item is detected to be an iterable of pairs (e.g., `[('a', 1), ('b', 2)]`), we will iterate directly over that. @@ -244,6 +280,11 @@ def _is_iterable_of_pairs(val: t.Any) -> bool: def itervalues(val: t.Any) -> t.Iterator[t.Any]: + """Iterate over the contained values for any object. + + Args: + val: The object to iterate over. + """ iterate = get_items_iter(val.__class__) return (v for k, v in iterate(val)) @@ -301,7 +342,7 @@ def _itervars(val: t.Any) -> t.Iterator[tuple[str, t.Any]]: def load(val: _T) -> PythonValueT | _T: - """Attempt to decode :py:param:`val` if it is a text-like object. + """Attempt to decode `val` if it is a text-like object. Args: val: The value to decode. @@ -327,6 +368,7 @@ def strload(val: str | bytes | bytearray | memoryview) -> PythonValueT: PythonPrimitiveT: t.TypeAlias = "bool | int | float | str | None" +"""Type alias for serializable, non-container Python types.""" PythonValueT: t.TypeAlias = ( "PythonPrimitiveT | " "dict[PythonPrimitiveT, PythonValueT] | " @@ -334,7 +376,9 @@ def strload(val: str | bytes | bytearray | memoryview) -> PythonValueT: "tuple[PythonValueT, ...] | " "set[PythonValueT]" ) +"""Type alias for any Python builtin type.""" MarshalledValueT: t.TypeAlias = "PythonPrimitiveT | dict[PythonPrimitiveT, MarshalledValueT] | list[MarshalledValueT]" +"""Type alias for a Python value which is ready for over-the-wire serialization.""" _itemscaller = operator.methodcaller("items") diff --git a/src/typelib/unmarshal/__init__.py b/src/typelib/unmarshal/__init__.py index beb9638..c3d6628 100644 --- a/src/typelib/unmarshal/__init__.py +++ b/src/typelib/unmarshal/__init__.py @@ -1,2 +1,37 @@ +"""Support for unmarshalling unstructured data into Python data structures. + +Notes: + "Unmarshalling" refers to the process of taking a "primitive" form of data, such + as a basic dictionary or JSON string, and coercing it into a higher-order structured + data type. + +Tip: + You are safe to use this package directly, but we encourage you to work with the + higher-level API provided by the [`interchange`][typelib.interchange] module. + +Examples: Typical Usage + >>> import dataclasses + >>> import decimal + >>> from typelib import unmarshal + >>> + >>> @dataclasses.dataclass(slots=True, weakref_slot=True, kw_only=True) + ... class Struct: + ... key: str + ... number: decimal.Decimal + ... + >>> + >>> data = {"key": "some-key", "number": "3.14"} + >>> unmarshal.unmarshal(Struct, data) + Struct(key='some-key', number=decimal.Decimal('3.14')) + >>> unmarshaller = unmarshal.unmarshaller(Struct) + >>> unmarshaller(data) + Struct(key='some-key', number=decimal.Decimal('3.14')) + +See Also: + * [`unmarshal`][typelib.unmarshal.unmarshal] + * [`unmarshaller`][typelib.unmarshal.unmarshaller] + * [`interchange.protocol`][typelib.interchange.protocol] +""" + from typelib.unmarshal.api import * from typelib.unmarshal.routines import * diff --git a/src/typelib/unmarshal/api.py b/src/typelib/unmarshal/api.py index 16a9d01..f116195 100644 --- a/src/typelib/unmarshal/api.py +++ b/src/typelib/unmarshal/api.py @@ -18,7 +18,7 @@ def unmarshal(typ: type[T] | refs.ForwardRef | str, value: tp.Any) -> T: - """Unmarshal :py:param:`value` into :py:param:`typ`. + """Unmarshal `value` into `typ`. Args: typ: The type annotation or reference to unmarshal into. @@ -37,7 +37,7 @@ def unmarshaller( Args: typ: The type annotation to generate an unmarshaller for. - May be a type, type alias, :py:class:`typing.ForwardRef`, or string reference. + May be a type, type alias, [`typing.ForwardRef`][], or string reference. """ nodes = graph.static_order(typ) context: dict[type | graph.TypeNode, routines.AbstractUnmarshaller] = ( diff --git a/src/typelib/unmarshal/routines.py b/src/typelib/unmarshal/routines.py index 835d625..30cdf09 100644 --- a/src/typelib/unmarshal/routines.py +++ b/src/typelib/unmarshal/routines.py @@ -61,8 +61,8 @@ class AbstractUnmarshaller(abc.ABC, tp.Generic[T]): Attributes: t: The root type of this unmarshaller. - origin: If :py:attr:`t` is a generic, this will be an actionable runtime type - related to `t`, otherwise it is the same as :py:attr:`t`. + origin: If `t` is a generic, this will be an actionable runtime type + related to `t`, otherwise it is the same as `t`. context: The complete type context for this unmarshaller. var: If this unmarshaller is used in a nested context, this will reference the field/parameter/index at which this unmarshaller should be used. @@ -109,11 +109,11 @@ def __call__(self, val: tp.Any) -> T: class NoneTypeUnmarshaller(AbstractUnmarshaller[None]): """Unmarshaller for null values. - Notes: + Note: We will attempt to decode any string/bytes input before evaluating for `None`. See Also: - - :py:func:`~typelib.serdes.decode` + - [`typelib.serdes.decode`][] """ def __call__(self, val: tp.Any) -> None: @@ -123,7 +123,7 @@ def __call__(self, val: tp.Any) -> None: val: The value to unmarshal. Raises: - ValueError: If :py:param:`val` is not `None` after decoding. + ValueError: If `val` is not `None` after decoding. """ decoded = serdes.decode(val) if decoded is not None: @@ -138,11 +138,11 @@ def __call__(self, val: tp.Any) -> None: class BytesUnmarshaller(AbstractUnmarshaller[BytesT], tp.Generic[BytesT]): """Unmarshaller that encodes an input to bytes. - Notes: + Note: We will format a member of the `datetime` module into ISO format before converting to bytes. See Also: - - :py:func:`~typelib.serdes.isoformat` + - [`typelib.serdes.isoformat`][] """ def __call__(self, val: tp.Any) -> BytesT: @@ -160,11 +160,11 @@ def __call__(self, val: tp.Any) -> BytesT: class StringUnmarshaller(AbstractUnmarshaller[StringT], tp.Generic[StringT]): """Unmarshaller that converts an input to a string. - Notes: + Note: We will format a member of the `datetime` module into ISO format. See Also: - - :py:func:`~typelib.serdes.isoformat` + - [`typelib.serdes.isoformat`][] """ def __call__(self, val: tp.Any) -> StringT: @@ -184,7 +184,7 @@ def __call__(self, val: tp.Any) -> StringT: class NumberUnmarshaller(AbstractUnmarshaller[NumberT], tp.Generic[NumberT]): """Unmarshaller that converts an input to a number. - Notes: + Note: Number unmarshalling follows a best-effort strategy. We may extend type resolution to support more advanced type unmarshalling strategies in the future. @@ -196,7 +196,7 @@ class NumberUnmarshaller(AbstractUnmarshaller[NumberT], tp.Generic[NumberT]): 5. Otherwise, call the number constructor with the input. See Also: - - :py:func:`~typelib.serdes.unixtime` + - [`typelib.serdes.unixtime`][] """ def __call__(self, val: tp.Any) -> NumberT: @@ -234,31 +234,29 @@ def __call__(self, val: tp.Any) -> NumberT: class DateUnmarshaller(AbstractUnmarshaller[DateT], tp.Generic[DateT]): - """Unmarshaller that converts an input to a :py:class`datetime.date` (or subclasses). + """Unmarshaller that converts an input to a [`datetime.date`][] (or subclasses). Notes: + This class tries to handle the 90% case: + + 1. If we are already a [`datetime.date`][] instance, return it. + 2. If we are a `float` or `int` instance, treat it as a unix timestamp, at UTC. + 3. Attempt to decode any bytes/string input into a real Python value. + 4. If we have a string value, parse it into either a [`datetime.date`][] + 5. If the parsed result is a [`datetime.time`][] instance, then return + the result of [`datetime.datetime.now`][], at UTC, as a [`datetime.date`][]. + + Tip: TL;DR There are many ways to represent a date object over-the-wire. Your most fool-proof method is to rely upon [ISO 8601][iso] or [RFC 3339][rfc]. - This class tries to handle the 90% case: - 1. If we are already a :py:class:`datetime.date` instance, return it. - 2. If we are a `float` or `int` instance, treat it as a unix timestamp, at UTC. - 3. Attempt to decode any bytes/string input into a real Python value. - 4. If we have a string value, parse it into either a :py:class:`datetime.date` - instance or a :py:class:`datetime.time` instance. - 5. If the parsed result is a :py:class:`datetime.time` instance, then return - the result of :py:meth:`datetime.datetime.now`, at UTC, as a :py:class:`datetime.date`. - - > We may add functionality in a future version to indicate a desired timezone via - > annotated types, but as mentioned above, _prefer common standards_ for formatting - > dates over other, less precise methods. + [iso]: https://en.wikipedia.org/wiki/ISO_8601 + [rfc]: https://tools.ietf.org/html/rfc3339 See Also: - - :py:func:`~typelib.serdes.decode` - - :py:func:`~typelib.serdes.dateparse` + - [`typelib.serdes.decode`][] + - [`typelib.serdes.dateparse`][] - [iso]: https://en.wikipedia.org/wiki/ISO_8601 - [rfc]: https://tools.ietf.org/html/rfc3339 """ def __call__(self, val: tp.Any) -> DateT: @@ -295,33 +293,34 @@ def __call__(self, val: tp.Any) -> DateT: class DateTimeUnmarshaller( AbstractUnmarshaller[datetime.datetime], tp.Generic[DateTimeT] ): - """Unmarshaller that converts an input to a :py:class`datetime.datetime` (or subclasses). + """Unmarshaller that converts an input to a [`datetime.datetime`][] (or subclasses). Notes: + This class tries to handle the 90% case: + + 1. If we are already a [`datetime.datetime`][] instance, return it. + 2. If we are a `float` or `int` instance, treat it as a unix timestamp, at UTC. + 3. Attempt to decode any bytes/string input into a real Python value. + 4. If we have a string value, parse it into either a [`datetime.date`][] + instance, a [`datetime.time`][] instance or a [`datetime.datetime`][]. + 5. If the parsed result is a [`datetime.time`][] instance, then merge + the parsed time with today, at the timezone specified in the time instance. + 6. If the parsed result is a [`datetime.date`][] instance, create a + [`datetime.datetime`][] instance at midnight of the indicated date, UTC. + + Tip: TL;DR There are many ways to represent a datetime object over-the-wire. Your most fool-proof method is to rely upon [ISO 8601][iso] or [RFC 3339][rfc]. - This class tries to handle the 90% case: - 1. If we are already a :py:class:`datetime.datetime` instance, return it. - 2. If we are a `float` or `int` instance, treat it as a unix timestamp, at UTC. - 3. Attempt to decode any bytes/string input into a real Python value. - 4. If we have a string value, parse it into either a :py:class:`datetime.date` - instance, a :py:class:`datetime.time` instance or a :py:class:`datetime.datetime`. - 5. If the parsed result is a :py:class:`datetime.time` instance, then merge - the parsed time with today, at the timezone specified in the time instance. - 6. If the parsed result is a :py:class:`datetime.date` instance, create a - :py:class:`datetime.datetime` instance at midnight of the indicated date, UTC. - - > We may add functionality in a future version to indicate a desired timezone via - > annotated types, but as mentioned above, _prefer common standards_ for formatting - > dates and times over other, less-precise methods. + [iso]: https://en.wikipedia.org/wiki/ISO_8601 + [rfc]: https://tools.ietf.org/html/rfc3339 + See Also: - - :py:func:`~typelib.serdes.decode` - - :py:func:`~typelib.serdes.dateparse` + - [`typelib.serdes.decode`][] + - [`typelib.serdes.dateparse`][] + - [iso]: https://en.wikipedia.org/wiki/ISO_8601 - [rfc]: https://tools.ietf.org/html/rfc3339 """ def __call__(self, val: tp.Any) -> datetime.datetime: @@ -377,33 +376,32 @@ def __call__(self, val: tp.Any) -> datetime.datetime: class TimeUnmarshaller(AbstractUnmarshaller[TimeT], tp.Generic[TimeT]): - """Unmarshaller that converts an input to a :py:class`datetime.time` (or subclasses). + """Unmarshaller that converts an input to a[`datetime.time`][] (or subclasses). Notes: + This class tries to handle the 90% case: + + 1. If we are already a [`datetime.time`][] instance, return it. + 2. If we are a `float` or `int` instance, treat it as a unix timestamp, at UTC. + 3. Attempt to decode any bytes/string input into a real Python value. + 4. If we have a string value, parse it into either a [`datetime.date`][] + instance, a [`datetime.time`][] instance or a [`datetime.datetime`][]. + 5. If the parsed result is a [`datetime.datetime`][] instance, then + extract the time portion, preserving the associated timezone. + 6. If the parsed result is a [`datetime.date`][] instance, create + a time instance at midnight, UTC. + + Tip: TL;DR There are many ways to represent a time object over-the-wire. Your most fool-proof method is to rely upon [ISO 8601][iso] or [RFC 3339][rfc]. - This class tries to handle the 90% case: - 1. If we are already a :py:class:`datetime.time` instance, return it. - 2. If we are a `float` or `int` instance, treat it as a unix timestamp, at UTC. - 3. Attempt to decode any bytes/string input into a real Python value. - 4. If we have a string value, parse it into either a :py:class:`datetime.date` - instance, a :py:class:`datetime.time` instance or a :py:class:`datetime.datetime`. - 5. If the parsed result is a :py:class:`datetime.datetime` instance, then - extract the time portion, preserving the associated timezone. - 6. If the parsed result is a :py:class:`datetime.date` instance, create - a time instance at midnight, UTC. - - > We may add functionality in a future version to indicate a desired timezone via - > annotated types, but as mentioned above, _prefer common standards_ for formatting - > dates and times over other, less precise methods. + [iso]: https://en.wikipedia.org/wiki/ISO_8601 + [rfc]: https://tools.ietf.org/html/rfc3339 See Also: - - :py:func:`~typelib.serdes.decode` - - :py:func:`~typelib.serdes.dateparse` + - [`typelib.serdes.decode`][] + - [`typelib.serdes.dateparse`][] - [iso]: https://en.wikipedia.org/wiki/ISO_8601 - [rfc]: https://tools.ietf.org/html/rfc3339 """ def __call__(self, val: tp.Any) -> TimeT: @@ -450,25 +448,30 @@ def __call__(self, val: tp.Any) -> TimeT: class TimeDeltaUnmarshaller(AbstractUnmarshaller[TimeDeltaT], tp.Generic[TimeDeltaT]): - """Unmarshaller that converts an input to a :py:class`datetime.timedelta` (or subclasses). + """Unmarshaller that converts an input to a [`datetime.timedelta`][] (or subclasses). Notes: - There are many ways to represent a timedelta object over-the-wire. Your most + This class tries to handle the 90% case: + + 1. If we are already a [`datetime.timedelta`][] instance, return it. + 2. If we are a `float` or `int` instance, treat it as total seconds for a delta. + 3. Attempt to decode any bytes/string input into a real Python value. + 4. If we have a string value, parse it into a [`datetime.timedelta`][] instance. + 5. If the parsed result is not *exactly* the bound `TimeDeltaT` type, convert it. + + + Tips: TL;DR + There are many ways to represent a time object over-the-wire. Your most fool-proof method is to rely upon [ISO 8601][iso] or [RFC 3339][rfc]. - This class tries to handle the 90% case: - 1. If we are already a :py:class:`datetime.timedelta` instance, return it. - 2. If we are a `float` or `int` instance, treat it as total seconds for a delta. - 3. Attempt to decode any bytes/string input into a real Python value. - 4. If we have a string value, parse it into a :py:class:`datetime.timedelta` instance. - 5. If the parsed result is not *exactly* the bound `TimeDeltaT` type, convert it. + [iso]: https://en.wikipedia.org/wiki/ISO_8601 + [rfc]: https://tools.ietf.org/html/rfc3339 + See Also: - - :py:func:`~typelib.serdes.decode` - - :py:func:`~typelib.serdes.dateparse` + - [`typelib.serdes.decode`][] + - [`typelib.serdes.dateparse`][] - [iso]: https://en.wikipedia.org/wiki/ISO_8601 - [rfc]: https://tools.ietf.org/html/rfc3339 """ def __call__(self, val: tp.Any) -> TimeDeltaT: @@ -497,18 +500,20 @@ def __call__(self, val: tp.Any) -> TimeDeltaT: class UUIDUnmarshaller(AbstractUnmarshaller[UUIDT], tp.Generic[UUIDT]): - """Unmarshaller that converts an input to a :py:class:`uuid.UUID` (or subclasses). + """Unmarshaller that converts an input to a [`uuid.UUID`][] (or subclasses). - Notes: + Note: The resolution algorithm is intentionally simple: - 1. Attempt to decode any bytes/string input into a real Python object. - 2. If the value is an integer, pass it into the constructor via the `int=` param. - 3. Otherwise, pass into the constructor directly. - - > While the :py:class:`uuid.UUID` constructor supports many different keyword - > inputs for different types of UUID formats/encodings, we don't have a great - > method for detecting the correct input. We have moved with the assumption that - > the two most formats are a standard string encoding, or an integer encoding. + + 1. Attempt to decode any bytes/string input into a real Python object. + 2. If the value is an integer, pass it into the constructor via the `int=` param. + 3. Otherwise, pass into the constructor directly. + + Tip: + While the [`uuid.UUID`][] constructor supports many different keyword + inputs for different types of UUID formats/encodings, we don't have a great + method for detecting the correct input. We have moved with the assumption that + the two most common formats are a standard string encoding, or an integer encoding. """ def __call__(self, val: tp.Any) -> UUIDT: @@ -518,7 +523,7 @@ def __call__(self, val: tp.Any) -> UUIDT: val: The input value to unmarshal. See Also: - - :py:func:`~typelib.serdes.load` + - [`typelib.serdes.load`][] """ decoded = serdes.load(val) if isinstance(decoded, int): @@ -532,15 +537,15 @@ def __call__(self, val: tp.Any) -> UUIDT: class PatternUnmarshaller(AbstractUnmarshaller[PatternT], tp.Generic[PatternT]): - """Unmarshaller that converts an input to a :py:class:`re.Pattern`. + """Unmarshaller that converts an input to a[`re.Pattern`][]. - Notes: - You can't instantiate a :py:class:`re.Pattern` directly, so we don't have a good - method for handling patterns from a different library OOTB. We simply call + Note: + You can't instantiate a [`re.Pattern`][] directly, so we don't have a good + method for handling patterns from a different library out-of-the-box. We simply call `re.compile()` on the decoded input. See Also: - - :py:func:`~typelib.serdes.decode` + - [`typelib.serdes.decode`][] """ def __call__(self, val: tp.Any) -> PatternT: @@ -549,14 +554,14 @@ def __call__(self, val: tp.Any) -> PatternT: class CastUnmarshaller(AbstractUnmarshaller[T]): - """Unmarshaller that converts an input to a :py:class:`T` with a direct cast. + """Unmarshaller that converts an input to an instance of `T` with a direct cast. - Notes: + Note: Before casting to the bound type, we will attempt to decode the value into a real Python object. See Also: - - :py:func:`~typelib.serdes.load` + - [`typelib.serdes.load`][] """ __slots__ = ("caster",) @@ -596,14 +601,14 @@ def __call__(self, val: tp.Any) -> T: class LiteralUnmarshaller(AbstractUnmarshaller[LiteralT], tp.Generic[LiteralT]): - """Unmarshaller that will enforce an input conform to a defined :py:class:typing.Literal`. + """Unmarshaller that will enforce an input conform to a defined [`typing.Literal`][]. - Notes: + Note: We will attempt to decode the value into a real Python object if the input fails initial membership evaluation. See Also: - - :py:func:`~typelib.serdes.load` + - [`typelib.serdes.load`][] """ __slots__ = ("values",) @@ -633,24 +638,26 @@ def __call__(self, val: tp.Any) -> LiteralT: class UnionUnmarshaller(AbstractUnmarshaller[UnionT], tp.Generic[UnionT]): - """Unmarshaller that will convert an input to one of the types defined in a :py:class:`typing.Union`. + """Unmarshaller that will convert an input to one of the types defined in a [`typing.Union`][]. - Notes: + Note: Union deserialization is messy and violates a static type-checking mechanism - for static type-checkers, `str | int` is equivalent to `int | str`. This breaks down during unmarshalling for the simple fact that casting something to `str` will always succeed, so we would never actually unmarshal the input it an `int`, even if that is the "correct" result. + Our algorithm is intentionally simple: + + 1. We iterate through each union member from top to bottom and call the + resolved unmarshaller, returning the result. + 2. If any of `(ValueError, TypeError, SyntaxError)`, try again with the + next unmarshaller. + 3. If all unmarshallers fail, then we have an invalid input, raise an error. + + Tip: TL;DR In order to ensure correctness, you should treat your union members as a stack, sorted from most-strict initialization to least-strict. - - Our algorithm is intentionally simple: - 1. We iterate through each union member from top to bottom and call the - resolved unmarshaller, returning the result. - 2. If any of `(ValueError, TypeError, SyntaxError)`, try again with the - next unmarshaller. - 3. If all unmarshallers fail, then we have an invalid input, raise an error. """ __slots__ = ("stack", "ordered_routines") @@ -696,21 +703,22 @@ class SubscriptedMappingUnmarshaller( ): """Unmarshaller for a subscripted mapping type. - Notes: + Note: This unmarshaller handles standard key->value mappings. We leverage our own generic `iteritems` to allow for translating other collections or structured objects into the target mapping. The algorithm is as follows: - 1. We attempt to decode the input into a real Python object. - 2. We iterate over key->value pairs. - 3. We call the key-type's unmarshaller on the `key` members. - 4. We call the value-type's unmarshaller on the `value` members. - 5. We pass the unmarshalling iterator in to the type's constructor. + + 1. We attempt to decode the input into a real Python object. + 2. We iterate over key->value pairs. + 3. We call the key-type's unmarshaller on the `key` members. + 4. We call the value-type's unmarshaller on the `value` members. + 5. We pass the unmarshalling iterator in to the type's constructor. See Also: - - :py:func:`~typelib.serdes.load` - - :py:func:`~typelib.serdes.iteritems` + - [`typelib.serdes.load`][] + - [`typelib.serdes.iteritems`][] """ __slots__ = ( @@ -754,20 +762,21 @@ class SubscriptedIterableUnmarshaller( ): """Unmarshaller for a subscripted iterable type. - Notes: + Note: This unmarshaller handles standard simple iterable types. We leverage our own generic `itervalues` to allow for translating other collections or structured objects into the target iterable. The algorithm is as follows: - 1. We attempt to decode the input into a real Python object. - 2. We iterate over values in the decoded input. - 3. We call the value-type's unmarshaller on the `value` members. - 5. We pass the unmarshalling iterator in to the type's constructor. + + 1. We attempt to decode the input into a real Python object. + 2. We iterate over values in the decoded input. + 3. We call the value-type's unmarshaller on the `value` members. + 5. We pass the unmarshalling iterator in to the type's constructor. See Also: - - :py:func:`~typelib.serdes.load` - - :py:func:`~typelib.serdes.itervalues` + - [`typelib.serdes.load`][] + - [`typelib.serdes.itervalues`][] """ __slots__ = ("values",) @@ -807,20 +816,21 @@ class SubscriptedIteratorUnmarshaller( ): """Unmarshaller for a subscripted iterator type. - Notes: + Note: This unmarshaller handles standard simple iterable types. We leverage our own generic `itervalues` to allow for translating other collections or structured objects into the target iterator. The algorithm is as follows: - 1. We attempt to decode the input into a real Python object. - 2. We iterate over values in the decoded input. - 3. We call the value-type's unmarshaller on the `value` members. - 5. We return a new, unmarshalling iterator. + + 1. We attempt to decode the input into a real Python object. + 2. We iterate over values in the decoded input. + 3. We call the value-type's unmarshaller on the `value` members. + 5. We return a new, unmarshalling iterator. See Also: - - :py:func:`~typelib.serdes.load` - - :py:func:`~typelib.serdes.itervalues` + - [`typelib.serdes.load`][] + - [`typelib.serdes.itervalues`][] """ __slots__ = ("values",) @@ -855,10 +865,11 @@ def __call__(self, val: tp.Any) -> IteratorT: class FixedTupleUnmarshaller(AbstractUnmarshaller[compat.TupleT]): """Unmarshaller for a "fixed" tuple (e.g., `tuple[int, str, float]`). - Notes: + Note: Python supports two distinct uses for tuples, unlike in other languages: - 1. Tuples with a fixed number of members. - 2. Tuples of variable length (an immutable sequence). + + 1. Tuples with a fixed number of members. + 2. Tuples of variable length (an immutable sequence). "Fixed" tuples may have a distinct type for each member, while variable-length tuples may only have a single type (or union of types) for all members. @@ -866,17 +877,19 @@ class FixedTupleUnmarshaller(AbstractUnmarshaller[compat.TupleT]): Variable-length tuples are handled by our generic iterable unmarshaller. For "fixed" tuples, the algorithm is: - 1. Attempt to decode the input into a real Python object. - 2. zip the stack of member unmarshallers and the values in the decoded object. - 3. Unmarshal each value using the associated unmarshaller for that position. - 4. Pass the unmarshalling iterator in to the type's constructor. - > If the input has more members than the type definition allows, those members - > will be dropped by nature of our unmarshalling algorithm. + 1. Attempt to decode the input into a real Python object. + 2. zip the stack of member unmarshallers and the values in the decoded object. + 3. Unmarshal each value using the associated unmarshaller for that position. + 4. Pass the unmarshalling iterator in to the type's constructor. - See Also: - - :py:func:`~typelib.serdes.load` - - :py:func:`~typelib.serdes.itervalues` + Tip: + If the input has more members than the type definition allows, those members + will be dropped by nature of our unmarshalling algorithm. + + See Also: + - [`typelib.serdes.load`][] + - [`typelib.serdes.itervalues`][] """ __slots__ = ("ordered_routines", "stack") @@ -896,7 +909,7 @@ def __init__( self.ordered_routines = [self.context[vt] for vt in self.stack] def __call__(self, val: tp.Any) -> compat.TupleT: - """Unmarshal a value into the bound :py:class:`~serdes.compat.TupleT`. + """Unmarshal a value into the bound [`tuple`][] structure. Args: val: The input value to unmarshal. @@ -914,26 +927,28 @@ def __call__(self, val: tp.Any) -> compat.TupleT: class StructuredTypeUnmarshaller(AbstractUnmarshaller[_ST]): """Unmarshaller for a "structured" (user-defined) type. - Notes: + Note: This unmarshaller supports the unmarshalling of any mapping or structured type into the targeted structured type. There are limitations. The algorithm is: - 1. Attempt to decode the input into a real Python object. - 2. Using a mapping of the structured types "field" to the field-type's unmarshaller, - iterate over the field->value pairs of the input, skipping fields in the - input which are not present in the field mapping. - 3. Store each unmarshalled value in a keyword-argument mapping. - 4. Unpack the keyword argument mapping into the bound type's constructor. - - > While we don't currently support arbitrary collections, we may add this - > functionality at a later date. Doing so requires more advanced introspection - > and parameter-binding that would lead to a significant loss in performance if - > not done carefully. + + 1. Attempt to decode the input into a real Python object. + 2. Using a mapping of the structured types "field" to the field-type's unmarshaller, + iterate over the field->value pairs of the input, skipping fields in the + input which are not present in the field mapping. + 3. Store each unmarshalled value in a keyword-argument mapping. + 4. Unpack the keyword argument mapping into the bound type's constructor. + + Tip: + While we don't currently support arbitrary collections, we may add this + functionality at a later date. Doing so requires more advanced introspection + and parameter-binding that would lead to a significant loss in performance if + not done carefully. See Also: - - :py:func:`~typelib.serdes.load` - - :py:func:`~typelib.serdes.itervalues` + - [`typelib.serdes.load`][] + - [`typelib.serdes.itervalues`][] """ __slots__ = ("fields_by_var",)