diff --git a/alembic/versions/9f4b6184b2f8_drop_usage_pkey.py b/alembic/versions/9f4b6184b2f8_drop_usage_pkey.py new file mode 100644 index 0000000..892b54a --- /dev/null +++ b/alembic/versions/9f4b6184b2f8_drop_usage_pkey.py @@ -0,0 +1,27 @@ +"""drop_usage_pkey + +Revision ID: 9f4b6184b2f8 +Revises: b65796c99771 +Create Date: 2024-10-10 11:28:39.846967 + +""" + +from alembic import op + +# revision identifiers, used by Alembic. +revision = "9f4b6184b2f8" +down_revision = "b65796c99771" +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_constraint("usage_pkey", "usage", type_="primary", schema="accounting") + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_primary_key("usage_pkey", "usage", ["id"], schema="accounting") + # ### end Alembic commands ### diff --git a/poetry.lock b/poetry.lock index ee5e29d..a82b442 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,9 +1,10 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry and should not be changed by hand. [[package]] name = "alabaster" version = "0.7.16" description = "A light, configurable Sphinx theme" +category = "main" optional = true python-versions = ">=3.9" files = [ @@ -15,6 +16,7 @@ files = [ name = "alembic" version = "1.13.2" description = "A database migration tool for SQLAlchemy." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -34,6 +36,7 @@ tz = ["backports.zoneinfo"] name = "amqp" version = "5.2.0" description = "Low-level AMQP client for Python (fork of amqplib)." +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -48,6 +51,7 @@ vine = ">=5.0.0,<6.0.0" name = "annotated-types" version = "0.7.0" description = "Reusable constraint types to use with typing.Annotated" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -59,6 +63,7 @@ files = [ name = "anyio" version = "4.4.0" description = "High level compatibility layer for multiple asynchronous event loop implementations" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -81,6 +86,7 @@ trio = ["trio (>=0.23)"] name = "application-properties" version = "0.8.2" description = "A simple, easy to use, unified manner of accessing program properties." +category = "dev" optional = false python-versions = ">=3.8.0" files = [ @@ -97,6 +103,7 @@ typing-extensions = ">=4.5.0" name = "appnope" version = "0.1.4" description = "Disable App Nap on macOS >= 10.9" +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -108,6 +115,7 @@ files = [ name = "astroid" version = "2.15.8" description = "An abstract syntax tree for Python with inference support." +category = "dev" optional = false python-versions = ">=3.7.2" files = [ @@ -127,6 +135,7 @@ wrapt = [ name = "asttokens" version = "2.4.1" description = "Annotate AST trees with source code positions" +category = "dev" optional = false python-versions = "*" files = [ @@ -145,6 +154,7 @@ test = ["astroid (>=1,<2)", "astroid (>=2,<4)", "pytest"] name = "async-lru" version = "1.0.3" description = "Simple lru_cache for asyncio" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -156,6 +166,7 @@ files = [ name = "async-timeout" version = "4.0.3" description = "Timeout context manager for asyncio programs" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -167,6 +178,7 @@ files = [ name = "asyncpg" version = "0.27.0" description = "An asyncio PostgreSQL driver" +category = "main" optional = false python-versions = ">=3.7.0" files = [ @@ -217,6 +229,7 @@ test = ["flake8 (>=5.0.4,<5.1.0)", "uvloop (>=0.15.3)"] name = "attrs" version = "24.2.0" description = "Classes Without Boilerplate" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -236,6 +249,7 @@ tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] name = "authlib" version = "1.3.1" description = "The ultimate Python library in building OAuth and OpenID Connect servers and clients." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -250,6 +264,7 @@ cryptography = "*" name = "azure-core" version = "1.30.2" description = "Microsoft Azure Core Library for Python" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -269,6 +284,7 @@ aio = ["aiohttp (>=3.0)"] name = "azure-identity" version = "1.17.1" description = "Microsoft Azure Identity Library for Python" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -287,6 +303,7 @@ typing-extensions = ">=4.0.0" name = "babel" version = "2.15.0" description = "Internationalization utilities" +category = "main" optional = true python-versions = ">=3.8" files = [ @@ -301,6 +318,7 @@ dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] name = "billiard" version = "4.2.0" description = "Python multiprocessing fork with improvements and bugfixes" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -312,6 +330,7 @@ files = [ name = "black" version = "24.8.0" description = "The uncompromising code formatter." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -358,6 +377,7 @@ uvloop = ["uvloop (>=0.15.2)"] name = "cachetools" version = "5.4.0" description = "Extensible memoizing collections and decorators" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -369,6 +389,7 @@ files = [ name = "celery" version = "5.4.0" description = "Distributed Task Queue." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -425,6 +446,7 @@ zstd = ["zstandard (==0.22.0)"] name = "certifi" version = "2024.7.4" description = "Python package for providing Mozilla's CA Bundle." +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -436,6 +458,7 @@ files = [ name = "cffi" version = "1.16.0" description = "Foreign Function Interface for Python calling C code." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -500,6 +523,7 @@ pycparser = "*" name = "cfgv" version = "3.4.0" description = "Validate configuration and produce human readable error messages." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -511,6 +535,7 @@ files = [ name = "charset-normalizer" version = "3.3.2" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +category = "main" optional = false python-versions = ">=3.7.0" files = [ @@ -610,6 +635,7 @@ files = [ name = "click" version = "8.1.7" description = "Composable command line interface toolkit" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -624,6 +650,7 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} name = "click-didyoumean" version = "0.3.1" description = "Enables git-like *did-you-mean* feature in click" +category = "main" optional = false python-versions = ">=3.6.2" files = [ @@ -638,6 +665,7 @@ click = ">=7" name = "click-plugins" version = "1.1.1" description = "An extension module for click to enable registering CLI commands via setuptools entry-points." +category = "main" optional = false python-versions = "*" files = [ @@ -655,6 +683,7 @@ dev = ["coveralls", "pytest (>=3.6)", "pytest-cov", "wheel"] name = "click-repl" version = "0.3.0" description = "REPL plugin for Click" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -673,6 +702,7 @@ testing = ["pytest (>=7.2.1)", "pytest-cov (>=4.0.0)", "tox (>=4.4.3)"] name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." +category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ @@ -684,6 +714,7 @@ files = [ name = "columnar" version = "1.4.1" description = "A tool for printing data in a columnar format." +category = "dev" optional = false python-versions = "*" files = [ @@ -699,6 +730,7 @@ wcwidth = "*" name = "comm" version = "0.2.2" description = "Jupyter Python Comm implementation, for usage in ipykernel, xeus-python etc." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -716,6 +748,7 @@ test = ["pytest"] name = "coverage" version = "7.6.1" description = "Code coverage measurement for Python" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -800,6 +833,7 @@ toml = ["tomli"] name = "cryptography" version = "43.0.0" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -849,6 +883,7 @@ test-randomorder = ["pytest-randomly"] name = "databases" version = "0.7.0" description = "Async database support for Python." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -874,6 +909,7 @@ sqlite = ["aiosqlite"] name = "debugpy" version = "1.8.5" description = "An implementation of the Debug Adapter Protocol for Python" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -905,6 +941,7 @@ files = [ name = "decorator" version = "5.1.1" description = "Decorators for Humans" +category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -916,6 +953,7 @@ files = [ name = "defusedxml" version = "0.7.1" description = "XML bomb protection for Python stdlib modules" +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -927,6 +965,7 @@ files = [ name = "devtools" version = "0.8.0" description = "Python's missing debug print command and other development tools." +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -946,6 +985,7 @@ pygments = ["Pygments (>=2.2.0)"] name = "dill" version = "0.3.8" description = "serialize all of Python" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -961,6 +1001,7 @@ profile = ["gprof2dot (>=2022.7.29)"] name = "distlib" version = "0.3.8" description = "Distribution utilities" +category = "dev" optional = false python-versions = "*" files = [ @@ -972,6 +1013,7 @@ files = [ name = "dnspython" version = "2.6.1" description = "DNS toolkit" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -992,6 +1034,7 @@ wmi = ["wmi (>=1.5.1)"] name = "docutils" version = "0.18.1" description = "Docutils -- Python Documentation Utilities" +category = "main" optional = true python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -1003,6 +1046,7 @@ files = [ name = "dparse" version = "0.6.4b0" description = "A parser for Python dependency files" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1024,6 +1068,7 @@ poetry = ["poetry"] name = "ecdsa" version = "0.19.0" description = "ECDSA cryptographic signature library (pure python)" +category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.6" files = [ @@ -1042,6 +1087,7 @@ gmpy2 = ["gmpy2"] name = "email-validator" version = "2.2.0" description = "A robust email address syntax and deliverability validation library." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1057,6 +1103,7 @@ idna = ">=2.0.0" name = "exceptiongroup" version = "1.2.2" description = "Backport of PEP 654 (exception groups)" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1071,6 +1118,7 @@ test = ["pytest (>=6)"] name = "executing" version = "0.10.0" description = "Get the currently executing AST node of a frame, and other information" +category = "dev" optional = false python-versions = "*" files = [ @@ -1082,6 +1130,7 @@ files = [ name = "fastapi" version = "0.111.1" description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1107,6 +1156,7 @@ all = ["email_validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)" name = "fastapi-cli" version = "0.0.5" description = "Run and manage FastAPI apps from the command line with FastAPI CLI. 🚀" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1125,6 +1175,7 @@ standard = ["uvicorn[standard] (>=0.15.0)"] name = "fastapimsal" version = "0.6.0" description = "Library to authenticate users using MSAL" +category = "main" optional = false python-versions = "^3.10" files = [] @@ -1152,6 +1203,7 @@ resolved_reference = "5e063a695474359c14ac8f8e099fc8fc14556012" name = "filelock" version = "3.15.4" description = "A platform independent file lock." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -1168,6 +1220,7 @@ typing = ["typing-extensions (>=4.8)"] name = "flake8" version = "3.9.2" description = "the modular source code checker: pep8 pyflakes and co" +category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" files = [ @@ -1184,6 +1237,7 @@ pyflakes = ">=2.3.0,<2.4.0" name = "genbadge" version = "1.1.1" description = "Generate badges for tools that do not provide one." +category = "dev" optional = false python-versions = "*" files = [ @@ -1207,6 +1261,7 @@ tests = ["defusedxml"] name = "google-api-core" version = "2.19.1" description = "Google API client core library" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1230,6 +1285,7 @@ grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] name = "google-auth" version = "2.32.0" description = "Google Authentication Library" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1253,6 +1309,7 @@ requests = ["requests (>=2.20.0,<3.0.0.dev0)"] name = "googleapis-common-protos" version = "1.63.2" description = "Common protobufs used in Google APIs" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1270,6 +1327,7 @@ grpc = ["grpcio (>=1.44.0,<2.0.0.dev0)"] name = "greenlet" version = "3.0.3" description = "Lightweight in-process concurrent programming" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1341,6 +1399,7 @@ test = ["objgraph", "psutil"] name = "h11" version = "0.14.0" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1352,6 +1411,7 @@ files = [ name = "hiredis" version = "3.0.0" description = "Python wrapper for hiredis" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1455,6 +1515,7 @@ files = [ name = "httpcore" version = "0.16.3" description = "A minimal low-level HTTP client." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1466,16 +1527,17 @@ files = [ anyio = ">=3.0,<5.0" certifi = "*" h11 = ">=0.13,<0.15" -sniffio = "==1.*" +sniffio = ">=1.0.0,<2.0.0" [package.extras] http2 = ["h2 (>=3,<5)"] -socks = ["socksio (==1.*)"] +socks = ["socksio (>=1.0.0,<2.0.0)"] [[package]] name = "httpie" version = "3.2.1" description = "HTTPie: modern, user-friendly command-line HTTP client for the API era." +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1503,6 +1565,7 @@ test = ["pytest", "pytest-httpbin (>=0.0.6)", "pytest-lazy-fixture (>=0.0.6)", " name = "httpie-jwt-auth" version = "0.4.0" description = "JWTAuth plugin for HTTPie." +category = "dev" optional = false python-versions = "*" files = [ @@ -1517,6 +1580,7 @@ httpie = ">=1.0.0" name = "httptools" version = "0.6.1" description = "A collection of framework independent HTTP protocol utils." +category = "main" optional = false python-versions = ">=3.8.0" files = [ @@ -1565,6 +1629,7 @@ test = ["Cython (>=0.29.24,<0.30.0)"] name = "httpx" version = "0.23.3" description = "The next generation HTTP client." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1580,14 +1645,15 @@ sniffio = "*" [package.extras] brotli = ["brotli", "brotlicffi"] -cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<13)"] +cli = ["click (>=8.0.0,<9.0.0)", "pygments (>=2.0.0,<3.0.0)", "rich (>=10,<13)"] http2 = ["h2 (>=3,<5)"] -socks = ["socksio (==1.*)"] +socks = ["socksio (>=1.0.0,<2.0.0)"] [[package]] name = "hypothesis" version = "6.108.10" description = "A library for property-based testing" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -1621,6 +1687,7 @@ zoneinfo = ["backports.zoneinfo (>=0.2.1)", "tzdata (>=2024.1)"] name = "identify" version = "2.6.0" description = "File identification library for Python" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -1635,6 +1702,7 @@ license = ["ukkonen"] name = "idna" version = "3.7" description = "Internationalized Domain Names in Applications (IDNA)" +category = "main" optional = false python-versions = ">=3.5" files = [ @@ -1646,6 +1714,7 @@ files = [ name = "imagesize" version = "1.4.1" description = "Getting image size from png/jpeg/jpeg2000/gif file" +category = "main" optional = true python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -1657,6 +1726,7 @@ files = [ name = "iniconfig" version = "2.0.0" description = "brain-dead simple config-ini parsing" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1668,6 +1738,7 @@ files = [ name = "ipykernel" version = "6.29.5" description = "IPython Kernel for Jupyter" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -1681,7 +1752,7 @@ comm = ">=0.1.1" debugpy = ">=1.6.5" ipython = ">=7.23.1" jupyter-client = ">=6.1.12" -jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +jupyter-core = ">=4.12,<5.0.0 || >=5.1.0" matplotlib-inline = ">=0.1" nest-asyncio = "*" packaging = "*" @@ -1701,6 +1772,7 @@ test = ["flaky", "ipyparallel", "pre-commit", "pytest (>=7.0)", "pytest-asyncio name = "ipython" version = "8.26.0" description = "IPython: Productive Interactive Computing" +category = "dev" optional = false python-versions = ">=3.10" files = [ @@ -1739,6 +1811,7 @@ test-extra = ["curio", "ipython[test]", "matplotlib (!=3.2.0)", "nbformat", "num name = "isort" version = "5.13.2" description = "A Python utility / library to sort Python imports." +category = "dev" optional = false python-versions = ">=3.8.0" files = [ @@ -1753,6 +1826,7 @@ colors = ["colorama (>=0.4.6)"] name = "itsdangerous" version = "1.1.0" description = "Various helpers to pass data to untrusted environments and back." +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -1764,6 +1838,7 @@ files = [ name = "jedi" version = "0.19.1" description = "An autocompletion tool for Python that can be used for text editors." +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -1783,6 +1858,7 @@ testing = ["Django", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] name = "jinja2" version = "3.1.4" description = "A very fast and expressive template engine." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1800,6 +1876,7 @@ i18n = ["Babel (>=2.7)"] name = "jupyter-client" version = "8.6.2" description = "Jupyter protocol implementation and client libraries" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -1808,7 +1885,7 @@ files = [ ] [package.dependencies] -jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +jupyter-core = ">=4.12,<5.0.0 || >=5.1.0" python-dateutil = ">=2.8.2" pyzmq = ">=23.0" tornado = ">=6.2" @@ -1822,6 +1899,7 @@ test = ["coverage", "ipykernel (>=6.14)", "mypy", "paramiko", "pre-commit", "pyt name = "jupyter-core" version = "5.7.2" description = "Jupyter core package. A base package on which Jupyter projects rely." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -1842,6 +1920,7 @@ test = ["ipykernel", "pre-commit", "pytest (<8)", "pytest-cov", "pytest-timeout" name = "kombu" version = "5.4.0" description = "Messaging library for Python." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1874,6 +1953,7 @@ zookeeper = ["kazoo (>=2.8.0)"] name = "lazy-object-proxy" version = "1.10.0" description = "A fast and thorough lazy object proxy." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -1920,6 +2000,7 @@ files = [ name = "mako" version = "1.3.5" description = "A super-fast templating language that borrows the best ideas from the existing templating languages." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1939,6 +2020,7 @@ testing = ["pytest"] name = "markdown-it-py" version = "3.0.0" description = "Python port of markdown-it. Markdown parsing, done right!" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1963,6 +2045,7 @@ testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] name = "markupsafe" version = "2.1.5" description = "Safely add untrusted strings to HTML/XML markup." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2032,6 +2115,7 @@ files = [ name = "marshmallow" version = "3.21.3" description = "A lightweight library for converting complex datatypes to and from native Python datatypes." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -2051,6 +2135,7 @@ tests = ["pytest", "pytz", "simplejson"] name = "matplotlib-inline" version = "0.1.7" description = "Inline Matplotlib backend for Jupyter" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -2065,6 +2150,7 @@ traitlets = "*" name = "mccabe" version = "0.6.1" description = "McCabe checker, plugin for flake8" +category = "dev" optional = false python-versions = "*" files = [ @@ -2076,6 +2162,7 @@ files = [ name = "mdit-py-plugins" version = "0.4.1" description = "Collection of plugins for markdown-it-py" +category = "main" optional = true python-versions = ">=3.8" files = [ @@ -2095,6 +2182,7 @@ testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] name = "mdurl" version = "0.1.2" description = "Markdown URL utilities" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2106,6 +2194,7 @@ files = [ name = "msal" version = "1.30.0" description = "The Microsoft Authentication Library (MSAL) for Python library enables your app to access the Microsoft Cloud by supporting authentication of users with Microsoft Azure Active Directory accounts (AAD) and Microsoft Accounts (MSA) using industry standard OAuth2 and OpenID Connect." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2125,6 +2214,7 @@ broker = ["pymsalruntime (>=0.13.2,<0.17)"] name = "msal-extensions" version = "1.2.0" description = "Microsoft Authentication Library extensions (MSAL EX) provides a persistence API that can save your data on disk, encrypted on Windows, macOS and Linux. Concurrent data access will be coordinated by a file lock mechanism." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2140,6 +2230,7 @@ portalocker = ">=1.4,<3" name = "multidict" version = "6.0.5" description = "multidict implementation" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2239,6 +2330,7 @@ files = [ name = "mypy" version = "1.11.1" description = "Optional static typing for Python" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -2286,6 +2378,7 @@ reports = ["lxml"] name = "mypy-extensions" version = "1.0.0" description = "Type system extensions for programs checked with the mypy type checker." +category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -2297,6 +2390,7 @@ files = [ name = "myst-parser" version = "3.0.1" description = "An extended [CommonMark](https://spec.commonmark.org/) compliant parser," +category = "main" optional = true python-versions = ">=3.8" files = [ @@ -2323,6 +2417,7 @@ testing-docutils = ["pygments", "pytest (>=8,<9)", "pytest-param-files (>=0.6.0, name = "nest-asyncio" version = "1.6.0" description = "Patch asyncio to allow nested event loops" +category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -2334,6 +2429,7 @@ files = [ name = "nodeenv" version = "1.9.1" description = "Node.js virtual environment builder" +category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ @@ -2345,6 +2441,7 @@ files = [ name = "numpy" version = "1.26.4" description = "Fundamental package for array computing in Python" +category = "main" optional = false python-versions = ">=3.9" files = [ @@ -2390,6 +2487,7 @@ files = [ name = "opencensus" version = "0.11.4" description = "A stats collection and distributed tracing framework" +category = "main" optional = false python-versions = "*" files = [ @@ -2406,6 +2504,7 @@ six = ">=1.16,<2.0" name = "opencensus-context" version = "0.1.3" description = "OpenCensus Runtime Context" +category = "main" optional = false python-versions = "*" files = [ @@ -2417,6 +2516,7 @@ files = [ name = "opencensus-ext-azure" version = "1.1.13" description = "OpenCensus Azure Monitor Exporter" +category = "main" optional = false python-versions = "*" files = [ @@ -2435,6 +2535,7 @@ requests = ">=2.19.0" name = "packaging" version = "24.1" description = "Core utilities for Python packages" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2446,6 +2547,7 @@ files = [ name = "pandas" version = "1.5.3" description = "Powerful data structures for data analysis, time series, and statistics" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2480,7 +2582,7 @@ files = [ [package.dependencies] numpy = [ - {version = ">=1.21.0", markers = "python_version >= \"3.10\" and python_version < \"3.11\""}, + {version = ">=1.21.0", markers = "python_version >= \"3.10\""}, {version = ">=1.23.2", markers = "python_version >= \"3.11\""}, ] python-dateutil = ">=2.8.1" @@ -2493,6 +2595,7 @@ test = ["hypothesis (>=5.5.3)", "pytest (>=6.0)", "pytest-xdist (>=1.31)"] name = "parso" version = "0.8.4" description = "A Python Parser" +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -2508,6 +2611,7 @@ testing = ["docopt", "pytest"] name = "pathspec" version = "0.12.1" description = "Utility library for gitignore style pattern matching of file paths." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -2519,6 +2623,7 @@ files = [ name = "pexpect" version = "4.9.0" description = "Pexpect allows easy control of interactive console applications." +category = "dev" optional = false python-versions = "*" files = [ @@ -2533,6 +2638,7 @@ ptyprocess = ">=0.5" name = "pillow" version = "10.4.0" description = "Python Imaging Library (Fork)" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -2630,6 +2736,7 @@ xmp = ["defusedxml"] name = "pip" version = "24.2" description = "The PyPA recommended tool for installing Python packages." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -2641,6 +2748,7 @@ files = [ name = "platformdirs" version = "4.2.2" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -2657,6 +2765,7 @@ type = ["mypy (>=1.8)"] name = "plotly" version = "5.23.0" description = "An open-source, interactive data visualization library for Python" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2672,6 +2781,7 @@ tenacity = ">=6.2.0" name = "pluggy" version = "1.5.0" description = "plugin and hook calling mechanisms for python" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -2687,6 +2797,7 @@ testing = ["pytest", "pytest-benchmark"] name = "pockets" version = "0.9.1" description = "A collection of helpful Python tools!" +category = "main" optional = true python-versions = "*" files = [ @@ -2701,6 +2812,7 @@ six = ">=1.5.2" name = "portalocker" version = "2.10.1" description = "Wraps the portalocker recipe for easy usage" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2720,6 +2832,7 @@ tests = ["pytest (>=5.4.1)", "pytest-cov (>=2.8.1)", "pytest-mypy (>=0.8.0)", "p name = "pre-commit" version = "2.21.0" description = "A framework for managing and maintaining multi-language pre-commit hooks." +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2738,6 +2851,7 @@ virtualenv = ">=20.10.0" name = "prompt-toolkit" version = "3.0.47" description = "Library for building powerful interactive command lines in Python" +category = "main" optional = false python-versions = ">=3.7.0" files = [ @@ -2752,6 +2866,7 @@ wcwidth = "*" name = "proto-plus" version = "1.24.0" description = "Beautiful, Pythonic protocol buffers." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2769,6 +2884,7 @@ testing = ["google-api-core (>=1.31.5)"] name = "protobuf" version = "5.27.3" description = "" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2789,6 +2905,7 @@ files = [ name = "psutil" version = "6.0.0" description = "Cross-platform lib for process and system monitoring in Python." +category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" files = [ @@ -2818,6 +2935,7 @@ test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"] name = "psycopg2-binary" version = "2.9.9" description = "psycopg2 - Python-PostgreSQL Database Adapter" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2847,6 +2965,7 @@ files = [ {file = "psycopg2_binary-2.9.9-cp311-cp311-win32.whl", hash = "sha256:dc4926288b2a3e9fd7b50dc6a1909a13bbdadfc67d93f3374d984e56f885579d"}, {file = "psycopg2_binary-2.9.9-cp311-cp311-win_amd64.whl", hash = "sha256:b76bedd166805480ab069612119ea636f5ab8f8771e640ae103e05a4aae3e417"}, {file = "psycopg2_binary-2.9.9-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:8532fd6e6e2dc57bcb3bc90b079c60de896d2128c5d9d6f24a63875a95a088cf"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b0605eaed3eb239e87df0d5e3c6489daae3f7388d455d0c0b4df899519c6a38d"}, {file = "psycopg2_binary-2.9.9-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f8544b092a29a6ddd72f3556a9fcf249ec412e10ad28be6a0c0d948924f2212"}, {file = "psycopg2_binary-2.9.9-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2d423c8d8a3c82d08fe8af900ad5b613ce3632a1249fd6a223941d0735fce493"}, {file = "psycopg2_binary-2.9.9-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e5afae772c00980525f6d6ecf7cbca55676296b580c0e6abb407f15f3706996"}, @@ -2855,6 +2974,8 @@ files = [ {file = "psycopg2_binary-2.9.9-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:cb16c65dcb648d0a43a2521f2f0a2300f40639f6f8c1ecbc662141e4e3e1ee07"}, {file = "psycopg2_binary-2.9.9-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:911dda9c487075abd54e644ccdf5e5c16773470a6a5d3826fda76699410066fb"}, {file = "psycopg2_binary-2.9.9-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:57fede879f08d23c85140a360c6a77709113efd1c993923c59fde17aa27599fe"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-win32.whl", hash = "sha256:64cf30263844fa208851ebb13b0732ce674d8ec6a0c86a4e160495d299ba3c93"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-win_amd64.whl", hash = "sha256:81ff62668af011f9a48787564ab7eded4e9fb17a4a6a74af5ffa6a457400d2ab"}, {file = "psycopg2_binary-2.9.9-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2293b001e319ab0d869d660a704942c9e2cce19745262a8aba2115ef41a0a42a"}, {file = "psycopg2_binary-2.9.9-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:03ef7df18daf2c4c07e2695e8cfd5ee7f748a1d54d802330985a78d2a5a6dca9"}, {file = "psycopg2_binary-2.9.9-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a602ea5aff39bb9fac6308e9c9d82b9a35c2bf288e184a816002c9fae930b77"}, @@ -2896,6 +3017,7 @@ files = [ name = "ptyprocess" version = "0.7.0" description = "Run a subprocess in a pseudo terminal" +category = "dev" optional = false python-versions = "*" files = [ @@ -2907,6 +3029,7 @@ files = [ name = "pure-eval" version = "0.2.3" description = "Safely evaluate AST nodes without side effects" +category = "dev" optional = false python-versions = "*" files = [ @@ -2921,6 +3044,7 @@ tests = ["pytest"] name = "pyasn1" version = "0.6.0" description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2932,6 +3056,7 @@ files = [ name = "pyasn1-modules" version = "0.4.0" description = "A collection of ASN.1-based protocols modules" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2946,6 +3071,7 @@ pyasn1 = ">=0.4.6,<0.7.0" name = "pycodestyle" version = "2.7.0" description = "Python style guide checker" +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -2957,6 +3083,7 @@ files = [ name = "pycparser" version = "2.22" description = "C parser in Python" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2968,6 +3095,7 @@ files = [ name = "pydantic" version = "2.8.2" description = "Data validation using Python type hints" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2988,6 +3116,7 @@ email = ["email-validator (>=2.0.0)"] name = "pydantic-core" version = "2.20.1" description = "Core functionality for Pydantic validation and serialization" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -3089,6 +3218,7 @@ typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" name = "pydantic-settings" version = "2.4.0" description = "Settings management using Pydantic" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -3109,6 +3239,7 @@ yaml = ["pyyaml (>=6.0.1)"] name = "pydocstyle" version = "6.3.0" description = "Python docstring style checker" +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -3126,6 +3257,7 @@ toml = ["tomli (>=1.2.3)"] name = "pyflakes" version = "2.3.1" description = "passive checker of Python programs" +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -3137,6 +3269,7 @@ files = [ name = "pygments" version = "2.18.0" description = "Pygments is a syntax highlighting package written in Python." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -3151,6 +3284,7 @@ windows-terminal = ["colorama (>=0.4.6)"] name = "pyjwt" version = "2.9.0" description = "JSON Web Token implementation in Python" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -3171,6 +3305,7 @@ tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] name = "pylint" version = "2.17.7" description = "python code static checker" +category = "dev" optional = false python-versions = ">=3.7.2" files = [ @@ -3199,6 +3334,7 @@ testutils = ["gitpython (>3)"] name = "pylint-absolute-imports" version = "1.1.0" description = "Pylint plugin which adds linter error for relatives imports.Read more about imports at https://peps.python.org/pep-0008/#imports" +category = "dev" optional = false python-versions = "*" files = [ @@ -3213,6 +3349,7 @@ pylint = ">=2.5.0,<4" name = "pymarkdownlnt" version = "0.9.22" description = "A GitHub Flavored Markdown compliant Markdown linter." +category = "dev" optional = false python-versions = ">=3.8.0" files = [ @@ -3229,6 +3366,7 @@ typing-extensions = ">=4.7.0" name = "pysocks" version = "1.7.1" description = "A Python SOCKS client module. See https://github.com/Anorov/PySocks for more information." +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -3241,6 +3379,7 @@ files = [ name = "pytest" version = "7.4.4" description = "pytest: simple powerful testing with Python" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -3263,6 +3402,7 @@ testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "no name = "pytest-asyncio" version = "0.14.0" description = "Pytest support for asyncio." +category = "dev" optional = false python-versions = ">= 3.5" files = [ @@ -3280,6 +3420,7 @@ testing = ["async-generator (>=1.3)", "coverage", "hypothesis (>=5.7.1)"] name = "pytest-cov" version = "2.12.1" description = "Pytest plugin for measuring coverage." +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -3299,6 +3440,7 @@ testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtuale name = "pytest-mock" version = "3.14.0" description = "Thin-wrapper around the mock package for easier use with pytest" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -3316,6 +3458,7 @@ dev = ["pre-commit", "pytest-asyncio", "tox"] name = "python-dateutil" version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" +category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" files = [ @@ -3330,6 +3473,7 @@ six = ">=1.5" name = "python-dotenv" version = "1.0.1" description = "Read key-value pairs from a .env file and set them as environment variables" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -3344,6 +3488,7 @@ cli = ["click (>=5.0)"] name = "python-http-client" version = "3.3.7" description = "HTTP REST client, simplified for Python" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -3355,6 +3500,7 @@ files = [ name = "python-jose" version = "3.3.0" description = "JOSE implementation in Python" +category = "main" optional = false python-versions = "*" files = [ @@ -3377,6 +3523,7 @@ pycryptodome = ["pyasn1", "pycryptodome (>=3.3.1,<4.0.0)"] name = "python-multipart" version = "0.0.9" description = "A streaming multipart parser for Python" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -3391,6 +3538,7 @@ dev = ["atomicwrites (==1.4.1)", "attrs (==23.2.0)", "coverage (==7.4.1)", "hatc name = "pytz" version = "2024.1" description = "World timezone definitions, modern and historical" +category = "main" optional = false python-versions = "*" files = [ @@ -3402,6 +3550,7 @@ files = [ name = "pywin32" version = "306" description = "Python for Window Extensions" +category = "main" optional = false python-versions = "*" files = [ @@ -3425,6 +3574,7 @@ files = [ name = "pyyaml" version = "6.0.1" description = "YAML parser and emitter for Python" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -3433,6 +3583,7 @@ files = [ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, @@ -3440,8 +3591,15 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, @@ -3458,6 +3616,7 @@ files = [ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, @@ -3465,6 +3624,7 @@ files = [ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, @@ -3474,6 +3634,7 @@ files = [ name = "pyzmq" version = "26.1.0" description = "Python bindings for 0MQ" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -3595,6 +3756,7 @@ cffi = {version = "*", markers = "implementation_name == \"pypy\""} name = "rctab-models" version = "0.1.0" description = "" +category = "main" optional = false python-versions = "^3.9" files = [] @@ -3604,15 +3766,14 @@ develop = false pydantic = "^2.8.2" [package.source] -type = "git" -url = "https://github.com/alan-turing-institute/rctab-models" -reference = "0.1.0" -resolved_reference = "2011fc718bbcc55c90fa9f86ae465f38c6ba9861" +type = "directory" +url = "../rctab-models" [[package]] name = "redis" version = "5.0.8" description = "Python client for Redis database and key-value store" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3632,6 +3793,7 @@ ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==20.0.1)", "requests (>=2.26.0)" name = "requests" version = "2.32.3" description = "Python HTTP for Humans." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -3654,6 +3816,7 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] name = "requests-toolbelt" version = "1.0.0" description = "A utility belt for advanced users of python-requests" +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -3668,6 +3831,7 @@ requests = ">=2.0.1,<3.0.0" name = "rfc3986" version = "1.5.0" description = "Validating URI References per RFC 3986" +category = "main" optional = false python-versions = "*" files = [ @@ -3685,6 +3849,7 @@ idna2008 = ["idna"] name = "rich" version = "13.7.1" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" +category = "main" optional = false python-versions = ">=3.7.0" files = [ @@ -3703,6 +3868,7 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] name = "rsa" version = "4.9" description = "Pure-Python RSA implementation" +category = "main" optional = false python-versions = ">=3.6,<4" files = [ @@ -3717,6 +3883,7 @@ pyasn1 = ">=0.1.3" name = "ruamel-yaml" version = "0.18.6" description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -3735,42 +3902,57 @@ jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"] name = "ruamel-yaml-clib" version = "0.2.8" description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml" +category = "dev" optional = false python-versions = ">=3.6" files = [ {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b42169467c42b692c19cf539c38d4602069d8c1505e97b86387fcf7afb766e1d"}, {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-macosx_13_0_arm64.whl", hash = "sha256:07238db9cbdf8fc1e9de2489a4f68474e70dffcb32232db7c08fa61ca0c7c462"}, - {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:d92f81886165cb14d7b067ef37e142256f1c6a90a65cd156b063a43da1708cfd"}, {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:fff3573c2db359f091e1589c3d7c5fc2f86f5bdb6f24252c2d8e539d4e45f412"}, + {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:aa2267c6a303eb483de8d02db2871afb5c5fc15618d894300b88958f729ad74f"}, + {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:840f0c7f194986a63d2c2465ca63af8ccbbc90ab1c6001b1978f05119b5e7334"}, + {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:024cfe1fc7c7f4e1aff4a81e718109e13409767e4f871443cbff3dba3578203d"}, {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-win32.whl", hash = "sha256:c69212f63169ec1cfc9bb44723bf2917cbbd8f6191a00ef3410f5a7fe300722d"}, {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-win_amd64.whl", hash = "sha256:cabddb8d8ead485e255fe80429f833172b4cadf99274db39abc080e068cbcc31"}, {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:bef08cd86169d9eafb3ccb0a39edb11d8e25f3dae2b28f5c52fd997521133069"}, {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:b16420e621d26fdfa949a8b4b47ade8810c56002f5389970db4ddda51dbff248"}, - {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:b5edda50e5e9e15e54a6a8a0070302b00c518a9d32accc2346ad6c984aacd279"}, {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:25c515e350e5b739842fc3228d662413ef28f295791af5e5110b543cf0b57d9b"}, + {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-manylinux_2_24_aarch64.whl", hash = "sha256:1707814f0d9791df063f8c19bb51b0d1278b8e9a2353abbb676c2f685dee6afe"}, + {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:46d378daaac94f454b3a0e3d8d78cafd78a026b1d71443f4966c696b48a6d899"}, + {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:09b055c05697b38ecacb7ac50bdab2240bfca1a0c4872b0fd309bb07dc9aa3a9"}, {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-win32.whl", hash = "sha256:53a300ed9cea38cf5a2a9b069058137c2ca1ce658a874b79baceb8f892f915a7"}, {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-win_amd64.whl", hash = "sha256:c2a72e9109ea74e511e29032f3b670835f8a59bbdc9ce692c5b4ed91ccf1eedb"}, {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:ebc06178e8821efc9692ea7544aa5644217358490145629914d8020042c24aa1"}, {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-macosx_13_0_arm64.whl", hash = "sha256:edaef1c1200c4b4cb914583150dcaa3bc30e592e907c01117c08b13a07255ec2"}, - {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-manylinux2014_aarch64.whl", hash = "sha256:7048c338b6c86627afb27faecf418768acb6331fc24cfa56c93e8c9780f815fa"}, {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d176b57452ab5b7028ac47e7b3cf644bcfdc8cacfecf7e71759f7f51a59e5c92"}, + {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-manylinux_2_24_aarch64.whl", hash = "sha256:1dc67314e7e1086c9fdf2680b7b6c2be1c0d8e3a8279f2e993ca2a7545fecf62"}, + {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3213ece08ea033eb159ac52ae052a4899b56ecc124bb80020d9bbceeb50258e9"}, + {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:aab7fd643f71d7946f2ee58cc88c9b7bfc97debd71dcc93e03e2d174628e7e2d"}, + {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-win32.whl", hash = "sha256:5c365d91c88390c8d0a8545df0b5857172824b1c604e867161e6b3d59a827eaa"}, + {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-win_amd64.whl", hash = "sha256:1758ce7d8e1a29d23de54a16ae867abd370f01b5a69e1a3ba75223eaa3ca1a1b"}, {file = "ruamel.yaml.clib-0.2.8-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a5aa27bad2bb83670b71683aae140a1f52b0857a2deff56ad3f6c13a017a26ed"}, {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c58ecd827313af6864893e7af0a3bb85fd529f862b6adbefe14643947cfe2942"}, {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-macosx_12_0_arm64.whl", hash = "sha256:f481f16baec5290e45aebdc2a5168ebc6d35189ae6fea7a58787613a25f6e875"}, - {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:3fcc54cb0c8b811ff66082de1680b4b14cf8a81dce0d4fbf665c2265a81e07a1"}, + {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-manylinux_2_24_aarch64.whl", hash = "sha256:77159f5d5b5c14f7c34073862a6b7d34944075d9f93e681638f6d753606c6ce6"}, {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:7f67a1ee819dc4562d444bbafb135832b0b909f81cc90f7aa00260968c9ca1b3"}, + {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4ecbf9c3e19f9562c7fdd462e8d18dd902a47ca046a2e64dba80699f0b6c09b7"}, + {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:87ea5ff66d8064301a154b3933ae406b0863402a799b16e4a1d24d9fbbcbe0d3"}, {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-win32.whl", hash = "sha256:75e1ed13e1f9de23c5607fe6bd1aeaae21e523b32d83bb33918245361e9cc51b"}, {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-win_amd64.whl", hash = "sha256:3f215c5daf6a9d7bbed4a0a4f760f3113b10e82ff4c5c44bec20a68c8014f675"}, {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1b617618914cb00bf5c34d4357c37aa15183fa229b24767259657746c9077615"}, {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:a6a9ffd280b71ad062eae53ac1659ad86a17f59a0fdc7699fd9be40525153337"}, - {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:665f58bfd29b167039f714c6998178d27ccd83984084c286110ef26b230f259f"}, + {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-manylinux_2_24_aarch64.whl", hash = "sha256:305889baa4043a09e5b76f8e2a51d4ffba44259f6b4c72dec8ca56207d9c6fe1"}, {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:700e4ebb569e59e16a976857c8798aee258dceac7c7d6b50cab63e080058df91"}, + {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:e2b4c44b60eadec492926a7270abb100ef9f72798e18743939bdbf037aab8c28"}, + {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e79e5db08739731b0ce4850bed599235d601701d5694c36570a99a0c5ca41a9d"}, {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-win32.whl", hash = "sha256:955eae71ac26c1ab35924203fda6220f84dce57d6d7884f189743e2abe3a9fbe"}, {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-win_amd64.whl", hash = "sha256:56f4252222c067b4ce51ae12cbac231bce32aee1d33fbfc9d17e5b8d6966c312"}, {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:03d1162b6d1df1caa3a4bd27aa51ce17c9afc2046c31b0ad60a0a96ec22f8001"}, {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:bba64af9fa9cebe325a62fa398760f5c7206b215201b0ec825005f1b18b9bccf"}, - {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:9eb5dee2772b0f704ca2e45b1713e4e5198c18f515b52743576d196348f374d3"}, + {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-manylinux_2_24_aarch64.whl", hash = "sha256:a1a45e0bb052edf6a1d3a93baef85319733a888363938e1fc9924cb00c8df24c"}, {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:da09ad1c359a728e112d60116f626cc9f29730ff3e0e7db72b9a2dbc2e4beed5"}, + {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:184565012b60405d93838167f425713180b949e9d8dd0bbc7b49f074407c5a8b"}, + {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a75879bacf2c987c003368cf14bed0ffe99e8e85acfa6c0bfffc21a090f16880"}, {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-win32.whl", hash = "sha256:84b554931e932c46f94ab306913ad7e11bba988104c5cff26d90d03f68258cd5"}, {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-win_amd64.whl", hash = "sha256:25ac8c08322002b06fa1d49d1646181f0b2c72f5cbc15a85e80b4c30a544bb15"}, {file = "ruamel.yaml.clib-0.2.8.tar.gz", hash = "sha256:beb2e0404003de9a4cab9753a8805a8fe9320ee6673136ed7f04255fe60bb512"}, @@ -3780,6 +3962,7 @@ files = [ name = "safety" version = "3.2.3" description = "Checks installed dependencies for known vulnerabilities and licenses." +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -3813,6 +3996,7 @@ spdx = ["spdx-tools (>=0.8.2)"] name = "safety-schemas" version = "0.0.2" description = "Schemas for Safety tools" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -3831,6 +4015,7 @@ typing-extensions = ">=4.7.1" name = "secure" version = "0.3.0" description = "A lightweight package that adds security headers for Python web frameworks." +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -3842,6 +4027,7 @@ files = [ name = "sendgrid" version = "6.11.0" description = "Twilio SendGrid library for Python" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -3857,6 +4043,7 @@ starkbank-ecdsa = ">=2.0.1" name = "setuptools" version = "72.1.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -3867,12 +4054,13 @@ files = [ [package.extras] core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.text (>=3.7)", "more-itertools (>=8.8)", "ordered-set (>=3.1.1)", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] 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"] -test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "mypy (==1.11.*)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (<0.4)", "pytest-ruff (>=0.2.1)", "pytest-ruff (>=0.3.2)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "mypy (>=1.11.0,<1.12.0)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (<0.4)", "pytest-ruff (>=0.2.1)", "pytest-ruff (>=0.3.2)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] [[package]] name = "shellingham" version = "1.5.4" description = "Tool to Detect Surrounding Shell" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3884,6 +4072,7 @@ files = [ name = "six" version = "1.16.0" description = "Python 2 and 3 compatibility utilities" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -3895,6 +4084,7 @@ files = [ name = "sniffio" version = "1.3.1" description = "Sniff out which async library your code is running under" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3906,6 +4096,7 @@ files = [ name = "snowballstemmer" version = "2.2.0" description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." +category = "main" optional = false python-versions = "*" files = [ @@ -3917,6 +4108,7 @@ files = [ name = "sortedcontainers" version = "2.4.0" description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" +category = "dev" optional = false python-versions = "*" files = [ @@ -3928,6 +4120,7 @@ files = [ name = "sphinx" version = "7.3.7" description = "Python documentation generator" +category = "main" optional = true python-versions = ">=3.9" files = [ @@ -3963,6 +4156,7 @@ test = ["cython (>=3.0)", "defusedxml (>=0.7.1)", "pytest (>=6.0)", "setuptools name = "sphinx-rtd-theme" version = "1.3.0" description = "Read the Docs theme for Sphinx" +category = "main" optional = true python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" files = [ @@ -3982,6 +4176,7 @@ dev = ["bump2version", "sphinxcontrib-httpdomain", "transifex-client", "wheel"] name = "sphinxcontrib-applehelp" version = "2.0.0" description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" +category = "main" optional = true python-versions = ">=3.9" files = [ @@ -3998,6 +4193,7 @@ test = ["pytest"] name = "sphinxcontrib-devhelp" version = "2.0.0" description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp documents" +category = "main" optional = true python-versions = ">=3.9" files = [ @@ -4014,6 +4210,7 @@ test = ["pytest"] name = "sphinxcontrib-htmlhelp" version = "2.1.0" description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" +category = "main" optional = true python-versions = ">=3.9" files = [ @@ -4030,6 +4227,7 @@ test = ["html5lib", "pytest"] name = "sphinxcontrib-jquery" version = "4.1" description = "Extension to include jQuery on newer Sphinx releases" +category = "main" optional = true python-versions = ">=2.7" files = [ @@ -4044,6 +4242,7 @@ Sphinx = ">=1.8" name = "sphinxcontrib-jsmath" version = "1.0.1" description = "A sphinx extension which renders display math in HTML via JavaScript" +category = "main" optional = true python-versions = ">=3.5" files = [ @@ -4058,6 +4257,7 @@ test = ["flake8", "mypy", "pytest"] name = "sphinxcontrib-napoleon" version = "0.7" description = "Sphinx \"napoleon\" extension." +category = "main" optional = true python-versions = "*" files = [ @@ -4073,6 +4273,7 @@ six = ">=1.5.2" name = "sphinxcontrib-qthelp" version = "2.0.0" description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp documents" +category = "main" optional = true python-versions = ">=3.9" files = [ @@ -4089,6 +4290,7 @@ test = ["defusedxml (>=0.7.1)", "pytest"] name = "sphinxcontrib-serializinghtml" version = "2.0.0" description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)" +category = "main" optional = true python-versions = ">=3.9" files = [ @@ -4105,6 +4307,7 @@ test = ["pytest"] name = "sqlalchemy" version = "1.4.53" description = "Database Abstraction Library" +category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" files = [ @@ -4182,6 +4385,7 @@ sqlcipher = ["sqlcipher3_binary"] name = "sqlalchemy-stubs" version = "0.3" description = "SQLAlchemy stubs and mypy plugin" +category = "dev" optional = false python-versions = "*" files = [ @@ -4197,6 +4401,7 @@ typing-extensions = ">=3.7.4" name = "stack-data" version = "0.5.1" description = "Extract data from python stack frames and tracebacks for informative displays" +category = "dev" optional = false python-versions = "*" files = [ @@ -4216,6 +4421,7 @@ tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"] name = "starkbank-ecdsa" version = "2.2.0" description = "A lightweight and fast pure python ECDSA library" +category = "main" optional = false python-versions = "*" files = [ @@ -4226,6 +4432,7 @@ files = [ name = "starlette" version = "0.37.2" description = "The little ASGI library that shines." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -4243,6 +4450,7 @@ full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.7 name = "tenacity" version = "9.0.0" description = "Retry code until it succeeds" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -4258,6 +4466,7 @@ test = ["pytest", "tornado (>=4.5)", "typeguard"] name = "toml" version = "0.10.2" description = "Python Library for Tom's Obvious, Minimal Language" +category = "dev" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -4269,6 +4478,7 @@ files = [ name = "tomli" version = "2.0.1" description = "A lil' TOML parser" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -4280,6 +4490,7 @@ files = [ name = "tomlkit" version = "0.13.0" description = "Style preserving TOML library" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -4291,6 +4502,7 @@ files = [ name = "toolz" version = "0.12.1" description = "List processing tools and functional utilities" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -4302,6 +4514,7 @@ files = [ name = "tornado" version = "6.4.1" description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -4322,6 +4535,7 @@ files = [ name = "traitlets" version = "5.14.3" description = "Traitlets Python configuration system" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -4337,6 +4551,7 @@ test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0, name = "typer" version = "0.12.3" description = "Typer, build great CLIs. Easy to code. Based on Python type hints." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -4354,6 +4569,7 @@ typing-extensions = ">=3.7.4.3" name = "types-requests" version = "2.32.0.20240712" description = "Typing stubs for requests" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -4368,6 +4584,7 @@ urllib3 = ">=2" name = "typing-extensions" version = "4.12.2" description = "Backported and Experimental Type Hints for Python 3.8+" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -4379,6 +4596,7 @@ files = [ name = "tzdata" version = "2024.1" description = "Provider of IANA time zone data" +category = "main" optional = false python-versions = ">=2" files = [ @@ -4390,6 +4608,7 @@ files = [ name = "urllib3" version = "2.2.2" description = "HTTP library with thread-safe connection pooling, file post, and more." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -4407,6 +4626,7 @@ zstd = ["zstandard (>=0.18.0)"] name = "uvicorn" version = "0.30.5" description = "The lightning-fast ASGI server." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -4422,7 +4642,7 @@ httptools = {version = ">=0.5.0", optional = true, markers = "extra == \"standar python-dotenv = {version = ">=0.13", optional = true, markers = "extra == \"standard\""} pyyaml = {version = ">=5.1", optional = true, markers = "extra == \"standard\""} typing-extensions = {version = ">=4.0", markers = "python_version < \"3.11\""} -uvloop = {version = ">=0.14.0,<0.15.0 || >0.15.0,<0.15.1 || >0.15.1", optional = true, markers = "(sys_platform != \"win32\" and sys_platform != \"cygwin\") and platform_python_implementation != \"PyPy\" and extra == \"standard\""} +uvloop = {version = ">=0.14.0,<0.15.0 || >0.15.0,<0.15.1 || >0.15.1", optional = true, markers = "sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\" and extra == \"standard\""} watchfiles = {version = ">=0.13", optional = true, markers = "extra == \"standard\""} websockets = {version = ">=10.4", optional = true, markers = "extra == \"standard\""} @@ -4433,6 +4653,7 @@ standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", name = "uvloop" version = "0.19.0" description = "Fast implementation of asyncio event loop on top of libuv" +category = "main" optional = false python-versions = ">=3.8.0" files = [ @@ -4477,6 +4698,7 @@ test = ["Cython (>=0.29.36,<0.30.0)", "aiohttp (==3.9.0b0)", "aiohttp (>=3.8.1)" name = "vine" version = "5.1.0" description = "Python promises." +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -4488,6 +4710,7 @@ files = [ name = "virtualenv" version = "20.26.3" description = "Virtual Python Environment builder" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -4508,6 +4731,7 @@ test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess name = "watchfiles" version = "0.22.0" description = "Simple, modern and high performance file watching and code reload in python." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -4595,6 +4819,7 @@ anyio = ">=3.0.0" name = "wcwidth" version = "0.2.13" description = "Measures the displayed width of unicode strings in a terminal" +category = "main" optional = false python-versions = "*" files = [ @@ -4606,6 +4831,7 @@ files = [ name = "websockets" version = "12.0" description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -4687,6 +4913,7 @@ files = [ name = "wrapt" version = "1.16.0" description = "Module for decorators, wrappers and monkey patching." +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -4763,9 +4990,9 @@ files = [ ] [extras] -docs = ["myst-parser", "sphinx-rtd-theme", "sphinxcontrib-napoleon"] +docs = ["sphinx-rtd-theme", "sphinxcontrib-napoleon", "myst-parser"] [metadata] lock-version = "2.0" python-versions = ">=3.10 <3.12" -content-hash = "be0af3dc93c7a9b9f58276ceef027d7db482dc6b338244ab9247888deb6b7f72" +content-hash = "1408205cac647397f7ec26aeda07bfd46bcddb1846bde818198565f352ea37f6" diff --git a/pyproject.toml b/pyproject.toml index 2ec7de5..a004a1d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,7 +25,6 @@ pydantic = { extras = ["email"], version = "^2.7.1" } pydantic-settings = "^2.3.4" PyJWT = { extras = ["crypto"], version = "^2.4.0" } python-dotenv = "^1.0.1" -rctab_models = { git = "https://github.com/alan-turing-institute/rctab-models", tag = "0.1.0" } redis = {extras = ["hiredis"], version = "^5.0.1"} requests = "^2.32.3" sendgrid = "^6.9.1" @@ -35,6 +34,7 @@ sphinx-rtd-theme = {version = "^1.3.0", optional = true} sphinxcontrib-napoleon = {version = "^0.7", optional = true} secure = "^0.3.0" uvicorn = { version = "^0.30.1", extras = ["standard"] } +rctab-models = {path = "../rctab-models"} [tool.poetry.group.dev.dependencies] black = "^24.3.0" diff --git a/rctab/routers/accounting/usage.py b/rctab/routers/accounting/usage.py index 7561a8e..091d7b8 100644 --- a/rctab/routers/accounting/usage.py +++ b/rctab/routers/accounting/usage.py @@ -10,7 +10,10 @@ from fastapi.security import OAuth2PasswordBearer from pydantic import BaseModel from rctab_models.models import AllCMUsage, AllUsage, CMUsage, Usage, UserRBAC -from sqlalchemy import select +from sqlalchemy import delete, select + +# require the postgre specific insert rather than the generic sqlachemy for; +# `post_cm_usage` fn where "excluded" and "on_conflict_do_update" are used. from sqlalchemy.dialects.postgresql import insert from sqlalchemy.inspection import inspect @@ -78,19 +81,14 @@ async def insert_usage(all_usage: AllUsage) -> None: all_usage: Usage data to insert. """ usage_query = insert(accounting_models.usage) - update_dict = {c.name: c for c in usage_query.excluded if not c.primary_key} - on_duplicate_key_stmt = usage_query.on_conflict_do_update( - index_elements=inspect(accounting_models.usage).primary_key, - set_=update_dict, - ) logger.info("Inserting usage data") insert_start = datetime.datetime.now() await executemany( database, - on_duplicate_key_stmt, - values=[i.dict() for i in all_usage.usage_list], + usage_query, + values=[i.model_dump() for i in all_usage.usage_list], ) logger.info("Inserting usage data took %s", datetime.datetime.now() - insert_start) refresh_start = datetime.datetime.now() @@ -101,6 +99,27 @@ async def insert_usage(all_usage: AllUsage) -> None: ) +async def delete_usage(start_date: datetime.date, end_date: datetime.date) -> None: + """Deletes usage(s) within a date range from the database. + + Args: + start_date: Defines the beginning of the date range. + end_date: Defines the end of the date range. + """ + usage_query = ( + delete(accounting_models.usage) + .where(accounting_models.usage.c.date >= start_date) + .where(accounting_models.usage.c.date <= end_date) + ) + + logger.info("Delete usage data within a date range") + delete_start = datetime.datetime.now() + + await database.execute(usage_query) + + logger.info("Delete usage data took %s", datetime.datetime.now() - delete_start) + + @router.post("/monthly-usage", response_model=TmpReturnStatus) async def post_monthly_usage( all_usage: AllUsage, _: Dict[str, str] = Depends(authenticate_usage_app) @@ -185,6 +204,7 @@ async def post_usage( unique_subscriptions = list( {i.subscription_id for i in all_usage.usage_list} ) + await delete_usage(all_usage.start_date, all_usage.end_date) await insert_subscriptions_if_not_exists(unique_subscriptions) @@ -199,6 +219,8 @@ async def post_usage( ) +# TODO: remove this decorator and leave it as a standard function as it's only +# used in test. Hence, it will prevent any accidental call to the function. @router.get("/all-usage", response_model=List[Usage]) async def get_usage(_: UserRBAC = Depends(token_admin_verified)) -> List[Usage]: """Get all usage data.""" diff --git a/tests/test_routes/api_calls.py b/tests/test_routes/api_calls.py index c289c30..a448789 100644 --- a/tests/test_routes/api_calls.py +++ b/tests/test_routes/api_calls.py @@ -173,7 +173,7 @@ def create_usage( monthly_upload=None, ) - post_data = AllUsage(usage_list=[usage]) + post_data = AllUsage(usage_list=[usage], start_date=date, end_date=date) return client.post( "usage/all-usage", diff --git a/tests/test_routes/test_usage.py b/tests/test_routes/test_usage.py index 5570fcb..da205c9 100644 --- a/tests/test_routes/test_usage.py +++ b/tests/test_routes/test_usage.py @@ -1,7 +1,7 @@ import datetime import json from pathlib import Path -from typing import List, Tuple, Union +from typing import Iterable, List, Tuple, Union from unittest.mock import AsyncMock from uuid import UUID @@ -45,9 +45,14 @@ def test_post_usage( auth_app, token = app_with_signed_billing_token example_usage_file = Path("tests/data/example.json") - example_usage_data = json.loads(example_usage_file.read_text(encoding="utf-8")) + example_usage_data: Iterable[dict] = json.loads( + example_usage_file.read_text(encoding="utf-8") + ) + dates = {item["date"] for item in example_usage_data} - post_data = AllUsage(usage_list=example_usage_data) + post_data = AllUsage( + usage_list=example_usage_data, start_date=min(dates), end_date=max(dates) + ) with TestClient(auth_app) as client: mock_refresh = AsyncMock() @@ -83,6 +88,118 @@ def test_post_usage( ) +@pytest.mark.asyncio +async def test_post_usage2( + test_db: Database, # pylint: disable=redefined-outer-name +) -> None: + sub1 = await create_subscription(test_db) + # create some usage data across 2 or more dates + usage_items = AllUsage( + usage_list=[ + Usage( + id=str(UUID(int=0)), + subscription_id=sub1, + date="2024-04-01", + total_cost=1.0, + invoice_section="-", + ), + Usage( + id=str(UUID(int=1)), + subscription_id=sub1, + date="2024-04-02", + total_cost=2.0, + invoice_section="-", + ), + Usage( + id=str(UUID(int=2)), + subscription_id=sub1, + date="2024-04-03", + total_cost=4.0, + invoice_section="-", + ), + ], + start_date="2024-04-01", + end_date="2024-04-03", + ) + await post_usage(usage_items, {"mock": "authentication"}) + all_usage = await get_usage() + assert len(all_usage) == 3 + + # upload some usage data for some subset of the dates + usage_list = [ + Usage( + id=str(UUID(int=3)), + subscription_id=sub1, + date="2024-04-02", + total_cost=4.0, + invoice_section="-", + ), + ] + usage_items = AllUsage( + usage_list=usage_list, + start_date="2024-04-02", + end_date="2024-04-02", + ) + await post_usage(usage_items, {"mock": "authentication"}) + + # check that the uploaded usage data replaced the existing ones + all_usage = await get_usage() + assert set(all_usage) == { + Usage( + id=str(UUID(int=0)), + subscription_id=sub1, + date="2024-04-01", + total_cost=1.0, + invoice_section="-", + ), + Usage( + id=str(UUID(int=3)), + subscription_id=sub1, + date="2024-04-02", + total_cost=4.0, + invoice_section="-", + ), + Usage( + id=str(UUID(int=2)), + subscription_id=sub1, + date="2024-04-03", + total_cost=4.0, + invoice_section="-", + ), + } + + +@pytest.mark.asyncio +async def test_post_usage3( + test_db: Database, # pylint: disable=redefined-outer-name +) -> None: + sub1 = await create_subscription(test_db) + # create two usage items with the same usage id + usage_items = AllUsage( + usage_list=[ + Usage( + id=str(UUID(int=0)), + subscription_id=sub1, + date="2024-04-01", + total_cost=1.0, + invoice_section="A", + ), + Usage( + id=str(UUID(int=0)), + subscription_id=sub1, + date="2024-04-01", + total_cost=1.0, + invoice_section="B", + ), + ], + start_date="2024-04-01", + end_date="2024-04-01", + ) + await post_usage(usage_items, {"mock": "authentication"}) + all_usage = await get_usage() + assert len(all_usage) == 2 + + def test_write_usage( app_with_signed_billing_token: Tuple[FastAPI, str], mocker: MockerFixture ) -> None: @@ -286,12 +403,18 @@ def test_post_monthly_usage( example_1_file = Path("tests/data/example-monthly-wrong.json") example_1_data = json.loads(example_1_file.read_text(encoding="utf-8")) + dates_ex1 = {item["date"] for item in example_1_data} example_2_file = Path("tests/data/example-monthly-correct.json") example_2_data = json.loads(example_2_file.read_text(encoding="utf-8")) + dates_ex2 = {item["date"] for item in example_2_data} - post_example_1_data = AllUsage(usage_list=example_1_data) - post_example_2_data = AllUsage(usage_list=example_2_data) + post_example_1_data = AllUsage( + usage_list=example_1_data, start_date=min(dates_ex1), end_date=max(dates_ex1) + ) + post_example_2_data = AllUsage( + usage_list=example_2_data, start_date=min(dates_ex2), end_date=max(dates_ex2) + ) with TestClient(auth_app) as client: mock_refresh = AsyncMock() @@ -302,7 +425,11 @@ def test_post_monthly_usage( # Should error if there is no data. resp = client.post( "usage/monthly-usage", - content=AllUsage(usage_list=[]).model_dump_json().encode("utf-8"), + content=AllUsage( + usage_list=[], start_date="2021-04-01", end_date="2021-04-30" + ) + .model_dump_json() + .encode("utf-8"), headers={"authorization": "Bearer " + token}, ) @@ -371,7 +498,9 @@ async def test_monthly_usage_2( total_cost=4.0, invoice_section="-", ), - ] + ], + start_date="2024-04-01", + end_date="2024-04-03", ), {"mock": "authentication"}, ) @@ -395,7 +524,9 @@ async def test_monthly_usage_2( invoice_section="-", monthly_upload=datetime.date.today(), ), - ] + ], + start_date="2024-04-01", + end_date="2024-04-02", ), {"mock": "authentication"}, ) @@ -438,7 +569,10 @@ async def test_post_usage_refreshes_view( "rctab.routers.accounting.usage.refresh_materialised_view", mock_refresh ) - await post_usage(AllUsage(usage_list=[]), {"mock": "authentication"}) + await post_usage( + AllUsage(usage_list=[], start_date="2021-04-01", end_date="2021-04-30"), + {"mock": "authentication"}, + ) mock_refresh.assert_called_once_with(test_db, usage_view) @@ -452,7 +586,10 @@ def test_post_usage_emails( auth_app, token = app_with_signed_billing_token example_usage_file = Path("tests/data/example.json") example_usage_data = json.loads(example_usage_file.read_text(encoding="utf-8")) - post_data = AllUsage(usage_list=example_usage_data) + dates = {item["date"] for item in example_usage_data} + post_data = AllUsage( + usage_list=example_usage_data, start_date=min(dates), end_date=max(dates) + ) with TestClient(auth_app) as client: mock_send_emails = AsyncMock()