diff --git a/poetry.lock b/poetry.lock index fb3ae6e..3636d82 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand. [[package]] name = "annotated-types" @@ -6,6 +6,7 @@ version = "0.7.0" description = "Reusable constraint types to use with typing.Annotated" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, @@ -20,6 +21,7 @@ version = "3.7.1" description = "High level compatibility layer for multiple asynchronous event loop implementations" optional = false python-versions = ">=3.7" +groups = ["main", "dev"] files = [ {file = "anyio-3.7.1-py3-none-any.whl", hash = "sha256:91dee416e570e92c64041bd18b900d1d6fa78dff7048769ce5ac5ddad004fbb5"}, {file = "anyio-3.7.1.tar.gz", hash = "sha256:44a3c9aba0f5defa43261a8b3efb97891f2bd7d804e0e1f56419befa1adfc780"}, @@ -32,7 +34,7 @@ sniffio = ">=1.1" [package.extras] doc = ["Sphinx", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme (>=1.2.2)", "sphinxcontrib-jquery"] -test = ["anyio[trio]", "coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "mock (>=4)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] +test = ["anyio[trio]", "coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "mock (>=4) ; python_version < \"3.8\"", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17) ; python_version < \"3.12\" and platform_python_implementation == \"CPython\" and platform_system != \"Windows\""] trio = ["trio (<0.22)"] [[package]] @@ -41,6 +43,7 @@ version = "0.8.1" description = "Read/rewrite/write Python ASTs" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" +groups = ["dev"] files = [ {file = "astor-0.8.1-py2.py3-none-any.whl", hash = "sha256:070a54e890cefb5b3739d19f30f5a5ec840ffc9c50ffa7d23cc9fc1a38ebbfc5"}, {file = "astor-0.8.1.tar.gz", hash = "sha256:6a6effda93f4e1ce9f618779b2dd1d9d84f1e32812c23a29b3fff6fd7f63fa5e"}, @@ -52,18 +55,19 @@ version = "24.2.0" description = "Classes Without Boilerplate" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "attrs-24.2.0-py3-none-any.whl", hash = "sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2"}, {file = "attrs-24.2.0.tar.gz", hash = "sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346"}, ] [package.extras] -benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +benchmark = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.9\"", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.9\" and python_version < \"3.13\"", "pytest-xdist[psutil]"] +cov = ["cloudpickle ; platform_python_implementation == \"CPython\"", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.9\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.9\" and python_version < \"3.13\"", "pytest-xdist[psutil]"] +dev = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.9\"", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.9\" and python_version < \"3.13\"", "pytest-xdist[psutil]"] docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier (<24.7)"] -tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] +tests = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.9\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.9\" and python_version < \"3.13\"", "pytest-xdist[psutil]"] +tests-mypy = ["mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.9\"", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.9\" and python_version < \"3.13\""] [[package]] name = "autoflake" @@ -71,6 +75,7 @@ version = "1.7.7" description = "Removes unused imports and unused variables" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "autoflake-1.7.7-py3-none-any.whl", hash = "sha256:a9b43d08f8e455824e4f7b3f078399f59ba538ba53872f466c09e55c827773ef"}, {file = "autoflake-1.7.7.tar.gz", hash = "sha256:c8e4fc41aa3eae0f5c94b939e3a3d50923d7a9306786a6cbf4866a077b8f6832"}, @@ -86,6 +91,7 @@ version = "1.7.10" description = "Security oriented static analyser for python code." optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "bandit-1.7.10-py3-none-any.whl", hash = "sha256:665721d7bebbb4485a339c55161ac0eedde27d51e638000d91c8c2d68343ad02"}, {file = "bandit-1.7.10.tar.gz", hash = "sha256:59ed5caf5d92b6ada4bf65bc6437feea4a9da1093384445fed4d472acc6cff7b"}, @@ -101,7 +107,7 @@ stevedore = ">=1.20.0" baseline = ["GitPython (>=3.1.30)"] sarif = ["jschema-to-python (>=1.2.3)", "sarif-om (>=1.0.4)"] test = ["beautifulsoup4 (>=4.8.0)", "coverage (>=4.5.4)", "fixtures (>=3.0.0)", "flake8 (>=4.0.0)", "pylint (==1.9.4)", "stestr (>=2.5.0)", "testscenarios (>=0.5.0)", "testtools (>=2.3.0)"] -toml = ["tomli (>=1.1.0)"] +toml = ["tomli (>=1.1.0) ; python_version < \"3.11\""] yaml = ["PyYAML"] [[package]] @@ -110,6 +116,7 @@ version = "23.12.1" description = "The uncompromising code formatter." optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "black-23.12.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0aaf6041986767a5e0ce663c7a2f0e9eaf21e6ff87a5f95cbf3675bfd4c41d2"}, {file = "black-23.12.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c88b3711d12905b74206227109272673edce0cb29f27e1385f33b0163c414bba"}, @@ -146,7 +153,7 @@ typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} [package.extras] colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4)", "aiohttp (>=3.7.4,!=3.9.0)"] +d = ["aiohttp (>=3.7.4) ; sys_platform != \"win32\" or implementation_name != \"pypy\"", "aiohttp (>=3.7.4,!=3.9.0) ; sys_platform == \"win32\" and implementation_name == \"pypy\""] jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] uvloop = ["uvloop (>=0.15.2)"] @@ -156,6 +163,7 @@ version = "3.4.0" description = "Validate configuration and produce human readable error messages." optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"}, {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, @@ -167,6 +175,7 @@ version = "8.1.7" description = "Composable command line interface toolkit" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, @@ -181,6 +190,8 @@ version = "0.4.6" description = "Cross-platform colored terminal text." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +groups = ["dev"] +markers = "platform_system == \"Windows\" or sys_platform == \"win32\"" files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, @@ -192,6 +203,7 @@ version = "7.6.1" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "coverage-7.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b06079abebbc0e89e6163b8e8f0e16270124c154dc6e4a47b413dd538859af16"}, {file = "coverage-7.6.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cf4b19715bccd7ee27b6b120e7e9dd56037b9c0681dcc1adc9ba9db3d417fa36"}, @@ -271,7 +283,7 @@ files = [ tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} [package.extras] -toml = ["tomli"] +toml = ["tomli ; python_full_version <= \"3.11.0a6\""] [[package]] name = "darglint" @@ -279,6 +291,7 @@ version = "1.8.1" description = "A utility for ensuring Google-style docstrings stay up to date with the source code." optional = false python-versions = ">=3.6,<4.0" +groups = ["dev"] files = [ {file = "darglint-1.8.1-py3-none-any.whl", hash = "sha256:5ae11c259c17b0701618a20c3da343a3eb98b3bc4b5a83d31cdd94f5ebdced8d"}, {file = "darglint-1.8.1.tar.gz", hash = "sha256:080d5106df149b199822e7ee7deb9c012b49891538f14a11be681044f0bb20da"}, @@ -290,6 +303,7 @@ version = "0.3.9" description = "Distribution utilities" optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87"}, {file = "distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403"}, @@ -301,6 +315,7 @@ version = "0.20.1" description = "Docutils -- Python Documentation Utilities" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "docutils-0.20.1-py3-none-any.whl", hash = "sha256:96f387a2c5562db4476f09f13bbab2192e764cac08ebbf3a34a95d9b1e4a59d6"}, {file = "docutils-0.20.1.tar.gz", hash = "sha256:f08a4e276c3a1583a86dce3e34aba3fe04d02bba2dd51ed16106244e8a923e3b"}, @@ -312,6 +327,7 @@ version = "2.3.0" description = "Removes commented-out code." optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "eradicate-2.3.0-py3-none-any.whl", hash = "sha256:2b29b3dd27171f209e4ddd8204b70c02f0682ae95eecb353f10e8d72b149c63e"}, {file = "eradicate-2.3.0.tar.gz", hash = "sha256:06df115be3b87d0fc1c483db22a2ebb12bcf40585722810d809cc770f5031c37"}, @@ -323,6 +339,8 @@ version = "1.2.2" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" +groups = ["main", "dev"] +markers = "python_version < \"3.11\"" files = [ {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, @@ -337,6 +355,7 @@ version = "2.1.1" description = "execnet: rapid multi-Python deployment" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "execnet-2.1.1-py3-none-any.whl", hash = "sha256:26dee51f1b80cebd6d0ca8e74dd8745419761d3bef34163928cbebbdc4749fdc"}, {file = "execnet-2.1.1.tar.gz", hash = "sha256:5189b52c6121c24feae288166ab41b32549c7e2348652736540b9e6e7d4e72e3"}, @@ -351,6 +370,7 @@ version = "3.16.1" description = "A platform independent file lock." optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0"}, {file = "filelock-3.16.1.tar.gz", hash = "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435"}, @@ -359,7 +379,7 @@ files = [ [package.extras] docs = ["furo (>=2024.8.6)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4.1)"] testing = ["covdefaults (>=2.3)", "coverage (>=7.6.1)", "diff-cover (>=9.2)", "pytest (>=8.3.3)", "pytest-asyncio (>=0.24)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.26.4)"] -typing = ["typing-extensions (>=4.12.2)"] +typing = ["typing-extensions (>=4.12.2) ; python_version < \"3.11\""] [[package]] name = "flake8" @@ -367,6 +387,7 @@ version = "6.1.0" description = "the modular source code checker: pep8 pyflakes and co" optional = false python-versions = ">=3.8.1" +groups = ["dev"] files = [ {file = "flake8-6.1.0-py2.py3-none-any.whl", hash = "sha256:ffdfce58ea94c6580c77888a86506937f9a1a227dfcd15f245d694ae20a6b6e5"}, {file = "flake8-6.1.0.tar.gz", hash = "sha256:d5b3857f07c030bdb5bf41c7f53799571d75c4491748a3adcd47de929e34cd23"}, @@ -383,6 +404,7 @@ version = "4.1.1" description = "Automated security testing with bandit and flake8." optional = false python-versions = ">=3.6" +groups = ["dev"] files = [ {file = "flake8_bandit-4.1.1-py3-none-any.whl", hash = "sha256:4c8a53eb48f23d4ef1e59293657181a3c989d0077c9952717e98a0eace43e06d"}, {file = "flake8_bandit-4.1.1.tar.gz", hash = "sha256:068e09287189cbfd7f986e92605adea2067630b75380c6b5733dab7d87f9a84e"}, @@ -398,6 +420,7 @@ version = "1.0.0" description = "Flake8 plugin to forbid backslashes for line breaks" optional = false python-versions = ">=3.8,<4.0" +groups = ["dev"] files = [ {file = "flake8_broken_line-1.0.0-py3-none-any.whl", hash = "sha256:96c964336024a5030dc536a9f6fb02aa679e2d2a6b35b80a558b5136c35832a9"}, {file = "flake8_broken_line-1.0.0.tar.gz", hash = "sha256:e2c6a17f8d9a129e99c1320fce89b33843e2963871025c4c2bb7b8b8d8732a85"}, @@ -412,6 +435,7 @@ version = "23.12.2" description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." optional = false python-versions = ">=3.8.1" +groups = ["dev"] files = [ {file = "flake8-bugbear-23.12.2.tar.gz", hash = "sha256:32b2903e22331ae04885dae25756a32a8c666c85142e933f43512a70f342052a"}, {file = "flake8_bugbear-23.12.2-py3-none-any.whl", hash = "sha256:83324bad4d90fee4bf64dd69c61aff94debf8073fbd807c8b6a36eec7a2f0719"}, @@ -430,6 +454,7 @@ version = "2.1.0" description = "Flake8 lint for trailing commas." optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "flake8-commas-2.1.0.tar.gz", hash = "sha256:940441ab8ee544df564ae3b3f49f20462d75d5c7cac2463e0b27436e2050f263"}, {file = "flake8_commas-2.1.0-py2.py3-none-any.whl", hash = "sha256:ebb96c31e01d0ef1d0685a21f3f0e2f8153a0381430e748bf0bbbb5d5b453d54"}, @@ -444,6 +469,7 @@ version = "3.15.0" description = "A flake8 plugin to help you write better list/set/dict comprehensions." optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "flake8_comprehensions-3.15.0-py3-none-any.whl", hash = "sha256:b7e027bbb52be2ceb779ee12484cdeef52b0ad3c1fcb8846292bdb86d3034681"}, {file = "flake8_comprehensions-3.15.0.tar.gz", hash = "sha256:923c22603e0310376a6b55b03efebdc09753c69f2d977755cba8bb73458a5d4d"}, @@ -458,6 +484,7 @@ version = "4.1.2" description = "ipdb/pdb statement checker plugin for flake8" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "flake8-debugger-4.1.2.tar.gz", hash = "sha256:52b002560941e36d9bf806fca2523dc7fb8560a295d5f1a6e15ac2ded7a73840"}, {file = "flake8_debugger-4.1.2-py3-none-any.whl", hash = "sha256:0a5e55aeddcc81da631ad9c8c366e7318998f83ff00985a49e6b3ecf61e571bf"}, @@ -473,6 +500,7 @@ version = "1.7.0" description = "Extension for flake8 which uses pydocstyle to check docstrings" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "flake8_docstrings-1.7.0-py2.py3-none-any.whl", hash = "sha256:51f2344026da083fc084166a9353f5082b01f72901df422f74b4d953ae88ac75"}, {file = "flake8_docstrings-1.7.0.tar.gz", hash = "sha256:4c8cc748dc16e6869728699e5d0d685da9a10b0ea718e090b1ba088e67a941af"}, @@ -488,6 +516,7 @@ version = "1.5.0" description = "Flake8 plugin to find commented out code" optional = false python-versions = ">=3.8,<4.0" +groups = ["dev"] files = [ {file = "flake8_eradicate-1.5.0-py3-none-any.whl", hash = "sha256:18acc922ad7de623f5247c7d5595da068525ec5437dd53b22ec2259b96ce9d22"}, {file = "flake8_eradicate-1.5.0.tar.gz", hash = "sha256:aee636cb9ecb5594a7cd92d67ad73eb69909e5cc7bd81710cf9d00970f3983a6"}, @@ -504,6 +533,7 @@ version = "6.1.1" description = "flake8 plugin that integrates isort" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "flake8_isort-6.1.1-py3-none-any.whl", hash = "sha256:0fec4dc3a15aefbdbe4012e51d5531a2eb5fa8b981cdfbc882296a59b54ede12"}, {file = "flake8_isort-6.1.1.tar.gz", hash = "sha256:c1f82f3cf06a80c13e1d09bfae460e9666255d5c780b859f19f8318d420370b3"}, @@ -522,6 +552,7 @@ version = "3.4.0" description = "Flake8 lint for quotes." optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "flake8-quotes-3.4.0.tar.gz", hash = "sha256:aad8492fb710a2d3eabe68c5f86a1428de650c8484127e14c43d0504ba30276c"}, ] @@ -536,6 +567,7 @@ version = "0.3.0" description = "Python docstring reStructuredText (RST) validator for flake8" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "flake8-rst-docstrings-0.3.0.tar.gz", hash = "sha256:d1ce22b4bd37b73cd86b8d980e946ef198cfcc18ed82fedb674ceaa2f8d1afa4"}, {file = "flake8_rst_docstrings-0.3.0-py3-none-any.whl", hash = "sha256:f8c3c6892ff402292651c31983a38da082480ad3ba253743de52989bdc84ca1c"}, @@ -555,6 +587,7 @@ version = "0.3.0" description = "string format checker, plugin for flake8" optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "flake8-string-format-0.3.0.tar.gz", hash = "sha256:65f3da786a1461ef77fca3780b314edb2853c377f2e35069723348c8917deaa2"}, {file = "flake8_string_format-0.3.0-py2.py3-none-any.whl", hash = "sha256:812ff431f10576a74c89be4e85b8e075a705be39bc40c4b4278b5b13e2afa9af"}, @@ -569,6 +602,8 @@ version = "1.1.0" description = "Backport of the Python 3.9 graphlib module for Python 3.6+" optional = false python-versions = ">=3.6,<4.0" +groups = ["main"] +markers = "python_version < \"3.9\"" files = [ {file = "graphlib_backport-1.1.0-py3-none-any.whl", hash = "sha256:eccacf9f2126cdf89ce32a6018c88e1ecd3e4898a07568add6e1907a439055ba"}, {file = "graphlib_backport-1.1.0.tar.gz", hash = "sha256:00a7888b21e5393064a133209cb5d3b3ef0a2096cf023914c9d778dff5644125"}, @@ -580,6 +615,7 @@ version = "2.6.1" description = "File identification library for Python" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "identify-2.6.1-py2.py3-none-any.whl", hash = "sha256:53863bcac7caf8d2ed85bd20312ea5dcfc22226800f6d6881f232d861db5a8f0"}, {file = "identify-2.6.1.tar.gz", hash = "sha256:91478c5fb7c3aac5ff7bf9b4344f803843dc586832d5f110d672b19aa1984c98"}, @@ -594,6 +630,7 @@ version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.6" +groups = ["main", "dev"] files = [ {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, @@ -608,6 +645,7 @@ version = "8.5.0" description = "Read metadata from Python packages" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "importlib_metadata-8.5.0-py3-none-any.whl", hash = "sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b"}, {file = "importlib_metadata-8.5.0.tar.gz", hash = "sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7"}, @@ -617,12 +655,12 @@ files = [ zipp = ">=3.20" [package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] enabler = ["pytest-enabler (>=2.2)"] perf = ["ipython"] -test = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"] +test = ["flufl.flake8", "importlib-resources (>=1.3) ; python_version < \"3.9\"", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"] type = ["pytest-mypy"] [[package]] @@ -631,6 +669,7 @@ version = "2.0.0" description = "brain-dead simple config-ini parsing" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, @@ -642,6 +681,7 @@ version = "5.13.2" description = "A Python utility / library to sort Python imports." optional = false python-versions = ">=3.8.0" +groups = ["dev"] files = [ {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, @@ -656,6 +696,7 @@ version = "3.0.0" description = "Python port of markdown-it. Markdown parsing, done right!" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, @@ -680,6 +721,7 @@ version = "0.7.0" description = "McCabe checker, plugin for flake8" optional = false python-versions = ">=3.6" +groups = ["dev"] files = [ {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, @@ -691,6 +733,7 @@ version = "0.1.2" description = "Markdown URL utilities" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, @@ -702,6 +745,7 @@ version = "1.12.0" description = "Optional static typing for Python" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "mypy-1.12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4397081e620dc4dc18e2f124d5e1d2c288194c2c08df6bdb1db31c38cd1fe1ed"}, {file = "mypy-1.12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:684a9c508a283f324804fea3f0effeb7858eb03f85c4402a967d187f64562469"}, @@ -754,6 +798,7 @@ version = "1.0.0" description = "Type system extensions for programs checked with the mypy type checker." optional = false python-versions = ">=3.5" +groups = ["dev"] files = [ {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, @@ -765,6 +810,7 @@ version = "1.9.1" description = "Node.js virtual environment builder" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +groups = ["dev"] files = [ {file = "nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9"}, {file = "nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f"}, @@ -776,6 +822,7 @@ version = "24.1" description = "Core utilities for Python packages" optional = false python-versions = ">=3.8" +groups = ["main", "dev"] files = [ {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, @@ -787,6 +834,7 @@ version = "0.12.1" description = "Utility library for gitignore style pattern matching of file paths." optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, @@ -798,6 +846,7 @@ version = "6.1.0" description = "Python Build Reasonableness" optional = false python-versions = ">=2.6" +groups = ["dev"] files = [ {file = "pbr-6.1.0-py2.py3-none-any.whl", hash = "sha256:a776ae228892d8013649c0aeccbb3d5f99ee15e005a4cbb7e61d55a067b28a2a"}, {file = "pbr-6.1.0.tar.gz", hash = "sha256:788183e382e3d1d7707db08978239965e8b9e4e5ed42669bf4758186734d5f24"}, @@ -809,6 +858,7 @@ version = "0.13.3" description = "Check PEP-8 naming conventions, plugin for flake8" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "pep8-naming-0.13.3.tar.gz", hash = "sha256:1705f046dfcd851378aac3be1cd1551c7c1e5ff363bacad707d43007877fa971"}, {file = "pep8_naming-0.13.3-py3-none-any.whl", hash = "sha256:1a86b8c71a03337c97181917e2b472f0f5e4ccb06844a0d6f0a33522549e7a80"}, @@ -823,6 +873,7 @@ version = "4.3.6" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"}, {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"}, @@ -839,6 +890,7 @@ version = "1.5.0" description = "plugin and hook calling mechanisms for python" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, @@ -854,6 +906,7 @@ version = "2.21.0" description = "A framework for managing and maintaining multi-language pre-commit hooks." optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "pre_commit-2.21.0-py2.py3-none-any.whl", hash = "sha256:e2f91727039fc39a92f58a588a25b87f936de6567eed4f0e673e0507edc75bad"}, {file = "pre_commit-2.21.0.tar.gz", hash = "sha256:31ef31af7e474a8d8995027fefdfcf509b5c913ff31f2015b4ec4beb26a6f658"}, @@ -868,114 +921,93 @@ virtualenv = ">=20.10.0" [[package]] name = "psqlpy" -version = "0.8.7" +version = "0.9.3" description = "Async PostgreSQL driver for Python written in Rust" optional = false python-versions = ">=3.8" -files = [ - {file = "psqlpy-0.8.7-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:f60e88b5d6aa5d3f440b5951784f74253b2d3e69a584f1b3d063476242943b37"}, - {file = "psqlpy-0.8.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:752640b1f679289f443812e1756ed491c3d6c7913bac2991a12e45f52ac9c7af"}, - {file = "psqlpy-0.8.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e2727d816c61164aaace1d1155728498f3508217911cf7292876cacd0dda665"}, - {file = "psqlpy-0.8.7-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2ac9a1fe8b6ab30aaaafb12bbec6dfa2452634dd03797996a221858ace6e4815"}, - {file = "psqlpy-0.8.7-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a1d90768271967bec1b86286b8a38e71e123fc8743caa5fca11cf0a73b2c7b6"}, - {file = "psqlpy-0.8.7-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5f0d6cf0310387453a70a075069e211f3ff2052181bbdaa76d59e7b57fd103ce"}, - {file = "psqlpy-0.8.7-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3eef60bb63dbcf3dbbd04759e06994fd998353f6098a37ced0519d69736f242f"}, - {file = "psqlpy-0.8.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da3dc8de2a15a8ddec15db35a7742d83bb281959aaa8195912487884ae785b0e"}, - {file = "psqlpy-0.8.7-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3b15dce79d99602fa158e660994ebbb231a77aae76360a18ce2659e27cf34d84"}, - {file = "psqlpy-0.8.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c4ca916d578d16ed6bbb9d030b1267fa0953d2543704659948839d4e7ba4a0dd"}, - {file = "psqlpy-0.8.7-cp310-cp310-win32.whl", hash = "sha256:feffebf84658dabe52eca48c1f2b934120af96792c3d8735e3799b3b9ea370cc"}, - {file = "psqlpy-0.8.7-cp310-cp310-win_amd64.whl", hash = "sha256:27e20e24db6090c3f5032d1ac940c851dca5987e7090527e141305ed26f3a2a5"}, - {file = "psqlpy-0.8.7-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:587b379736f74721d177265353f6c9435e30f08907fb21a677502fd5a31b1ab2"}, - {file = "psqlpy-0.8.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4a231d6a9976b4613808acfc2ca68a4f5425891bf12068239ca5c1e3ee9635ad"}, - {file = "psqlpy-0.8.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:deac09e9f3f79327c98e659d7ed35e6b4de0b8c600dcc806e1efb69e2bd93208"}, - {file = "psqlpy-0.8.7-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6f701dd59628fd109955c1baf2b76c66a3cf86f3f315988f4ddaae3ab403ad40"}, - {file = "psqlpy-0.8.7-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:21dcdee367d500eb8a6f7780b86d8306d8f11a9ac0e98959842345730a2f9cc5"}, - {file = "psqlpy-0.8.7-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:273366f8e66e282a5902ffc265c61794f9f242884730a959eb0bd498fa1bd1ed"}, - {file = "psqlpy-0.8.7-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ffde5f287980e842eec6a4af0b5864a28978889396d054e8eaa37f5aae6516dd"}, - {file = "psqlpy-0.8.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf6f2a2c65e5bebed6107baed64942d4ba315e9a495c4b709bdfedd020cf676e"}, - {file = "psqlpy-0.8.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f12231fc2a1fe326b32fa93d7540f75fd68e9d916dcd8881d9bc61e94d3eaf0d"}, - {file = "psqlpy-0.8.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e2b460a55f7935a5d53a919143be1cfb8406fec2fa0e2d66fbf19c92179e4a8d"}, - {file = "psqlpy-0.8.7-cp311-cp311-win32.whl", hash = "sha256:15a8c0afddabe35e5c501d0af6d9098aa725c528214f806e33a2bcae952f2af7"}, - {file = "psqlpy-0.8.7-cp311-cp311-win_amd64.whl", hash = "sha256:d84e8ffe5aed5a5e5ff2103c96967b605bbb71a16d26606e32c28a1e94abb3b2"}, - {file = "psqlpy-0.8.7-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:ecae2101876843446bd3a06d928dc811321776dca2c668411137d12686880656"}, - {file = "psqlpy-0.8.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f885531118bb6cfd02bc4a9150c9303d2c6ff822993b45c6ed1a7bfd1afc3e36"}, - {file = "psqlpy-0.8.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:503746ee8d3a4ebf7f47fa14e5a2a112d9657267979ecf356876b1c00e5b626b"}, - {file = "psqlpy-0.8.7-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8225b7f175cd77aa87f77d360e2e952ab3dabcc66dcc06548ef43295df8fcc33"}, - {file = "psqlpy-0.8.7-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:489ce6e5581dd20aab1e53d0ebf3f5fecae4929d5214918cdb0f011ad912a5f1"}, - {file = "psqlpy-0.8.7-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a2a8d8ec9013dbc871672b763ebbad5f1736dc2aa71e1d667ba7d5bfca6ff626"}, - {file = "psqlpy-0.8.7-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0449bd2ca76a943b8d923a9a666c8046665fc80ebfbffdf64e1f2d67423bf76d"}, - {file = "psqlpy-0.8.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93c8890fde3633b6f52b18a954bd14e23672843daaa9302f3b2340332facc985"}, - {file = "psqlpy-0.8.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c946bf2a868d8d6dcd2349e36e8c1f2933c1ed630b1d3b9f01ee67e31bd4c32b"}, - {file = "psqlpy-0.8.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:912865a07f11de8b59860ca9abc544cc77ac8b2e163a13348ed674363dffcd15"}, - {file = "psqlpy-0.8.7-cp312-cp312-win32.whl", hash = "sha256:bf2a46db0b9c3300e034ad565760a646f8f5b07d8e15b6c7b94fdc6cf3a1d0ac"}, - {file = "psqlpy-0.8.7-cp312-cp312-win_amd64.whl", hash = "sha256:dfc4c87df98d0d3a1be32f3cc4d7c4e3b9b542a557fc3339cdc2e5c2b2b1f51c"}, - {file = "psqlpy-0.8.7-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:a451f8d4b775f3df3b5f88d354a36b0a341119c902a8717c95f08023f2a3e1f6"}, - {file = "psqlpy-0.8.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c43edd1b04e465d87ef0596ec9a07db52f02260ccb4d76211bb6681dc9d369d6"}, - {file = "psqlpy-0.8.7-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b50d96c7232970525f04ca4b77c0647ffea93d8d9ab28fdde19a101a50428a8"}, - {file = "psqlpy-0.8.7-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:112eda28b4b312b2b9d58c01bc318f73949a7a9c99805aef2e04a5950232f319"}, - {file = "psqlpy-0.8.7-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9dfaacb59324177219c833db062a243f333dd6d91f5c41f02bea096c620fc2b0"}, - {file = "psqlpy-0.8.7-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:096712fa25bd6dcda8604d4351af06bffb13f4ede6b0a34e151d967df576f443"}, - {file = "psqlpy-0.8.7-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7b62763d95582d5a310b7b08a574eb324cdba740b6f5e4f56affd2a43121b54d"}, - {file = "psqlpy-0.8.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:600187ac8c233219fa59983713f9249d6d9287f6b0f6d75636c219a46d7bc2aa"}, - {file = "psqlpy-0.8.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b1da73c341da70a377406904fdf29aee85832af3538b5baadc441a7dd3fee24b"}, - {file = "psqlpy-0.8.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6aa44f890afc4076507a453dd4faf27a32e41f7fa952e659da94d5c1551d06d3"}, - {file = "psqlpy-0.8.7-cp313-cp313-win32.whl", hash = "sha256:3929b7292d7c642e6f8bb024c27c7c376789b54ef730a442bbd29df2c1c0b347"}, - {file = "psqlpy-0.8.7-cp313-cp313-win_amd64.whl", hash = "sha256:f48d6ff606db2fef2c5816e598cadc7b9349aa83118f896cd29875853fd83b4e"}, - {file = "psqlpy-0.8.7-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d97f8a683f05d38faa56a2165c822eb725447ab5e8b4d79bc972d6743ddc1d17"}, - {file = "psqlpy-0.8.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:92aaafef0bdd91f19466e268eacea8019a95c0dff2bae93f304c8d0d50652c6e"}, - {file = "psqlpy-0.8.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:225293c56221ddbb1d580d2251ea61e4677783fe2a267ead4e751a479dc04321"}, - {file = "psqlpy-0.8.7-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e668b5c4e51837baaa374ce869dee3ca8f5ae7f2ec819fc6bcb057a3a58269b4"}, - {file = "psqlpy-0.8.7-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3de81b7abce2d0a398cb20814b7716ace4f62d82839b98150fb7f6cd92a308e0"}, - {file = "psqlpy-0.8.7-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2043508609db80220cf4afa8f0ae49428be331c1b88e18af1642804e8c092ce3"}, - {file = "psqlpy-0.8.7-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5b4f22f4ccd0165075acdc565a505ce74737e2574e2c5452af79c2d1950f7924"}, - {file = "psqlpy-0.8.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bcb925661e4b769a3d6710e5031c079e1eed888628d2fe9b7b9cfcd42f12ba4a"}, - {file = "psqlpy-0.8.7-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:03de165fc817408466903085e5b1465ac1b0985ae6b18bef0c2196690f23ffd9"}, - {file = "psqlpy-0.8.7-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:f8011f7cd9083b65bf0f09bef25f5e4b6fab0cd9e15bbb48bff56548c78ed612"}, - {file = "psqlpy-0.8.7-cp38-cp38-win32.whl", hash = "sha256:2e6d4471645a7e9674e06d408729fd174709b1b7e24456425616210256714975"}, - {file = "psqlpy-0.8.7-cp38-cp38-win_amd64.whl", hash = "sha256:4e5b91b83a2d153dce8a8c0408e2dadc9f93820170a3d82575796b57badda02e"}, - {file = "psqlpy-0.8.7-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:d93c6f0a170995c1893e4860805eaa07046ba665047d5a2825ed05f76d96feb1"}, - {file = "psqlpy-0.8.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:79df75e711deb3b7cbc915e98f8e45a65df211d1bec12b158c4c12c98996b5e4"}, - {file = "psqlpy-0.8.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:565ed39b316f3ee66af9237542c3620ced11869fa98560e8ab97e2cb080209c3"}, - {file = "psqlpy-0.8.7-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:33f372433d30b4d82f69719ef70f2d80c41bc51b8d2f75d6718ebd20496481e5"}, - {file = "psqlpy-0.8.7-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:079a9951418f4f5f75f6f75e308ced87f2f0ec4a438a61acc6bc35dca1fa070c"}, - {file = "psqlpy-0.8.7-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:20646eb238e041af6874111dd45bf56d1cb1053c3fd59ab5cad07bcb3ea580e3"}, - {file = "psqlpy-0.8.7-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:390934bb8bb2a3e133dc03281fe808b88f03c0ecaa97af0bf88167e7d798845b"}, - {file = "psqlpy-0.8.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de9aed62f87111c1615d2ccd646d950f91740c2a0dff80ea27f0deb9432a3d92"}, - {file = "psqlpy-0.8.7-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:00cdf118cd516a43c0473686eda79a3027faa1b79afabaf551338af3e7477f1e"}, - {file = "psqlpy-0.8.7-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c0968a51d03a17cce922731748b3a1071bac6599363a9aef5bb338293e622f1c"}, - {file = "psqlpy-0.8.7-cp39-cp39-win32.whl", hash = "sha256:6eafbdb9b03db5ca2db19e7d3568346ebc65cbe851cb5a1181eab1e13ae51715"}, - {file = "psqlpy-0.8.7-cp39-cp39-win_amd64.whl", hash = "sha256:9d9808b92103ad7058ea19406a9e86ee510250c5ce093b06908e91e06c63e42c"}, - {file = "psqlpy-0.8.7-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:859a781607785bd8e7a46ae2cfb84974c386f734817ae1e5cdf141628445dd7f"}, - {file = "psqlpy-0.8.7-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:c5d070dcf5e84baac3f5e31149f112c5330834c73e52133584b6da13ec9d89fe"}, - {file = "psqlpy-0.8.7-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b3ed7d278be41b730a72c0219e45b1de91399e0a08a525301e9d4d2e5cdcf179"}, - {file = "psqlpy-0.8.7-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b4da8bb7c94a8b6f7d3f719156d8d407faec5b1ac2a901883c9df83859342ac7"}, - {file = "psqlpy-0.8.7-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f48967f37a6643563d6cfb10796fafb6cc22a707b3491885ab8e66187cf6146d"}, - {file = "psqlpy-0.8.7-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80612eb35c1d91e62f14e7be9fdeff7e0a9f017f7334a85b31b1b5fc829df761"}, - {file = "psqlpy-0.8.7-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:addb9857d802944fa8c51ea1481fdba3e0dd19aa8d11b75f9002bf0b438f6234"}, - {file = "psqlpy-0.8.7-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd0c8387009c8e627af0eecaa46a1546266f9d7263c3cb1a1f1c851188b5acdf"}, - {file = "psqlpy-0.8.7-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:0e8c3a3ceb53c3e728e8d0293951041a50053b0ce6981892174e01b80e864c07"}, - {file = "psqlpy-0.8.7-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:cd94077b6f6511fb8c87b8ef55854e9935fe15475562be095c5e82226d58ef6f"}, - {file = "psqlpy-0.8.7-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:578637f29478136f219beac95b6ad867c40608dcc35d2c0f5473d4b4ca867b65"}, - {file = "psqlpy-0.8.7-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:87d8bc35ce54696d2416801cdd9662e999c6d6ffd0cdee77ee7ccf2069c50bb3"}, - {file = "psqlpy-0.8.7-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ae93d353b546458e5aa31f993a88bd600932b27ca54f269477818559907525c3"}, - {file = "psqlpy-0.8.7-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5030016f90521d3496ce52537aaf145f73ce0786306f215015f43b8883ba658d"}, - {file = "psqlpy-0.8.7-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:71748c94dc754c0cf659fd639338890e3b5308e84ea32dd4a247e11150b0ce60"}, - {file = "psqlpy-0.8.7-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:027cb7eb6c5817fbfe253bd1703d59e0710213451c0ccf4128e8765324e7fdf7"}, - {file = "psqlpy-0.8.7-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f2b41265ed914a536d66944dee5c2fc189807bfae05a35d541f0ddb1ac53e7ee"}, - {file = "psqlpy-0.8.7-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f447b8de785805cac81677a2fd8f3d2ad8d0e66b89c66b952d1e1ca7bfdc9d33"}, - {file = "psqlpy-0.8.7-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:37360884103c1a0977be9b7d48b83ae377a37727a302ed4695f62a228daa2a18"}, - {file = "psqlpy-0.8.7-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:dc2d1bf1f8721c7b17b91a71e510ff2db98a2758409febd49a237b834c092575"}, - {file = "psqlpy-0.8.7-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:86ac1a3edfeca0a7c2a20bfcf7fa77ea76cb74e126c1c1040332f8049e983672"}, - {file = "psqlpy-0.8.7-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:eb47deed2bd7c104f5676c62c9bd52c3561454f903c632cfb769015699890e95"}, - {file = "psqlpy-0.8.7-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cc823f556846e94bb691f175191086c792a95eec196d32f4b9cd564c8ad0d2e"}, - {file = "psqlpy-0.8.7-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a4cab6add99093fbfadc183715a45f6b443c8ee0738b75c84cfe09657fa972b1"}, - {file = "psqlpy-0.8.7-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:03774a1be5922892cc0c54e08fb27833c19fe7d294e75910f722bb5781cb2622"}, - {file = "psqlpy-0.8.7-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:94e4e8740aa920d3f8f96b5f40617e7410c482fec2e9be57852251090f290b27"}, - {file = "psqlpy-0.8.7-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f7896592b74b996aac3954ee3555a060010c5c37774c4aff679390a24b3e770b"}, - {file = "psqlpy-0.8.7-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9afd28f30084e51279077962506ed8a84346c384dff6d2111782a164ba887d5"}, - {file = "psqlpy-0.8.7-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:304f3395ed930ce85a873169649a06057d1c63e91de657c7d6d4894cce6def6a"}, - {file = "psqlpy-0.8.7-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:df55e811d0802f0f56353e4b93eeac5be29ff042eda708ef9508ca892e4b4627"}, - {file = "psqlpy-0.8.7.tar.gz", hash = "sha256:510f3d66a99d40242224ac97f90dd8d19c91407ab6ad042cbf8d5864a4afe6ea"}, +groups = ["main"] +files = [ + {file = "psqlpy-0.9.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3c36efab33733d6fb9064a0c9fb59de4a529376837b080277e6825437bb1efa9"}, + {file = "psqlpy-0.9.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:57d9b5054494daaa60a7337351c3f9fc36354bac5764dd868134f9e91cd11245"}, + {file = "psqlpy-0.9.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a32b7f7b700180058ac7b5e7a02bac4c91de1ac94404e2a2a4eb67c91d2369a"}, + {file = "psqlpy-0.9.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:40ce3f9b67c7cea8bff8ce7b2f435191f1f064168134c17ba457695278145cd1"}, + {file = "psqlpy-0.9.3-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e6704cd34d1ed0f0873c448eb206565fdcd3eb0fc435428860aa529ce203bec"}, + {file = "psqlpy-0.9.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d3215cac58e8a6fb867a4cafaac3303d03ace5a623cb2ed7858ee797ab6b2bcd"}, + {file = "psqlpy-0.9.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d6a741e1694325c737f1917fa80ffcda27a3a533c03d033a059b39e5fb85eca6"}, + {file = "psqlpy-0.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc9013962aac0ca16d59e8b7a20856c0838fb09ddbf9a3e5bb2cde2add3c5a89"}, + {file = "psqlpy-0.9.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:2bdf0afa1cae9e79553665a906315d7c6421ed587b012ec9c4397e91c200fd7b"}, + {file = "psqlpy-0.9.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:bd2c3c3a5b0305d42430cc8af1d5c4130008b9a80cf5bb3fedfd414cd9b95181"}, + {file = "psqlpy-0.9.3-cp310-cp310-win32.whl", hash = "sha256:79a0ec837dd314df5af74577f8b5b2fb752e74641a5cb66d58d779d88648d191"}, + {file = "psqlpy-0.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:ee0d53b33f7b841cd606a8dbbf8b36e809dddee526dc7e226a7d1b1fdb0e3e3b"}, + {file = "psqlpy-0.9.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:66830960242bdec926ebb697284731f643176f4694419ecc4e48d064545c6e40"}, + {file = "psqlpy-0.9.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:45a12aead3ca4d2b18b114b541289bcb5894bd5746670ee9fe5d783f55a565d4"}, + {file = "psqlpy-0.9.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3fec5e579f519b98f5feb9e2148549c48391811e3153156deee7d2bc129f605"}, + {file = "psqlpy-0.9.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:11a2b3574e9cf37f49dd5a8376823bb1c416222c133b59873ad2fdb91b0ba25f"}, + {file = "psqlpy-0.9.3-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:92afd8603006a18461d91167eff7ac100029b47034bbdd477f5e3805f9d23ff8"}, + {file = "psqlpy-0.9.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:71a912328513d6c89a8c3d1be615916ab360075c810ff0445e7c53030ff03186"}, + {file = "psqlpy-0.9.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4861bb23574f2275bbd4f695bd4b2393fe6a5442f0a1bb603ebb6061f9926f9e"}, + {file = "psqlpy-0.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf151599e516d7b0bbe0f8e2c10d45b7a48a72be2716c9fe7a77ecf41b17e3b9"}, + {file = "psqlpy-0.9.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:b3fece2b78d568d74435b5ff0f05406bb3a43b1c571a66b7c1909efd52c31508"}, + {file = "psqlpy-0.9.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3c49ea203ef3007b8dbd12a453dd6d45aa9ffd3e395181e837138d172e30c293"}, + {file = "psqlpy-0.9.3-cp311-cp311-win32.whl", hash = "sha256:60833a0187dfdd859248bc424326d34b96b74c627e057a286632adbe4fb185a1"}, + {file = "psqlpy-0.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:185d508f9165ae51ed8e659ce8356986523ac14021233162e7b565a1b50e0486"}, + {file = "psqlpy-0.9.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:6502545e46f9453a6103152e223f43461ca90e4d6d353b8567b40b45a01d43f8"}, + {file = "psqlpy-0.9.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f447410df05b0b927a8cc995fa011477b291d57f1b8f8ca52ee4a3799b698c8b"}, + {file = "psqlpy-0.9.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b825a3534d6a2810aed9c53873b8a58562bd28afc95506643ec4cc095bdda1a0"}, + {file = "psqlpy-0.9.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:842a06192c4d6748aa63df3966b8685630ce1d2f1cdfbe54f95177c2db7436ad"}, + {file = "psqlpy-0.9.3-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ece78105348c482bbcc1c7504c2067e8baf8ec64600aea40c293880995fb39c"}, + {file = "psqlpy-0.9.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c099c16aa3d224d3b0c6950eabbbf58154f04612522511c3d83a0e97cd689eed"}, + {file = "psqlpy-0.9.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bb9746cdb5c8ddbbcf952bad67e07f4c46722de072cf6cfd69d8fb67d296156c"}, + {file = "psqlpy-0.9.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4beb0fc66c7924edcf6f842682554910d93376e31d527fa3d055ee24326bd84f"}, + {file = "psqlpy-0.9.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:40e530d71441af61b791723bbf4a198b0da4e95f59d261e67074790564b629e5"}, + {file = "psqlpy-0.9.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a74926fa272acc2889f510317894307c2dda7702feb8195a159b564603d0c74c"}, + {file = "psqlpy-0.9.3-cp312-cp312-win32.whl", hash = "sha256:2b125d06a0c2718b5cf3b9c866ea9bf19764f51c2aa054919534e4767f43b1f8"}, + {file = "psqlpy-0.9.3-cp312-cp312-win_amd64.whl", hash = "sha256:613facca51bbf0682d863989e7368222e8040b3ce5f5b0ae3ce30d9df4e44d60"}, + {file = "psqlpy-0.9.3-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:9c7b371f5bc3e4e60e7f0b34db5c8ec82c6aee3e967f6916251895fc0123015b"}, + {file = "psqlpy-0.9.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8546854232368d26eb2c7eba64df2765a4b4698d1465a9c20e6af0b61f495558"}, + {file = "psqlpy-0.9.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5e83ede139b7c650b5be3019de769db5bab44e72c3365604719222ca9c0825d"}, + {file = "psqlpy-0.9.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5441f83b707f698c23b9c498845caabf523248adda1276be4efc58474991ba88"}, + {file = "psqlpy-0.9.3-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9070b7a767aa3ad6d16a6b4008b3590e576296d1ef810f11fbf7ad317ca902e"}, + {file = "psqlpy-0.9.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2452e0c1b5fa1f4d4b0c73daf277de0785e2a4aaa7d75282b100b2d1758a7677"}, + {file = "psqlpy-0.9.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:231f57d6129358bdd828f1a24667c727ac9cd07ae374b76ab9d860bc9778be36"}, + {file = "psqlpy-0.9.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b9d258b4af8593fafd02ec00dd594f0de7cb9c5a6d59bb30c0883bb314046bf4"}, + {file = "psqlpy-0.9.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:5a45f42936faa2839b72d8ba6f31c7f22490cf5211a5acfe507655b22110df6e"}, + {file = "psqlpy-0.9.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:81f2c9f7f94388d5977e28ab00522ddccd1b880e9f382e350207a80a6c2b790f"}, + {file = "psqlpy-0.9.3-cp313-cp313-win32.whl", hash = "sha256:9126f5e942c2a8ed1aefa8a662a2865f7aaf293a7610911fd4a07200c133a27a"}, + {file = "psqlpy-0.9.3-cp313-cp313-win_amd64.whl", hash = "sha256:e438732440dbba845b1f2fcec426cc8a70461d31e81b330efe5ab4e5a83ead52"}, + {file = "psqlpy-0.9.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:583f93e6dcdc5f0c6a9259ed7da686c5a888f10ac8546cdd7e4cacfac5826700"}, + {file = "psqlpy-0.9.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8fc690c4b56b5aa3242518309167c78820621fd6b3284951c65d7426218be3f6"}, + {file = "psqlpy-0.9.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1395fcfdb294d75ee9044b1da60fcaaca3d01c62cfa338f3c18ecd097e0bd738"}, + {file = "psqlpy-0.9.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:033e41fecdfe3b4dee6050d4002c5d619b9325bef4167cc497d644c093ee87f4"}, + {file = "psqlpy-0.9.3-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7fadb57a391db8ac1b172a2f3882796e8f77ef2e01795db9fe96870b3d434116"}, + {file = "psqlpy-0.9.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d7cb7714554cf08e4eaea8fd547dddb65a32927db4c37afd0fbe9a941d839743"}, + {file = "psqlpy-0.9.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ddbcd8438cc439862e05e03f4cf364f76dc51d918fe405878c1acfab1848112c"}, + {file = "psqlpy-0.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fd086508cf11e3c390f5d6ed638a39e3d2b4186e53e33ffe6af9b37981ef615"}, + {file = "psqlpy-0.9.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:35aa277d6585ed14936e6c1e4de677564959e379485272906c88090cc5e635dd"}, + {file = "psqlpy-0.9.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:81a25ef924322a15a53ee6c36dd38c3d609d05c96f3cf500af33cd929cbe30a1"}, + {file = "psqlpy-0.9.3-cp39-cp39-win32.whl", hash = "sha256:fa1cbd09536576b22e7aa5e312cf802d4e7da2438c48064bf6886028e8977bec"}, + {file = "psqlpy-0.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:ca15a64cbd4de84c7b9a34f388c70dded46316fac8af851c2f1ba51a755f378f"}, + {file = "psqlpy-0.9.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:8c4a6035ebfba0744b15a5c9a3668b2166393619bfb882a189468966ec45f7f0"}, + {file = "psqlpy-0.9.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:681dee1d030873f08e55b154c8907a2062f0f6e4b10646411f5ce94028eb0642"}, + {file = "psqlpy-0.9.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e26ed13c864b21542eab15f1dfccf02e40fae046076d9c48b3ff062f8406053b"}, + {file = "psqlpy-0.9.3-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1baa0200bcdacc9f61efbd273074395bfc7f32b7f7a30fcebb260ae175545914"}, + {file = "psqlpy-0.9.3-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:925677b1c2ea70addbcb28b86ddc826b77a8107ec489e2d191fb74074ea423b2"}, + {file = "psqlpy-0.9.3-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d2c01d44e04f2e9fc7de1c3a8692f38fa22d0a354ce51888b91d8653cae4e0a3"}, + {file = "psqlpy-0.9.3-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b89fb5906bffa757f76c1ef46ec48e3ec3488d484d95d9bc57503b30107e3041"}, + {file = "psqlpy-0.9.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c193eeca5dbceb770332197cc77a6e5e6ead210c34c4fff1d8cb8675e42e1f6"}, + {file = "psqlpy-0.9.3-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:eab75d64e3b27a52bcbee690e8651a3b0dbaeef3028a19afad3a848ccb1b2951"}, + {file = "psqlpy-0.9.3-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:a4f77af73b77bd73285efc0576a3ac087ee0aca39821371ea16d8e2bf9a16c90"}, + {file = "psqlpy-0.9.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:d7d4c6fcc343e0c0238e767caccb534d08b42d234d96e35aa5ce55d195f81281"}, + {file = "psqlpy-0.9.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7d0220fa8127db04433c2be2a55da1042e4581531a36692c45668c3484bda437"}, + {file = "psqlpy-0.9.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbdd68fa7f61e00d7f14f010cd4a7f242935cb9df560181bb947fde75c8c1af5"}, + {file = "psqlpy-0.9.3-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1c1e3c82aeec4c58328c723ef0755c2f02e2d30874ce850e0d7505db8bd90397"}, + {file = "psqlpy-0.9.3-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c936f35fa793b421b116aa37040291ff5a33fc54e7f636e7ae946ec987070a94"}, + {file = "psqlpy-0.9.3-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:28ee25f791ccbad04269e22a21a79d52609d65298fe9b5300b8fe00fef42bab6"}, + {file = "psqlpy-0.9.3-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b3a1d90bb1da48649852e636612bb12fa0e3ec07f230446836195054598f0de4"}, + {file = "psqlpy-0.9.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a764bf80ce4e9d284bc11e255aff836894ee55e540c1be20120e67f855d8b07c"}, + {file = "psqlpy-0.9.3-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:7939bfa80b649e650b9b4efe9064936837b14082851f1ad95c24548a105277cd"}, + {file = "psqlpy-0.9.3-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:23496ed36433c88308f7e85f36091b203bb6c8c655ded639ce1626a1c8319afe"}, + {file = "psqlpy-0.9.3.tar.gz", hash = "sha256:f369528a4a1f5c8dea6efe0d469a07a735ab4d07e680faff4508699b183bcc37"}, ] [[package]] @@ -984,6 +1016,7 @@ version = "2.11.1" description = "Python style guide checker" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "pycodestyle-2.11.1-py2.py3-none-any.whl", hash = "sha256:44fe31000b2d866f2e41841b18528a505fbd7fef9017b04eff4e2648a0fadc67"}, {file = "pycodestyle-2.11.1.tar.gz", hash = "sha256:41ba0e7afc9752dfb53ced5489e89f8186be00e599e712660695b7a75ff2663f"}, @@ -995,6 +1028,7 @@ version = "3.0.0" description = "Simple cron-like parser, which determines if current datetime matches conditions." optional = false python-versions = ">=3.5" +groups = ["main"] files = [ {file = "pycron-3.0.0.tar.gz", hash = "sha256:b916044e3e8253d5409c68df3ac64a3472c4e608dab92f40e8f595e5d3acb3de"}, ] @@ -1005,6 +1039,7 @@ version = "2.9.2" description = "Data validation using Python type hints" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "pydantic-2.9.2-py3-none-any.whl", hash = "sha256:f048cec7b26778210e28a0459867920654d48e5e62db0958433636cde4254f12"}, {file = "pydantic-2.9.2.tar.gz", hash = "sha256:d155cef71265d1e9807ed1c32b4c8deec042a44a50a4188b25ac67ecd81a9c0f"}, @@ -1020,7 +1055,7 @@ typing-extensions = [ [package.extras] email = ["email-validator (>=2.0.0)"] -timezone = ["tzdata"] +timezone = ["tzdata ; python_version >= \"3.9\" and sys_platform == \"win32\""] [[package]] name = "pydantic-core" @@ -1028,6 +1063,7 @@ version = "2.23.4" description = "Core functionality for Pydantic validation and serialization" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "pydantic_core-2.23.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:b10bd51f823d891193d4717448fab065733958bdb6a6b351967bd349d48d5c9b"}, {file = "pydantic_core-2.23.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4fc714bdbfb534f94034efaa6eadd74e5b93c8fa6315565a222f7b6f42ca1166"}, @@ -1129,6 +1165,7 @@ version = "6.3.0" description = "Python docstring style checker" optional = false python-versions = ">=3.6" +groups = ["dev"] files = [ {file = "pydocstyle-6.3.0-py3-none-any.whl", hash = "sha256:118762d452a49d6b05e194ef344a55822987a462831ade91ec5c06fd2169d019"}, {file = "pydocstyle-6.3.0.tar.gz", hash = "sha256:7ce43f0c0ac87b07494eb9c0b462c0b73e6ff276807f204d6b53edc72b7e44e1"}, @@ -1138,7 +1175,7 @@ files = [ snowballstemmer = ">=2.2.0" [package.extras] -toml = ["tomli (>=1.2.3)"] +toml = ["tomli (>=1.2.3) ; python_version < \"3.11\""] [[package]] name = "pyflakes" @@ -1146,6 +1183,7 @@ version = "3.1.0" description = "passive checker of Python programs" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "pyflakes-3.1.0-py2.py3-none-any.whl", hash = "sha256:4132f6d49cb4dae6819e5379898f2b8cce3c5f23994194c24b77d5da2e36f774"}, {file = "pyflakes-3.1.0.tar.gz", hash = "sha256:a0aae034c444db0071aa077972ba4768d40c830d9539fd45bf4cd3f8f6992efc"}, @@ -1157,6 +1195,7 @@ version = "2.18.0" description = "Pygments is a syntax highlighting package written in Python." optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"}, {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"}, @@ -1171,6 +1210,7 @@ version = "7.4.4" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, @@ -1193,6 +1233,7 @@ version = "4.1.0" description = "Pytest plugin for measuring coverage." optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"}, {file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"}, @@ -1211,6 +1252,7 @@ version = "3.6.1" description = "pytest xdist plugin for distributed testing, most importantly across multiple CPUs" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "pytest_xdist-3.6.1-py3-none-any.whl", hash = "sha256:9ed4adfb68a016610848639bb7e02c9352d5d9f03d04809919e2dafc3be4cca7"}, {file = "pytest_xdist-3.6.1.tar.gz", hash = "sha256:ead156a4db231eec769737f57668ef58a2084a34b2e55c4a8fa20d861107300d"}, @@ -1231,6 +1273,7 @@ version = "2024.2" description = "World timezone definitions, modern and historical" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "pytz-2024.2-py2.py3-none-any.whl", hash = "sha256:31c7c1817eb7fae7ca4b8c7ee50c72f93aa2dd863de768e1ef4245d426aa0725"}, {file = "pytz-2024.2.tar.gz", hash = "sha256:2aa355083c50a0f93fa581709deac0c9ad65cca8a9e9beac660adcbd493c798a"}, @@ -1242,6 +1285,7 @@ version = "6.0.2" description = "YAML parser and emitter for Python" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, @@ -1304,6 +1348,7 @@ version = "1.4.0" description = "reStructuredText linter" optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "restructuredtext_lint-1.4.0.tar.gz", hash = "sha256:1b235c0c922341ab6c530390892eb9e92f90b9b75046063e047cacfb0f050c45"}, ] @@ -1317,6 +1362,7 @@ version = "13.9.2" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" optional = false python-versions = ">=3.8.0" +groups = ["dev"] files = [ {file = "rich-13.9.2-py3-none-any.whl", hash = "sha256:8c82a3d3f8dcfe9e734771313e606b39d8247bb6b826e196f4914b333b743cf1"}, {file = "rich-13.9.2.tar.gz", hash = "sha256:51a2c62057461aaf7152b4d611168f93a9fc73068f8ded2790f29fe2b5366d0c"}, @@ -1336,6 +1382,7 @@ version = "0.3.7" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "ruff-0.3.7-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:0e8377cccb2f07abd25e84fc5b2cbe48eeb0fea9f1719cad7caedb061d70e5ce"}, {file = "ruff-0.3.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:15a4d1cc1e64e556fa0d67bfd388fed416b7f3b26d5d1c3e7d192c897e39ba4b"}, @@ -1362,19 +1409,20 @@ version = "75.2.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "setuptools-75.2.0-py3-none-any.whl", hash = "sha256:a7fcb66f68b4d9e8e66b42f9876150a3371558f98fa32222ffaa5bced76406f8"}, {file = "setuptools-75.2.0.tar.gz", hash = "sha256:753bb6ebf1f465a1912e19ed1d41f403a79173a9acf66a42e7e6aec45c3c16ec"}, ] [package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.5.2)"] -core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.collections", "jaraco.functools", "jaraco.text (>=3.7)", "more-itertools", "more-itertools (>=8.8)", "packaging", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\"", "ruff (>=0.5.2) ; sys_platform != \"cygwin\""] +core = ["importlib-metadata (>=6) ; python_version < \"3.10\"", "importlib-resources (>=5.10.2) ; python_version < \"3.9\"", "jaraco.collections", "jaraco.functools", "jaraco.text (>=3.7)", "more-itertools", "more-itertools (>=8.8)", "packaging", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1) ; python_version < \"3.11\"", "wheel (>=0.43.0)"] cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] enabler = ["pytest-enabler (>=2.2)"] -test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] -type = ["importlib-metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (==1.11.*)", "pytest-mypy"] +test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21) ; python_version >= \"3.9\" and sys_platform != \"cygwin\"", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf ; sys_platform != \"cygwin\"", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] +type = ["importlib-metadata (>=7.0.2) ; python_version < \"3.10\"", "jaraco.develop (>=7.21) ; sys_platform != \"cygwin\"", "mypy (==1.11.*)", "pytest-mypy"] [[package]] name = "sniffio" @@ -1382,6 +1430,7 @@ version = "1.3.1" description = "Sniff out which async library your code is running under" optional = false python-versions = ">=3.7" +groups = ["main", "dev"] files = [ {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, @@ -1393,6 +1442,7 @@ version = "2.2.0" description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, @@ -1404,6 +1454,7 @@ version = "5.3.0" description = "Manage dynamic plugins for Python applications" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "stevedore-5.3.0-py3-none-any.whl", hash = "sha256:1efd34ca08f474dad08d9b19e934a22c68bb6fe416926479ba29e5013bcc8f78"}, {file = "stevedore-5.3.0.tar.gz", hash = "sha256:9a64265f4060312828151c204efbe9b7a9852a0d9228756344dbc7e4023e375a"}, @@ -1418,6 +1469,7 @@ version = "0.11.10" description = "Distributed task queue with full async support" optional = false python-versions = "<4.0.0,>=3.8.1" +groups = ["main"] files = [ {file = "taskiq-0.11.10-py3-none-any.whl", hash = "sha256:2b656c34231bf6947a6020098c94f93d6c45d15688d9e6bb8b3fbf54088e7717"}, {file = "taskiq-0.11.10.tar.gz", hash = "sha256:d3ce40ccf399b38aa656614ecab6e5bbcc222b61fee654927822fc97ef4418a6"}, @@ -1439,7 +1491,7 @@ metrics = ["prometheus_client (>=0,<1)"] msgpack = ["msgpack (>=1.0.7,<2.0.0)"] orjson = ["orjson (>=3,<4)"] reload = ["gitignore-parser (>=0,<1)", "watchdog (>=4,<5)"] -uv = ["uvloop (>=0.16.0,<1)"] +uv = ["uvloop (>=0.16.0,<1) ; sys_platform != \"win32\""] zmq = ["pyzmq (>=26,<27)"] [[package]] @@ -1448,6 +1500,7 @@ version = "1.5.4" description = "FastAPI like dependency injection implementation" optional = false python-versions = "<4.0.0,>=3.8.1" +groups = ["main"] files = [ {file = "taskiq_dependencies-1.5.4-py3-none-any.whl", hash = "sha256:8b10d2635a8ada8774f1b555e0a6d72c4fb5e6089601858d38dd95ff6d214a4c"}, {file = "taskiq_dependencies-1.5.4.tar.gz", hash = "sha256:04546a5786e0f8cb2e008af19cdf415dd27d63d6d29ccf15eda8fa6b8b6b8006"}, @@ -1463,6 +1516,7 @@ version = "6.0.0" description = "A wrapper around the stdlib `tokenize` which roundtrips." optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "tokenize_rt-6.0.0-py2.py3-none-any.whl", hash = "sha256:d4ff7ded2873512938b4f8cbb98c9b07118f01d30ac585a30d7a88353ca36d22"}, {file = "tokenize_rt-6.0.0.tar.gz", hash = "sha256:b9711bdfc51210211137499b5e355d3de5ec88a85d2025c520cbb921b5194367"}, @@ -1474,6 +1528,8 @@ version = "2.0.2" description = "A lil' TOML parser" optional = false python-versions = ">=3.8" +groups = ["dev"] +markers = "python_full_version <= \"3.11.0a6\"" files = [ {file = "tomli-2.0.2-py3-none-any.whl", hash = "sha256:2ebe24485c53d303f690b0ec092806a085f07af5a5aa1464f3931eec36caaa38"}, {file = "tomli-2.0.2.tar.gz", hash = "sha256:d46d457a85337051c36524bc5349dd91b1877838e2979ac5ced3e710ed8a60ed"}, @@ -1485,6 +1541,7 @@ version = "4.12.2" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" +groups = ["main", "dev"] files = [ {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, @@ -1496,6 +1553,7 @@ version = "20.27.0" description = "Virtual Python Environment builder" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "virtualenv-20.27.0-py3-none-any.whl", hash = "sha256:44a72c29cceb0ee08f300b314848c86e57bf8d1f13107a5e671fb9274138d655"}, {file = "virtualenv-20.27.0.tar.gz", hash = "sha256:2ca56a68ed615b8fe4326d11a0dca5dfbe8fd68510fb6c6349163bed3c15f2b2"}, @@ -1508,7 +1566,7 @@ platformdirs = ">=3.9.1,<5" [package.extras] 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)"] +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) ; platform_python_implementation == \"PyPy\" or platform_python_implementation == \"CPython\" and sys_platform == \"win32\" and python_version >= \"3.13\"", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10) ; platform_python_implementation == \"CPython\""] [[package]] name = "wemake-python-styleguide" @@ -1516,6 +1574,7 @@ version = "0.18.0" description = "The strictest and most opinionated python linter ever" optional = false python-versions = ">=3.8.1,<4.0" +groups = ["dev"] files = [ {file = "wemake_python_styleguide-0.18.0-py3-none-any.whl", hash = "sha256:2219be145185edcd5e01f4ce49e3dea11acc34f2c377face0c175bb6ea6ac988"}, {file = "wemake_python_styleguide-0.18.0.tar.gz", hash = "sha256:69139858cf5b2a9ba09dac136e2873a4685515768f68fdef2684ebefd7b1dafd"}, @@ -1549,6 +1608,7 @@ version = "1.5.0" description = "Automatically remove unnecessary `# noqa` comments." optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "yesqa-1.5.0-py2.py3-none-any.whl", hash = "sha256:600c6d6e59aff9d85422c28c0d0ff016c040f4eb653636632c18fb6c43453e00"}, {file = "yesqa-1.5.0.tar.gz", hash = "sha256:209c17274f3c0cc22195ddb26f93df3523634d0756f756913ed05cba970efad9"}, @@ -1564,20 +1624,21 @@ version = "3.20.2" description = "Backport of pathlib-compatible object wrapper for zip files" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "zipp-3.20.2-py3-none-any.whl", hash = "sha256:a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350"}, {file = "zipp-3.20.2.tar.gz", hash = "sha256:bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29"}, ] [package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] enabler = ["pytest-enabler (>=2.2)"] -test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"] +test = ["big-O", "importlib-resources ; python_version < \"3.9\"", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"] type = ["pytest-mypy"] [metadata] -lock-version = "2.0" +lock-version = "2.1" python-versions = "^3.8.1" -content-hash = "389f523846fb945f8876cb954ff695aeab4928f40d2ba6f4ade566a3e23a167f" +content-hash = "8225295c28ae5dd5934b16ae6a1f7660a726efbcf7cca9f812ef32e597a92953" diff --git a/pyproject.toml b/pyproject.toml index 857adb2..ed1c328 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,7 +29,7 @@ keywords = [ [tool.poetry.dependencies] python = "^3.8.1" -psqlpy = "^0.8.7" +psqlpy = "^0.9.3" taskiq = "^0.11.10" [tool.poetry.group.dev.dependencies] diff --git a/taskiq_psqlpy/__init__.py b/taskiq_psqlpy/__init__.py index 8c4db26..7ebcea4 100644 --- a/taskiq_psqlpy/__init__.py +++ b/taskiq_psqlpy/__init__.py @@ -1,5 +1,7 @@ +from taskiq_psqlpy.broker import PSQLPyBroker from taskiq_psqlpy.result_backend import PSQLPyResultBackend __all__ = [ + "PSQLPyBroker", "PSQLPyResultBackend", ] diff --git a/taskiq_psqlpy/broker.py b/taskiq_psqlpy/broker.py new file mode 100644 index 0000000..4839c49 --- /dev/null +++ b/taskiq_psqlpy/broker.py @@ -0,0 +1,258 @@ +import asyncio +import logging +from dataclasses import dataclass +from datetime import datetime +from typing import ( + AsyncGenerator, + Callable, + Optional, + TypedDict, + TypeVar, + cast, + override, +) + +import psqlpy +from psqlpy.extra_types import JSONB +from taskiq import AckableMessage, AsyncBroker, AsyncResultBackend, BrokerMessage + +from taskiq_psqlpy.broker_queries import ( + CREATE_TABLE_QUERY, + DELETE_MESSAGE_QUERY, + INSERT_MESSAGE_QUERY, + SELECT_MESSAGE_QUERY, +) + +_T = TypeVar("_T") +logger = logging.getLogger("taskiq.asyncpg_broker") + + +@dataclass +class MessageRow: + """Message in db table.""" + + id: int + task_id: str + task_name: str + message: str + labels: JSONB + created_at: datetime + + +class PoolKwargs(TypedDict, total=False): + """Psqlpy connection kwargs. + + Excludes dsn/user params because dsn used in broker. + """ + + target_session_attrs: psqlpy.TargetSessionAttrs | None + options: str | None + application_name: str | None + connect_timeout_sec: int | None + connect_timeout_nanosec: int | None + tcp_user_timeout_sec: int | None + tcp_user_timeout_nanosec: int | None + keepalives: bool | None + keepalives_idle_sec: int | None + keepalives_idle_nanosec: int | None + keepalives_interval_sec: int | None + keepalives_interval_nanosec: int | None + keepalives_retries: int | None + load_balance_hosts: psqlpy.LoadBalanceHosts | None + conn_recycling_method: psqlpy.ConnRecyclingMethod | None + ssl_mode: psqlpy.SslMode | None + ca_file: str | None + + +class PSQLPyBroker(AsyncBroker): + """Broker that uses PostgreSQL and asyncpg with LISTEN/NOTIFY.""" + + def __init__( + self, + dsn: str = "postgresql://postgres:postgres@localhost:5432/postgres", + result_backend: Optional[AsyncResultBackend[_T]] = None, + task_id_generator: Optional[Callable[[], str]] = None, + channel_name: str = "taskiq", + table_name: str = "taskiq_messages", + max_retry_attempts: int = 5, + read_pool_kwargs: Optional[PoolKwargs] = None, + write_pool_kwargs: Optional[PoolKwargs] = None, + max_write_pool_size: int = 2, + ) -> None: + """ + Construct a new broker. + + :param dsn: Connection string to PostgreSQL. + :param result_backend: Custom result backend. + :param task_id_generator: Custom task_id generator. + :param channel_name: Name of the channel to listen on. + :param table_name: Name of the table to store messages. + :param max_retry_attempts: Maximum number of message processing attempts. + :param connection_kwargs: Additional arguments for asyncpg connection. + :param pool_kwargs: Additional arguments for asyncpg pool creation. + """ + super().__init__( + result_backend=result_backend, + task_id_generator=task_id_generator, + ) + + self.dsn: str = dsn + self.channel_name: str = channel_name + self.table_name: str = table_name + self.read_pool_kwargs: PoolKwargs = read_pool_kwargs if read_pool_kwargs else {} + self.write_pool_kwargs: PoolKwargs = ( + write_pool_kwargs if write_pool_kwargs else {} + ) + self.max_retry_attempts: int = max_retry_attempts + self.read_conn: Optional[psqlpy.Connection] = None + self.write_pool: Optional[psqlpy.ConnectionPool] = None + self.max_write_pool_size: int = max_write_pool_size + + self._queue: Optional[asyncio.Queue[str]] = None + + @override + async def startup(self) -> None: + """Initialize the broker.""" + await super().startup() + self.read_conn = await psqlpy.connect( + dsn=self.dsn, + **self.read_pool_kwargs, + ).connection() + self.write_pool = psqlpy.connect( + dsn=self.dsn, + max_db_pool_size=self.max_write_pool_size, + **self.write_pool_kwargs, + ) + + # create messages table if doesn't exist + async with self.write_pool.acquire() as conn: + _ = await conn.execute(CREATE_TABLE_QUERY.format(self.table_name)) + + # listen to notification channel + listener = self.write_pool.listener() + await listener.add_callback(self.channel_name, self._notification_handler) + await listener.startup() + listener.listen() + + self._queue = asyncio.Queue() + + @override + async def shutdown(self) -> None: + """Close all connections on shutdown.""" + await super().shutdown() + if self.read_conn is not None: + self.read_conn.back_to_pool() + if self.write_pool is not None: + self.write_pool.close() + + async def _notification_handler( + self, + connection: psqlpy.Connection, # pyright: ignore[reportUnusedParameter] + payload: str, + channel: str, + process_id: int, # pyright: ignore[reportUnusedParameter] + ) -> None: + """Handle NOTIFY messages. + + From asyncpg.connection.add_listener docstring: + A callable or a coroutine function receiving the following arguments: + **connection**: a Connection the callback is registered with; + **pid**: PID of the Postgres server that sent the notification; + **channel**: name of the channel the notification was sent to; + **payload**: the payload. + """ + logger.debug(f"Received notification on channel {channel}: {payload}") + if self._queue is not None: + self._queue.put_nowait(payload) + + @override + async def kick(self, message: BrokerMessage) -> None: + """ + Send message to the channel. + + Inserts the message into the database and sends a NOTIFY. + + :param message: Message to send. + """ + if self.write_pool is None: + raise ValueError("Please run startup before kicking.") + + async with self.write_pool.acquire() as conn: + # insert message into db table + message_inserted_id = cast( + int, + await conn.fetch_val( + INSERT_MESSAGE_QUERY.format(self.table_name), + [ + message.task_id, + message.task_name, + message.message.decode(), + JSONB(message.labels), + ], + ), + ) + + delay_value = cast(Optional[str], message.labels.get("delay")) + if delay_value is not None: + delay_seconds = int(delay_value) + _ = asyncio.create_task( # noqa: RUF006 + self._schedule_notification(message_inserted_id, delay_seconds), + ) + else: + # Send NOTIFY with message ID as payload + _ = await conn.execute( + f"NOTIFY {self.channel_name}, '{message_inserted_id}'", + ) + + async def _schedule_notification(self, message_id: int, delay_seconds: int) -> None: + """Schedule a notification to be sent after a delay.""" + await asyncio.sleep(delay_seconds) + if self.write_pool is None: + raise ValueError("Call startup before starting listening.") + async with self.write_pool.acquire() as conn: + # Send NOTIFY with message ID as payload + _ = await conn.execute(f"NOTIFY {self.channel_name}, '{message_id}'") + + @override + async def listen(self) -> AsyncGenerator[AckableMessage, None]: + """ + Listen to the channel. + + Yields messages as they are received. + + :yields: AckableMessage instances. + """ + if self.read_conn is None: + raise ValueError("Call startup before starting listening.") + if self._queue is None: + raise ValueError("Startup did not initialize the queue.") + + while True: + try: + payload = await self._queue.get() + message_id = int(payload) # payload is the message id + message_row = await self.read_conn.fetch_row( + SELECT_MESSAGE_QUERY.format(self.table_name), + [message_id], + ) + # ugly type hacks b/c SingleQueryResult.as_class return type is wrong + message_row_result = cast( + MessageRow, + cast(object, message_row.as_class(MessageRow)), + ) + message_data = message_row_result.message.encode() + + async def ack(*, _message_id: int = message_id) -> None: + if self.write_pool is None: + raise ValueError("Call startup before starting listening.") + + async with self.write_pool.acquire() as conn: + _ = await conn.execute( + DELETE_MESSAGE_QUERY.format(self.table_name), + [_message_id], + ) + + yield AckableMessage(data=message_data, ack=ack) + except Exception as e: + logger.exception(f"Error processing message: {e}") + continue diff --git a/taskiq_psqlpy/broker_queries.py b/taskiq_psqlpy/broker_queries.py new file mode 100644 index 0000000..d074f33 --- /dev/null +++ b/taskiq_psqlpy/broker_queries.py @@ -0,0 +1,20 @@ +CREATE_TABLE_QUERY = """ +CREATE TABLE IF NOT EXISTS {} ( + id SERIAL PRIMARY KEY, + task_id VARCHAR NOT NULL, + task_name VARCHAR NOT NULL, + message TEXT NOT NULL, + labels JSONB NOT NULL, + created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() +); +""" + +INSERT_MESSAGE_QUERY = """ +INSERT INTO {} (task_id, task_name, message, labels) +VALUES ($1, $2, $3, $4) +RETURNING id +""" + +SELECT_MESSAGE_QUERY = "SELECT * FROM {} WHERE id = $1" + +DELETE_MESSAGE_QUERY = "DELETE FROM {} WHERE id = $1" diff --git a/taskiq_psqlpy/result_backend.py b/taskiq_psqlpy/result_backend.py index e6415e7..4a15d80 100644 --- a/taskiq_psqlpy/result_backend.py +++ b/taskiq_psqlpy/result_backend.py @@ -67,13 +67,14 @@ async def startup(self) -> None: dsn=self.dsn, **self.connect_kwargs, ) - await self._database_pool.execute( + connection = await self._database_pool.connection() + await connection.execute( querystring=CREATE_TABLE_QUERY.format( self.table_name, self.field_for_task_id, ), ) - await self._database_pool.execute( + await connection.execute( querystring=CREATE_INDEX_QUERY.format( self.table_name, self.table_name, @@ -94,7 +95,8 @@ async def set_result( :param task_id: ID of the task. :param result: result of the task. """ - await self._database_pool.execute( + connection = await self._database_pool.connection() + await connection.execute( querystring=INSERT_RESULT_QUERY.format( self.table_name, ), @@ -149,7 +151,7 @@ async def get_result( ) from exc if not self.keep_results: - await self._database_pool.execute( + await connection.execute( querystring=DELETE_RESULT_QUERY.format( self.table_name, ), diff --git a/tests/conftest.py b/tests/conftest.py index 8791a10..25ad9ea 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -5,6 +5,7 @@ import pytest +from taskiq_psqlpy.broker import PSQLPyBroker from taskiq_psqlpy.result_backend import PSQLPyResultBackend _ReturnType = TypeVar("_ReturnType") @@ -30,7 +31,7 @@ def postgres_table() -> str: """ return "".join( random.choice( - string.ascii_uppercase, + string.ascii_lowercase, ) for _ in range(10) ) @@ -60,7 +61,33 @@ async def psqlpy_result_backend( ) await backend.startup() yield backend - await backend._database_pool.execute( - querystring=f"DROP TABLE {postgres_table}", - ) + async with backend._database_pool.acquire() as conn: + _ = await conn.execute( + querystring=f"DROP TABLE {postgres_table}", + ) await backend.shutdown() + + +@pytest.fixture() +async def psqlpy_broker( + postgresql_dsn: str, + postgres_table: str, +) -> AsyncGenerator[PSQLPyBroker, None]: + """ + Fixture to set up and tear down the broker. + + Initializes the broker with test parameters. + """ + broker = PSQLPyBroker( + dsn=postgresql_dsn, + channel_name=f"{postgres_table}_channel", + table_name=postgres_table, + ) + await broker.startup() + + yield broker + + assert broker.write_pool + async with broker.write_pool.acquire() as conn: + _ = await conn.execute(f"DROP TABLE {postgres_table}") + await broker.shutdown() diff --git a/tests/test_broker.py b/tests/test_broker.py new file mode 100644 index 0000000..c622a7c --- /dev/null +++ b/tests/test_broker.py @@ -0,0 +1,195 @@ +import asyncio +import json +import uuid +from typing import cast + +import psqlpy +from psqlpy.extra_types import JSONB +import pytest +from taskiq import AckableMessage, BrokerMessage +from taskiq.utils import maybe_awaitable + +from taskiq_psqlpy import PSQLPyBroker +from taskiq_psqlpy.broker_queries import ( + INSERT_MESSAGE_QUERY, +) + + +async def get_first_task(psqlpy_broker: PSQLPyBroker) -> AckableMessage: + """ + Get the first message from the broker's listen method. + + :param broker: Instance of AsyncpgBroker. + :return: The first AckableMessage received. + """ + async for message in psqlpy_broker.listen(): + return message + msg = "Unreachable" + raise RuntimeError(msg) + + +@pytest.mark.anyio +async def test_kick_success(psqlpy_broker: PSQLPyBroker) -> None: + """ + Test that messages are published and read correctly. + + We kick the message, listen to the queue, and check that + the received message matches what was sent. + """ + # Create a unique task ID and name + task_id = uuid.uuid4().hex + task_name = uuid.uuid4().hex + + # Construct the message + sent = BrokerMessage( + task_id=task_id, + task_name=task_name, + message=b"my_msg", + labels={ + "label1": "val1", + }, + ) + + # Send the message + await psqlpy_broker.kick(sent) + + # Listen for the message + message = await asyncio.wait_for(get_first_task(psqlpy_broker), timeout=1.0) + + # Check that the received message matches the sent message + assert message.data == sent.message + + # Acknowledge the message + await maybe_awaitable(message.ack()) + + +@pytest.mark.anyio +async def test_startup(psqlpy_broker: PSQLPyBroker) -> None: + """ + Test the startup process of the broker. + + We drop the messages table, restart the broker, and ensure + that the table is recreated. + """ + # Drop the messages table + assert psqlpy_broker.write_pool is not None + assert psqlpy_broker.read_conn is not None + + async with psqlpy_broker.write_pool.acquire() as conn: + _ = await conn.execute(f"DROP TABLE IF EXISTS {psqlpy_broker.table_name}") + + # Shutdown and restart the broker + await psqlpy_broker.shutdown() + await psqlpy_broker.startup() + + # Verify that the table exists + table_exists = cast( + bool, + await psqlpy_broker.read_conn.fetch_val( + """ + SELECT EXISTS ( + SELECT 1 FROM information_schema.tables + WHERE table_schema = 'public' AND table_name = $1 + ) + """, + [ + psqlpy_broker.table_name, + ], + ), + ) + assert table_exists, f"couldn't find {psqlpy_broker.table_name}" + + +@pytest.mark.anyio +async def test_listen(psqlpy_broker: PSQLPyBroker) -> None: + """ + Test listen. + + Test that the broker can listen to messages inserted directly into the database + and notified via the channel. + """ + # Insert a message directly into the database + pool = psqlpy.connect(psqlpy_broker.dsn) + message_content = b"test_message" + task_id = uuid.uuid4().hex + task_name = "test_task" + labels = {"label1": "label_val"} + async with pool.acquire() as conn: + message_id = cast( + bool, + await conn.fetch_val( + INSERT_MESSAGE_QUERY.format(psqlpy_broker.table_name), + [ + task_id, + task_name, + message_content.decode(), + JSONB(labels), + ], + ), + ) + # Send a NOTIFY with the message ID + _ = await conn.execute(f"NOTIFY {psqlpy_broker.channel_name}, '{message_id}'") + + # Listen for the message + message = await asyncio.wait_for(get_first_task(psqlpy_broker), timeout=1.0) + assert message.data == message_content + + # Acknowledge the message + await maybe_awaitable(message.ack()) + + +@pytest.mark.anyio +async def test_wrong_format(psqlpy_broker: PSQLPyBroker) -> None: + """Test that messages with incorrect formats are still received.""" + # Insert a message with missing task_id and task_name + pool = psqlpy.connect(psqlpy_broker.dsn) + async with pool.acquire() as conn: + message_id = cast( + bool, + await conn.fetch_val( + INSERT_MESSAGE_QUERY.format(psqlpy_broker.table_name), + [ + "", # Missing task_id + "", # Missing task_name + "wrong", # Message content + JSONB({}), # Empty labels + ], + ), + ) + # Send a NOTIFY with the message ID + _ = await conn.execute(f"NOTIFY {psqlpy_broker.channel_name}, '{message_id}'") + + # Listen for the message + message = await asyncio.wait_for(get_first_task(psqlpy_broker), timeout=1.0) + assert message.data == b"wrong" # noqa: PLR2004 + + # Acknowledge the message + await maybe_awaitable(message.ack()) + + +@pytest.mark.anyio +async def test_delayed_message(psqlpy_broker: PSQLPyBroker) -> None: + """Test that delayed messages are delivered correctly after the specified delay.""" + # Send a message with a delay + task_id = uuid.uuid4().hex + task_name = "test_task" + sent = BrokerMessage( + task_id=task_id, + task_name=task_name, + message=b"delayed_message", + labels={ + "delay": "2", # Delay in seconds + }, + ) + await psqlpy_broker.kick(sent) + + # Try to get the message immediately (should not be available yet) + with pytest.raises(asyncio.TimeoutError): + _ = await asyncio.wait_for(get_first_task(psqlpy_broker), timeout=1.0) + + # Wait for the delay to pass and receive the message + message = await asyncio.wait_for(get_first_task(psqlpy_broker), timeout=3.0) + assert message.data == sent.message + + # Acknowledge the message + await maybe_awaitable(message.ack()) diff --git a/tests/test_result_backend.py b/tests/test_result_backend.py index 9a55217..831176e 100644 --- a/tests/test_result_backend.py +++ b/tests/test_result_backend.py @@ -89,7 +89,8 @@ async def test_success_backend_default_result_delete_res( with pytest.raises(expected_exception=ResultIsMissingError): await backend.get_result(task_id=task_id) - await backend._database_pool.execute( + connection = await backend._database_pool.connection() + await connection.execute( querystring=f"DROP TABLE {postgres_table}", )