From 29a88c5a1dd46cd352c5f298f1be0c1525d8bebe Mon Sep 17 00:00:00 2001 From: Haleemur Ali Date: Sat, 7 Oct 2023 16:48:16 -0400 Subject: [PATCH 1/7] add ability to do list comprehensions in stream map expressions --- singer_sdk/mapper.py | 27 ++++++++++++++++++++++++++- tests/core/test_mapper.py | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/singer_sdk/mapper.py b/singer_sdk/mapper.py index f705ac5da..9b56d5089 100644 --- a/singer_sdk/mapper.py +++ b/singer_sdk/mapper.py @@ -54,6 +54,27 @@ def md5(string: str) -> str: return hashlib.md5(string.encode("utf-8")).hexdigest() # noqa: S324 +def compound_eval( + expr: str, + operators: t.Dict[str, t.Callable[[dict], dict | None]] = None, + functions: t.Dict[str, t.Callable[[dict], dict | None]] = None, + names=t.Dict[str, t.Any] + ) -> t.Union[str, int, float, t.List, t.Set, t.Dict]: + """Evaluate inline maps using the `EvalWithCompoundTypes` class + + Args: + expr: expression to evaluate + operators: dictionary of operators and the functions they map to in the evaluation context + functions: dictionary of function names and definitions available in the evaluation context + names: dictionary of variable names available in the evaluation context + + Returns: + result of the evaluated expression + """ + s = simpleeval.EvalWithCompoundTypes(operators=operators, functions=functions, names=names) + return s.eval(expr) + + StreamMapsDict: TypeAlias = t.Dict[str, t.Union[str, dict, None]] @@ -296,6 +317,7 @@ def functions(self) -> dict[str, t.Callable]: funcs: dict[str, t.Any] = simpleeval.DEFAULT_FUNCTIONS.copy() funcs["md5"] = md5 funcs["datetime"] = datetime + funcs["bool"] = bool return funcs def _eval( @@ -325,7 +347,7 @@ def _eval( # Allow access to original property value if applicable names["self"] = record[property_name] try: - result: str | int | float = simpleeval.simple_eval( + result: str | int | float = compound_eval( expr, functions=self.functions, names=names, @@ -374,6 +396,9 @@ def _eval_type( if expr.startswith("str("): return th.StringType() + if expr.startswith("bool("): + return th.BooleanType() + return th.StringType() if expr[0] == "'" and expr[-1] == "'" else default def _init_functions_and_schema( # noqa: PLR0912, PLR0915, C901 diff --git a/tests/core/test_mapper.py b/tests/core/test_mapper.py index abc517260..2afcb59b4 100644 --- a/tests/core/test_mapper.py +++ b/tests/core/test_mapper.py @@ -28,6 +28,8 @@ PropertiesList, Property, StringType, + BooleanType, + OneOf, ) if t.TYPE_CHECKING: @@ -56,6 +58,14 @@ def sample_catalog_dict() -> dict: Property("the", StringType), Property("brown", StringType), ).to_dict() + nested_jellybean_schema = PropertiesList( + Property("id", IntegerType), + Property("custom_fields", + ArrayType(ObjectType( + Property("id", IntegerType), + Property("value", OneOf(StringType, IntegerType, BooleanType)))) + ) + ).to_dict() return { "streams": [ { @@ -68,6 +78,11 @@ def sample_catalog_dict() -> dict: "tap_stream_id": "foobars", "schema": foobars_schema, }, + { + "stream": "nested_jellybean", + "tap_stream_id": "nested_jellybean", + "schema": nested_jellybean_schema + } ], } @@ -110,6 +125,10 @@ def sample_stream(): {"the": "quick"}, {"brown": "fox"}, ], + "nested_jellybean": [ + {"id": 123, "custom_fields": [{"id": 1, "value": "abc"}, {"id": 2, "value": 1212}, {"id": 3, "value": None}]}, + {"id": 124, "custom_fields": [{"id": 1, "value": "foo"}, {"id": 2, "value": 9009}, {"id": 3, "value": True}]} + ], } @@ -129,6 +148,12 @@ def transform_stream_maps(): "int_test": "int('0')", "__else__": None, }, + "nested_jellybean": { + "custom_fields": "__NULL__", + "custom_field_1": 'dict([(x["id"], x["value"]) for x in custom_fields]).get(1)', + "custom_field_2": 'int(dict([(x["id"], x["value"]) for x in custom_fields]).get(2)) if dict([(x["id"], x["value"]) for x in custom_fields]).get(2) else None', + "custom_field_3": 'bool(dict([(x["id"], x["value"]) for x in custom_fields]).get(3)) if dict([(x["id"], x["value"]) for x in custom_fields]).get(3) else None', + } } @@ -185,6 +210,10 @@ def transformed_result(stream_map_config): {"the": "quick"}, {"brown": "fox"}, ], + "nested_jellybean": [ + {"id": 123, "custom_field_1": "abc", "custom_field_2": 1212, "custom_field_3": None}, + {"id": 124, "custom_field_1": "foo", "custom_field_2": 9009, "custom_field_3": True} + ], } @@ -204,6 +233,12 @@ def transformed_schemas(): Property("the", StringType), Property("brown", StringType), ).to_dict(), + "nested_jellybean": PropertiesList( + Property("id", IntegerType), + Property("custom_field_1", StringType), + Property("custom_field_2", IntegerType), + Property("custom_field_3", BooleanType) + ).to_dict() } From 9f29633919f0e19a30fb581dfa4b86c86712769a Mon Sep 17 00:00:00 2001 From: Haleemur Ali Date: Mon, 9 Oct 2023 00:15:06 -0400 Subject: [PATCH 2/7] parse expressions only once --- poetry.lock | 600 +++++++++++++++++++++++++- pyproject.toml | 1 + singer_sdk/helpers/_simpleeval.py | 679 ------------------------------ singer_sdk/mapper.py | 67 +-- tests/core/test_mapper.py | 60 ++- tests/core/test_simpleeval.py | 4 +- 6 files changed, 678 insertions(+), 733 deletions(-) delete mode 100644 singer_sdk/helpers/_simpleeval.py diff --git a/poetry.lock b/poetry.lock index e8c2693c9..b79bd28e7 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,9 +1,10 @@ -# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.4.1 and should not be changed by hand. [[package]] name = "alabaster" version = "0.7.13" description = "A configurable sidebar-enabled Sphinx theme" +category = "main" optional = true python-versions = ">=3.6" files = [ @@ -15,6 +16,7 @@ files = [ name = "appdirs" version = "1.4.4" description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +category = "main" optional = false python-versions = "*" files = [ @@ -22,10 +24,29 @@ files = [ {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, ] +[[package]] +name = "argcomplete" +version = "3.1.2" +description = "Bash tab completion for argparse" +category = "dev" +optional = false +python-versions = ">=3.6" +files = [ + {file = "argcomplete-3.1.2-py3-none-any.whl", hash = "sha256:d97c036d12a752d1079f190bc1521c545b941fda89ad85d15afa909b4d1b9a99"}, + {file = "argcomplete-3.1.2.tar.gz", hash = "sha256:d5d1e5efd41435260b8f85673b74ea2e883affcbec9f4230c582689e8e78251b"}, +] + +[package.dependencies] +importlib-metadata = {version = ">=0.23,<7", markers = "python_version < \"3.8\""} + +[package.extras] +test = ["coverage", "mypy", "pexpect", "ruff", "wheel"] + [[package]] name = "arrow" version = "1.2.3" description = "Better dates & times for Python" +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -41,6 +62,7 @@ typing-extensions = {version = "*", markers = "python_version < \"3.8\""} name = "attrs" version = "23.1.0" description = "Classes Without Boilerplate" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -62,6 +84,7 @@ tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pyte name = "babel" version = "2.12.1" description = "Internationalization utilities" +category = "main" optional = true python-versions = ">=3.7" files = [ @@ -76,6 +99,7 @@ pytz = {version = ">=2015.7", markers = "python_version < \"3.9\""} name = "backoff" version = "2.2.1" description = "Function decoration for backoff and retry" +category = "main" optional = false python-versions = ">=3.7,<4.0" files = [ @@ -87,6 +111,7 @@ files = [ name = "beautifulsoup4" version = "4.12.2" description = "Screen-scraping library" +category = "main" optional = true python-versions = ">=3.6.0" files = [ @@ -105,6 +130,7 @@ lxml = ["lxml"] name = "binaryornot" version = "0.4.4" description = "Ultra-lightweight pure Python package to check if a file is binary or text." +category = "dev" optional = false python-versions = "*" files = [ @@ -119,6 +145,7 @@ chardet = ">=3.0.2" name = "boto3" version = "1.28.52" description = "The AWS SDK for Python" +category = "main" optional = true python-versions = ">= 3.7" files = [ @@ -138,6 +165,7 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] name = "botocore" version = "1.31.52" description = "Low-level, data-driven core of boto 3." +category = "main" optional = true python-versions = ">= 3.7" files = [ @@ -157,6 +185,7 @@ crt = ["awscrt (==0.16.26)"] name = "certifi" version = "2023.7.22" description = "Python package for providing Mozilla's CA Bundle." +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -168,6 +197,7 @@ files = [ name = "cffi" version = "1.15.1" description = "Foreign Function Interface for Python calling C code." +category = "main" optional = false python-versions = "*" files = [ @@ -244,6 +274,7 @@ pycparser = "*" name = "chardet" version = "5.2.0" description = "Universal encoding detector for Python 3" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -255,6 +286,7 @@ files = [ name = "charset-normalizer" version = "3.2.0" 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 = [ @@ -339,6 +371,7 @@ files = [ name = "click" version = "8.1.7" description = "Composable command line interface toolkit" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -354,6 +387,7 @@ importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} 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 = [ @@ -361,10 +395,57 @@ files = [ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +[[package]] +name = "commitizen" +version = "3.9.0" +description = "Python commitizen client tool" +category = "dev" +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "commitizen-3.9.0-py3-none-any.whl", hash = "sha256:ae6a525a0acdb65437e7ba0cf4714dfb3c5f528316a0bbf4368f8e537432f815"}, + {file = "commitizen-3.9.0.tar.gz", hash = "sha256:36630bea53a35bc2c578346d516ca6b9870f13c7e009c68265e2f098423de2a2"}, +] + +[package.dependencies] +argcomplete = ">=1.12.1,<3.2" +charset-normalizer = ">=2.1.0,<4" +colorama = ">=0.4.1,<0.5.0" +decli = ">=0.6.0,<0.7.0" +importlib_metadata = ">=4.13,<7" +jinja2 = ">=2.10.3" +packaging = ">=19" +pyyaml = ">=3.08" +questionary = ">=1.4.0,<2.0.0" +termcolor = ">=1.1,<3" +tomlkit = ">=0.5.3,<1.0.0" +typing-extensions = {version = ">=4.0.1,<5.0.0", markers = "python_version < \"3.8\""} + +[[package]] +name = "commitizen-version-bump" +version = "0.1.0" +description = "Commitizen customized for Meltano projects (https://commitizen-tools.github.io/commitizen/customization)" +category = "dev" +optional = false +python-versions = "^3.7" +files = [] +develop = false + +[package.dependencies] +commitizen = ">=3.0.0,<4.0.0" +PyGithub = "^1.57" + +[package.source] +type = "git" +url = "https://github.com/meltano/commitizen-version-bump.git" +reference = "main" +resolved_reference = "32fa072821bff397466b55be2abda62bd93e6a8d" + [[package]] name = "cookiecutter" version = "2.4.0" description = "A command-line utility that creates projects from project templates, e.g. creating a Python package project from a Python package project template." +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -386,6 +467,7 @@ rich = "*" name = "coverage" version = "7.2.7" description = "Code coverage measurement for Python" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -461,6 +543,7 @@ toml = ["tomli"] name = "cryptography" version = "41.0.4" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -502,10 +585,41 @@ ssh = ["bcrypt (>=3.1.5)"] test = ["pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] test-randomorder = ["pytest-randomly"] +[[package]] +name = "decli" +version = "0.6.1" +description = "Minimal, easy-to-use, declarative cli tool" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "decli-0.6.1-py3-none-any.whl", hash = "sha256:7815ac58617764e1a200d7cadac6315fcaacc24d727d182f9878dd6378ccf869"}, + {file = "decli-0.6.1.tar.gz", hash = "sha256:ed88ccb947701e8e5509b7945fda56e150e2ac74a69f25d47ac85ef30ab0c0f0"}, +] + +[[package]] +name = "deprecated" +version = "1.2.14" +description = "Python @deprecated decorator to deprecate old python classes, functions or methods." +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "Deprecated-1.2.14-py2.py3-none-any.whl", hash = "sha256:6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c"}, + {file = "Deprecated-1.2.14.tar.gz", hash = "sha256:e5323eb936458dccc2582dc6f9c322c852a775a27065ff2b0c4970b9d53d01b3"}, +] + +[package.dependencies] +wrapt = ">=1.10,<2" + +[package.extras] +dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "sphinx (<2)", "tox"] + [[package]] name = "docutils" version = "0.19" description = "Docutils -- Python Documentation Utilities" +category = "main" optional = true python-versions = ">=3.7" files = [ @@ -517,6 +631,7 @@ files = [ name = "duckdb" version = "0.9.0" description = "DuckDB embedded database" +category = "dev" optional = false python-versions = ">=3.7.0" files = [ @@ -565,6 +680,7 @@ files = [ name = "duckdb-engine" version = "0.9.2" description = "SQLAlchemy driver for duckdb" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -580,6 +696,7 @@ sqlalchemy = ">=1.3.22" name = "exceptiongroup" version = "1.1.3" description = "Backport of PEP 654 (exception groups)" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -594,6 +711,7 @@ test = ["pytest (>=6)"] name = "fs" version = "2.4.16" description = "Python's filesystem abstraction layer" +category = "main" optional = false python-versions = "*" files = [ @@ -613,6 +731,7 @@ scandir = ["scandir (>=1.5,<2.0)"] name = "fs-s3fs" version = "1.1.1" description = "Amazon S3 filesystem for PyFilesystem2" +category = "main" optional = true python-versions = "*" files = [ @@ -629,6 +748,7 @@ six = ">=1.10,<2.0" name = "furo" version = "2023.3.27" description = "A clean customisable Sphinx documentation theme." +category = "main" optional = true python-versions = ">=3.7" files = [ @@ -646,6 +766,7 @@ sphinx-basic-ng = "*" name = "greenlet" version = "2.0.2" description = "Lightweight in-process concurrent programming" +category = "main" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" files = [ @@ -719,6 +840,7 @@ test = ["objgraph", "psutil"] name = "idna" version = "3.4" description = "Internationalized Domain Names in Applications (IDNA)" +category = "main" optional = false python-versions = ">=3.5" files = [ @@ -730,6 +852,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 = [ @@ -741,6 +864,7 @@ files = [ name = "importlib-metadata" version = "6.7.0" description = "Read metadata from Python packages" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -761,6 +885,7 @@ testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs name = "importlib-resources" version = "5.12.0" description = "Read resources from Python packages" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -779,6 +904,7 @@ testing = ["flake8 (<5)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-chec name = "inflection" version = "0.5.1" description = "A port of Ruby on Rails inflector to Python" +category = "main" optional = false python-versions = ">=3.5" files = [ @@ -790,6 +916,7 @@ files = [ name = "iniconfig" version = "2.0.0" description = "brain-dead simple config-ini parsing" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -801,6 +928,7 @@ files = [ name = "jinja2" version = "3.1.2" description = "A very fast and expressive template engine." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -818,6 +946,7 @@ i18n = ["Babel (>=2.7)"] name = "jmespath" version = "1.0.1" description = "JSON Matching Expressions" +category = "main" optional = true python-versions = ">=3.7" files = [ @@ -829,6 +958,7 @@ files = [ name = "joblib" version = "1.3.2" description = "Lightweight pipelining with Python functions" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -840,6 +970,7 @@ files = [ name = "jsonpath-ng" version = "1.6.0" description = "A final implementation of JSONPath for Python that aims to be standard compliant, including arithmetic and binary comparison operators and providing clear AST for metaprogramming." +category = "main" optional = false python-versions = "*" files = [ @@ -854,6 +985,7 @@ ply = "*" name = "jsonschema" version = "4.17.3" description = "An implementation of JSON Schema validation for Python" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -877,6 +1009,7 @@ format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339- name = "livereload" version = "2.6.3" description = "Python LiveReload is an awesome tool for web developers" +category = "main" optional = true python-versions = "*" files = [ @@ -892,6 +1025,7 @@ tornado = {version = "*", markers = "python_version > \"2.7\""} name = "markdown-it-py" version = "2.2.0" description = "Python port of markdown-it. Markdown parsing, done right!" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -917,6 +1051,7 @@ testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] name = "markupsafe" version = "2.1.3" description = "Safely add untrusted strings to HTML/XML markup." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -976,6 +1111,7 @@ files = [ name = "mdit-py-plugins" version = "0.3.5" description = "Collection of plugins for markdown-it-py" +category = "main" optional = true python-versions = ">=3.7" files = [ @@ -995,6 +1131,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 = [ @@ -1006,16 +1143,102 @@ files = [ name = "memoization" version = "0.4.0" description = "A powerful caching library for Python, with TTL support and multiple algorithm options. (https://github.com/lonelyenvoy/python-memoization)" +category = "main" optional = false python-versions = ">=3, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, <4" files = [ {file = "memoization-0.4.0.tar.gz", hash = "sha256:fde5e7cd060ef45b135e0310cfec17b2029dc472ccb5bbbbb42a503d4538a135"}, ] +[[package]] +name = "multidict" +version = "6.0.4" +description = "multidict implementation" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8"}, + {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eeb6dcc05e911516ae3d1f207d4b0520d07f54484c49dfc294d6e7d63b734171"}, + {file = "multidict-6.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d6d635d5209b82a3492508cf5b365f3446afb65ae7ebd755e70e18f287b0adf7"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c048099e4c9e9d615545e2001d3d8a4380bd403e1a0578734e0d31703d1b0c0b"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea20853c6dbbb53ed34cb4d080382169b6f4554d394015f1bef35e881bf83547"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16d232d4e5396c2efbbf4f6d4df89bfa905eb0d4dc5b3549d872ab898451f569"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36c63aaa167f6c6b04ef2c85704e93af16c11d20de1d133e39de6a0e84582a93"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:64bdf1086b6043bf519869678f5f2757f473dee970d7abf6da91ec00acb9cb98"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:43644e38f42e3af682690876cff722d301ac585c5b9e1eacc013b7a3f7b696a0"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7582a1d1030e15422262de9f58711774e02fa80df0d1578995c76214f6954988"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ddff9c4e225a63a5afab9dd15590432c22e8057e1a9a13d28ed128ecf047bbdc"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ee2a1ece51b9b9e7752e742cfb661d2a29e7bcdba2d27e66e28a99f1890e4fa0"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a2e4369eb3d47d2034032a26c7a80fcb21a2cb22e1173d761a162f11e562caa5"}, + {file = "multidict-6.0.4-cp310-cp310-win32.whl", hash = "sha256:574b7eae1ab267e5f8285f0fe881f17efe4b98c39a40858247720935b893bba8"}, + {file = "multidict-6.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:4dcbb0906e38440fa3e325df2359ac6cb043df8e58c965bb45f4e406ecb162cc"}, + {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03"}, + {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:64da238a09d6039e3bd39bb3aee9c21a5e34f28bfa5aa22518581f910ff94af3"}, + {file = "multidict-6.0.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5cb09abb18c1ea940fb99360ea0396f34d46566f157122c92dfa069d3e0e982"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:666daae833559deb2d609afa4490b85830ab0dfca811a98b70a205621a6109fe"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d18748f2d30f94f498e852c67d61261c643b349b9d2a581131725595c45ec6c"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:458f37be2d9e4c95e2d8866a851663cbc76e865b78395090786f6cd9b3bbf4f4"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:b1a2eeedcead3a41694130495593a559a668f382eee0727352b9a41e1c45759a"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7d6ae9d593ef8641544d6263c7fa6408cc90370c8cb2bbb65f8d43e5b0351d9c"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5979b5632c3e3534e42ca6ff856bb24b2e3071b37861c2c727ce220d80eee9ed"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dcfe792765fab89c365123c81046ad4103fcabbc4f56d1c1997e6715e8015461"}, + {file = "multidict-6.0.4-cp311-cp311-win32.whl", hash = "sha256:3601a3cece3819534b11d4efc1eb76047488fddd0c85a3948099d5da4d504636"}, + {file = "multidict-6.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:81a4f0b34bd92df3da93315c6a59034df95866014ac08535fc819f043bfd51f0"}, + {file = "multidict-6.0.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:67040058f37a2a51ed8ea8f6b0e6ee5bd78ca67f169ce6122f3e2ec80dfe9b78"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:853888594621e6604c978ce2a0444a1e6e70c8d253ab65ba11657659dcc9100f"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:39ff62e7d0f26c248b15e364517a72932a611a9b75f35b45be078d81bdb86603"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:af048912e045a2dc732847d33821a9d84ba553f5c5f028adbd364dd4765092ac"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e8b901e607795ec06c9e42530788c45ac21ef3aaa11dbd0c69de543bfb79a9"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62501642008a8b9871ddfccbf83e4222cf8ac0d5aeedf73da36153ef2ec222d2"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:99b76c052e9f1bc0721f7541e5e8c05db3941eb9ebe7b8553c625ef88d6eefde"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:509eac6cf09c794aa27bcacfd4d62c885cce62bef7b2c3e8b2e49d365b5003fe"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:21a12c4eb6ddc9952c415f24eef97e3e55ba3af61f67c7bc388dcdec1404a067"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:5cad9430ab3e2e4fa4a2ef4450f548768400a2ac635841bc2a56a2052cdbeb87"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab55edc2e84460694295f401215f4a58597f8f7c9466faec545093045476327d"}, + {file = "multidict-6.0.4-cp37-cp37m-win32.whl", hash = "sha256:5a4dcf02b908c3b8b17a45fb0f15b695bf117a67b76b7ad18b73cf8e92608775"}, + {file = "multidict-6.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:6ed5f161328b7df384d71b07317f4d8656434e34591f20552c7bcef27b0ab88e"}, + {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5fc1b16f586f049820c5c5b17bb4ee7583092fa0d1c4e28b5239181ff9532e0c"}, + {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1502e24330eb681bdaa3eb70d6358e818e8e8f908a22a1851dfd4e15bc2f8161"}, + {file = "multidict-6.0.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b692f419760c0e65d060959df05f2a531945af31fda0c8a3b3195d4efd06de11"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45e1ecb0379bfaab5eef059f50115b54571acfbe422a14f668fc8c27ba410e7e"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddd3915998d93fbcd2566ddf9cf62cdb35c9e093075f862935573d265cf8f65d"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:59d43b61c59d82f2effb39a93c48b845efe23a3852d201ed2d24ba830d0b4cf2"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc8e1d0c705233c5dd0c5e6460fbad7827d5d36f310a0fadfd45cc3029762258"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6aa0418fcc838522256761b3415822626f866758ee0bc6632c9486b179d0b52"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6748717bb10339c4760c1e63da040f5f29f5ed6e59d76daee30305894069a660"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4d1a3d7ef5e96b1c9e92f973e43aa5e5b96c659c9bc3124acbbd81b0b9c8a951"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4372381634485bec7e46718edc71528024fcdc6f835baefe517b34a33c731d60"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b9d9e4e2b37daddb5c23ea33a3417901fa7c7b3dee2d855f63ee67a0b21e5b1"}, + {file = "multidict-6.0.4-cp38-cp38-win32.whl", hash = "sha256:e41b7e2b59679edfa309e8db64fdf22399eec4b0b24694e1b2104fb789207779"}, + {file = "multidict-6.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:d6c254ba6e45d8e72739281ebc46ea5eb5f101234f3ce171f0e9f5cc86991480"}, + {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:16ab77bbeb596e14212e7bab8429f24c1579234a3a462105cda4a66904998664"}, + {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc779e9e6f7fda81b3f9aa58e3a6091d49ad528b11ed19f6621408806204ad35"}, + {file = "multidict-6.0.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ceef517eca3e03c1cceb22030a3e39cb399ac86bff4e426d4fc6ae49052cc60"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:281af09f488903fde97923c7744bb001a9b23b039a909460d0f14edc7bf59706"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:52f2dffc8acaba9a2f27174c41c9e57f60b907bb9f096b36b1a1f3be71c6284d"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b41156839806aecb3641f3208c0dafd3ac7775b9c4c422d82ee2a45c34ba81ca"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5e3fc56f88cc98ef8139255cf8cd63eb2c586531e43310ff859d6bb3a6b51f1"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8316a77808c501004802f9beebde51c9f857054a0c871bd6da8280e718444449"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bf6774e60d67a9efe02b3616fee22441d86fab4c6d335f9d2051d19d90a40063"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:e69924bfcdda39b722ef4d9aa762b2dd38e4632b3641b1d9a57ca9cd18f2f83a"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:6b181d8c23da913d4ff585afd1155a0e1194c0b50c54fcfe286f70cdaf2b7176"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:52509b5be062d9eafc8170e53026fbc54cf3b32759a23d07fd935fb04fc22d95"}, + {file = "multidict-6.0.4-cp39-cp39-win32.whl", hash = "sha256:27c523fbfbdfd19c6867af7346332b62b586eed663887392cff78d614f9ec313"}, + {file = "multidict-6.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:33029f5734336aa0d4c0384525da0387ef89148dc7191aae00ca5fb23d7aafc2"}, + {file = "multidict-6.0.4.tar.gz", hash = "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49"}, +] + [[package]] name = "mypy" version = "1.4.1" description = "Optional static typing for Python" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1063,6 +1286,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 = [ @@ -1074,6 +1298,7 @@ files = [ name = "myst-parser" version = "1.0.0" description = "An extended [CommonMark](https://spec.commonmark.org/) compliant parser," +category = "main" optional = true python-versions = ">=3.7" files = [ @@ -1101,6 +1326,7 @@ testing-docutils = ["pygments", "pytest (>=7,<8)", "pytest-param-files (>=0.3.4, name = "numpy" version = "1.21.6" description = "NumPy is the fundamental package for array computing with Python." +category = "dev" optional = false python-versions = ">=3.7,<3.11" files = [ @@ -1141,6 +1367,7 @@ files = [ name = "numpy" version = "1.24.4" description = "Fundamental package for array computing in Python" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -1178,6 +1405,7 @@ files = [ name = "packaging" version = "23.2" description = "Core utilities for Python packages" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1189,6 +1417,7 @@ files = [ name = "pendulum" version = "2.1.2" description = "Python datetimes made easy" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -1223,6 +1452,7 @@ pytzdata = ">=2020.1" name = "pkgutil-resolve-name" version = "1.3.10" description = "Resolve a name to an object." +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -1234,6 +1464,7 @@ files = [ name = "pluggy" version = "1.2.0" description = "plugin and hook calling mechanisms for python" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1252,6 +1483,7 @@ testing = ["pytest", "pytest-benchmark"] name = "ply" version = "3.11" description = "Python Lex & Yacc" +category = "main" optional = false python-versions = "*" files = [ @@ -1260,9 +1492,10 @@ files = [ ] [[package]] -name = "py-cpuinfo" -version = "9.0.0" -description = "Get CPU info with pure Python" +name = "prompt-toolkit" +version = "3.0.39" +description = "Library for building powerful interactive command lines in Python" +category = "dev" optional = false python-versions = "*" files = [ @@ -1274,6 +1507,7 @@ files = [ name = "pyarrow" version = "12.0.1" description = "Python library for Apache Arrow" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1311,6 +1545,7 @@ numpy = ">=1.16.6" name = "pycparser" version = "2.21" description = "C parser in Python" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -1318,10 +1553,29 @@ files = [ {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, ] +[[package]] +name = "pygithub" +version = "1.59.1" +description = "Use the full Github API v3" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "PyGithub-1.59.1-py3-none-any.whl", hash = "sha256:3d87a822e6c868142f0c2c4bf16cce4696b5a7a4d142a7bd160e1bdf75bc54a9"}, + {file = "PyGithub-1.59.1.tar.gz", hash = "sha256:c44e3a121c15bf9d3a5cc98d94c9a047a5132a9b01d22264627f58ade9ddc217"}, +] + +[package.dependencies] +deprecated = "*" +pyjwt = {version = ">=2.4.0", extras = ["crypto"]} +pynacl = ">=1.4.0" +requests = ">=2.14.0" + [[package]] name = "pygments" version = "2.16.1" description = "Pygments is a syntax highlighting package written in Python." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1336,6 +1590,7 @@ plugins = ["importlib-metadata"] name = "pyjwt" version = "2.8.0" description = "JSON Web Token implementation in Python" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1352,10 +1607,38 @@ dev = ["coverage[toml] (==5.0.4)", "cryptography (>=3.4.0)", "pre-commit", "pyte docs = ["sphinx (>=4.5.0,<5.0.0)", "sphinx-rtd-theme", "zope.interface"] tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] +[[package]] +name = "pynacl" +version = "1.5.0" +description = "Python binding to the Networking and Cryptography (NaCl) library" +category = "dev" +optional = false +python-versions = ">=3.6" +files = [ + {file = "PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1"}, + {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92"}, + {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394"}, + {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d"}, + {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858"}, + {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b"}, + {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff"}, + {file = "PyNaCl-1.5.0-cp36-abi3-win32.whl", hash = "sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543"}, + {file = "PyNaCl-1.5.0-cp36-abi3-win_amd64.whl", hash = "sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93"}, + {file = "PyNaCl-1.5.0.tar.gz", hash = "sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba"}, +] + +[package.dependencies] +cffi = ">=1.4.1" + +[package.extras] +docs = ["sphinx (>=1.6.5)", "sphinx-rtd-theme"] +tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"] + [[package]] name = "pyrsistent" version = "0.19.3" description = "Persistent/Functional/Immutable data structures" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1392,6 +1675,7 @@ files = [ name = "pytest" version = "7.4.2" description = "pytest: simple powerful testing with Python" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1435,6 +1719,7 @@ histogram = ["pygal", "pygaljs"] name = "pytest-durations" version = "1.2.0" description = "Pytest plugin reporting fixtures and test functions execution time." +category = "main" optional = true python-versions = ">=3.6.2" files = [ @@ -1449,6 +1734,7 @@ pytest = ">=4.6" name = "pytest-snapshot" version = "0.9.0" description = "A plugin for snapshot testing with pytest." +category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -1463,6 +1749,7 @@ pytest = ">=3.0.0" name = "python-dateutil" version = "2.8.2" description = "Extensions to the standard Python datetime module" +category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" files = [ @@ -1477,6 +1764,7 @@ six = ">=1.5" name = "python-dotenv" version = "0.21.1" description = "Read key-value pairs from a .env file and set them as environment variables" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1491,6 +1779,7 @@ cli = ["click (>=5.0)"] name = "python-slugify" version = "8.0.1" description = "A Python slugify application that also handles Unicode" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1508,6 +1797,7 @@ unidecode = ["Unidecode (>=1.1.1)"] name = "pytz" version = "2023.3.post1" description = "World timezone definitions, modern and historical" +category = "main" optional = false python-versions = "*" files = [ @@ -1519,6 +1809,7 @@ files = [ name = "pytzdata" version = "2020.1" description = "The Olson timezone database for Python." +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -1530,6 +1821,7 @@ files = [ name = "pyyaml" version = "6.0.1" description = "YAML parser and emitter for Python" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -1585,10 +1877,46 @@ files = [ {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, ] +[[package]] +name = "questionary" +version = "1.10.0" +description = "Python library to build pretty command line user prompts ⭐️" +category = "dev" +optional = false +python-versions = ">=3.6,<4.0" +files = [ + {file = "questionary-1.10.0-py3-none-any.whl", hash = "sha256:fecfcc8cca110fda9d561cb83f1e97ecbb93c613ff857f655818839dac74ce90"}, + {file = "questionary-1.10.0.tar.gz", hash = "sha256:600d3aefecce26d48d97eee936fdb66e4bc27f934c3ab6dd1e292c4f43946d90"}, +] + +[package.dependencies] +prompt_toolkit = ">=2.0,<4.0" + +[package.extras] +docs = ["Sphinx (>=3.3,<4.0)", "sphinx-autobuild (>=2020.9.1,<2021.0.0)", "sphinx-autodoc-typehints (>=1.11.1,<2.0.0)", "sphinx-copybutton (>=0.3.1,<0.4.0)", "sphinx-rtd-theme (>=0.5.0,<0.6.0)"] + +[[package]] +name = "referencing" +version = "0.8.9" +description = "JSON Referencing + Python" +category = "dev" +optional = false +python-versions = "*" +files = [ + {file = "referencing-0.8.9-py2.py3-none-any.whl", hash = "sha256:d144e834a707652a488c4d8b29949a4f7ece7526ea8c889d8d881bebee72bb6d"}, + {file = "referencing-0.8.9.tar.gz", hash = "sha256:2c0bc673a26fa0939d9f0a6bc8b0975f573b6f1fed14b42ee7597a766d4ec416"}, +] + +[package.dependencies] +attrs = "*" +pyrsistent = "*" +yarl = "*" + [[package]] name = "requests" version = "2.31.0" description = "Python HTTP for Humans." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1610,6 +1938,7 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] name = "requests-mock" version = "1.11.0" description = "Mock out responses from the requests package" +category = "dev" optional = false python-versions = "*" files = [ @@ -1629,6 +1958,7 @@ test = ["fixtures", "mock", "purl", "pytest", "requests-futures", "sphinx", "tes name = "rich" version = "13.5.3" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" +category = "dev" optional = false python-versions = ">=3.7.0" files = [ @@ -1648,6 +1978,7 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] name = "s3transfer" version = "0.6.2" description = "An Amazon S3 Transfer Manager" +category = "main" optional = true python-versions = ">= 3.7" files = [ @@ -1665,6 +1996,7 @@ crt = ["botocore[crt] (>=1.20.29,<2.0a.0)"] name = "setuptools" version = "68.0.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1677,10 +2009,23 @@ docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-g testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] +[[package]] +name = "simpleeval" +version = "0.9.13" +description = "A simple, safe single expression evaluator library." +category = "main" +optional = false +python-versions = "*" +files = [ + {file = "simpleeval-0.9.13-py2.py3-none-any.whl", hash = "sha256:22a2701a5006e4188d125d34accf2405c2c37c93f6b346f2484b6422415ae54a"}, + {file = "simpleeval-0.9.13.tar.gz", hash = "sha256:4a30f9cc01825fe4c719c785e3762623e350c4840d5e6855c2a8496baaa65fac"}, +] + [[package]] name = "simplejson" version = "3.19.2" description = "Simple, fast, extensible JSON encoder/decoder for Python" +category = "main" optional = false python-versions = ">=2.5, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -1788,6 +2133,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 = [ @@ -1799,6 +2145,7 @@ files = [ name = "snowballstemmer" version = "2.2.0" description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." +category = "main" optional = true python-versions = "*" files = [ @@ -1810,6 +2157,7 @@ files = [ name = "soupsieve" version = "2.4.1" description = "A modern CSS selector implementation for Beautiful Soup." +category = "main" optional = true python-versions = ">=3.7" files = [ @@ -1821,6 +2169,7 @@ files = [ name = "sphinx" version = "5.3.0" description = "Python documentation generator" +category = "main" optional = true python-versions = ">=3.6" files = [ @@ -1856,6 +2205,7 @@ test = ["cython", "html5lib", "pytest (>=4.6)", "typed_ast"] name = "sphinx-autobuild" version = "2021.3.14" description = "Rebuild Sphinx documentation on changes, with live-reload in the browser." +category = "main" optional = true python-versions = ">=3.6" files = [ @@ -1875,6 +2225,7 @@ test = ["pytest", "pytest-cov"] name = "sphinx-basic-ng" version = "1.0.0b2" description = "A modern skeleton for Sphinx themes." +category = "main" optional = true python-versions = ">=3.7" files = [ @@ -1892,6 +2243,7 @@ docs = ["furo", "ipython", "myst-parser", "sphinx-copybutton", "sphinx-inline-ta name = "sphinx-copybutton" version = "0.5.2" description = "Add a copy button to each of your code cells." +category = "main" optional = true python-versions = ">=3.7" files = [ @@ -1910,6 +2262,7 @@ rtd = ["ipython", "myst-nb", "sphinx", "sphinx-book-theme", "sphinx-examples"] name = "sphinx-inline-tabs" version = "2023.4.21" description = "Add inline tabbed content to your Sphinx documentation." +category = "main" optional = true python-versions = ">=3.8" files = [ @@ -1928,6 +2281,7 @@ test = ["pytest", "pytest-cov", "pytest-xdist"] name = "sphinx-reredirects" version = "0.1.2" description = "Handles redirects for moved pages in Sphinx documentation projects" +category = "main" optional = true python-versions = ">=3.5" files = [ @@ -1942,6 +2296,7 @@ sphinx = "*" name = "sphinxcontrib-applehelp" version = "1.0.2" description = "sphinxcontrib-applehelp is a sphinx extension which outputs Apple help books" +category = "main" optional = true python-versions = ">=3.5" files = [ @@ -1957,6 +2312,7 @@ test = ["pytest"] name = "sphinxcontrib-devhelp" version = "1.0.2" description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document." +category = "main" optional = true python-versions = ">=3.5" files = [ @@ -1972,6 +2328,7 @@ test = ["pytest"] name = "sphinxcontrib-htmlhelp" version = "2.0.0" description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" +category = "main" optional = true python-versions = ">=3.6" files = [ @@ -1987,6 +2344,7 @@ test = ["html5lib", "pytest"] 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 = [ @@ -2001,6 +2359,7 @@ test = ["flake8", "mypy", "pytest"] name = "sphinxcontrib-qthelp" version = "1.0.3" description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document." +category = "main" optional = true python-versions = ">=3.5" files = [ @@ -2016,6 +2375,7 @@ test = ["pytest"] name = "sphinxcontrib-serializinghtml" version = "1.1.5" description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)." +category = "main" optional = true python-versions = ">=3.5" files = [ @@ -2031,6 +2391,7 @@ test = ["pytest"] name = "sqlalchemy" version = "2.0.21" description = "Database Abstraction Library" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2114,10 +2475,26 @@ postgresql-psycopgbinary = ["psycopg[binary] (>=3.0.7)"] pymysql = ["pymysql"] sqlcipher = ["sqlcipher3-binary"] +[[package]] +name = "termcolor" +version = "2.3.0" +description = "ANSI color formatting for output in terminal" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "termcolor-2.3.0-py3-none-any.whl", hash = "sha256:3afb05607b89aed0ffe25202399ee0867ad4d3cb4180d98aaf8eefa6a5f7d475"}, + {file = "termcolor-2.3.0.tar.gz", hash = "sha256:b5b08f68937f138fe92f6c089b99f1e2da0ae56c52b78bf7075fd95420fd9a5a"}, +] + +[package.extras] +tests = ["pytest", "pytest-cov"] + [[package]] name = "text-unidecode" version = "1.3" description = "The most basic Text::Unidecode port" +category = "dev" optional = false python-versions = "*" files = [ @@ -2129,6 +2506,7 @@ files = [ name = "time-machine" version = "2.10.0" description = "Travel through time in your tests." +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2195,6 +2573,7 @@ python-dateutil = "*" name = "tomli" version = "2.0.1" description = "A lil' TOML parser" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2202,10 +2581,23 @@ files = [ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] +[[package]] +name = "tomlkit" +version = "0.12.1" +description = "Style preserving TOML library" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tomlkit-0.12.1-py3-none-any.whl", hash = "sha256:712cbd236609acc6a3e2e97253dfc52d4c2082982a88f61b640ecf0817eab899"}, + {file = "tomlkit-0.12.1.tar.gz", hash = "sha256:38e1ff8edb991273ec9f6181244a6a391ac30e9f5098e7535640ea6be97a7c86"}, +] + [[package]] name = "tornado" version = "6.2" description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." +category = "main" optional = true python-versions = ">= 3.7" files = [ @@ -2226,6 +2618,7 @@ files = [ name = "typed-ast" version = "1.5.5" description = "a fork of Python 2 and 3 ast modules with type comment support" +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -2276,6 +2669,7 @@ files = [ name = "types-jsonschema" version = "4.17.0.10" description = "Typing stubs for jsonschema" +category = "dev" optional = false python-versions = "*" files = [ @@ -2287,6 +2681,7 @@ files = [ name = "types-python-dateutil" version = "2.8.19.14" description = "Typing stubs for python-dateutil" +category = "dev" optional = false python-versions = "*" files = [ @@ -2298,6 +2693,7 @@ files = [ name = "types-pytz" version = "2023.3.1.1" description = "Typing stubs for pytz" +category = "dev" optional = false python-versions = "*" files = [ @@ -2309,6 +2705,7 @@ files = [ name = "types-pyyaml" version = "6.0.12.12" description = "Typing stubs for PyYAML" +category = "dev" optional = false python-versions = "*" files = [ @@ -2320,6 +2717,7 @@ files = [ name = "types-requests" version = "2.31.0.6" description = "Typing stubs for requests" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2334,6 +2732,7 @@ types-urllib3 = "*" name = "types-simplejson" version = "3.19.0.2" description = "Typing stubs for simplejson" +category = "dev" optional = false python-versions = "*" files = [ @@ -2345,6 +2744,7 @@ files = [ name = "types-urllib3" version = "1.26.25.14" description = "Typing stubs for urllib3" +category = "dev" optional = false python-versions = "*" files = [ @@ -2356,6 +2756,7 @@ files = [ name = "typing-extensions" version = "4.7.1" description = "Backported and Experimental Type Hints for Python 3.7+" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2367,6 +2768,7 @@ files = [ name = "urllib3" version = "1.26.17" description = "HTTP library with thread-safe connection pooling, file post, and more." +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" files = [ @@ -2379,10 +2781,108 @@ brotli = ["brotli (==1.0.9)", "brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotl secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] +[[package]] +name = "wcwidth" +version = "0.2.6" +description = "Measures the displayed width of unicode strings in a terminal" +category = "dev" +optional = false +python-versions = "*" +files = [ + {file = "wcwidth-0.2.6-py2.py3-none-any.whl", hash = "sha256:795b138f6875577cd91bba52baf9e445cd5118fd32723b460e30a0af30ea230e"}, + {file = "wcwidth-0.2.6.tar.gz", hash = "sha256:a5220780a404dbe3353789870978e472cfe477761f06ee55077256e509b156d0"}, +] + +[[package]] +name = "wrapt" +version = "1.15.0" +description = "Module for decorators, wrappers and monkey patching." +category = "dev" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +files = [ + {file = "wrapt-1.15.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ca1cccf838cd28d5a0883b342474c630ac48cac5df0ee6eacc9c7290f76b11c1"}, + {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e826aadda3cae59295b95343db8f3d965fb31059da7de01ee8d1c40a60398b29"}, + {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5fc8e02f5984a55d2c653f5fea93531e9836abbd84342c1d1e17abc4a15084c2"}, + {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:96e25c8603a155559231c19c0349245eeb4ac0096fe3c1d0be5c47e075bd4f46"}, + {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:40737a081d7497efea35ab9304b829b857f21558acfc7b3272f908d33b0d9d4c"}, + {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:f87ec75864c37c4c6cb908d282e1969e79763e0d9becdfe9fe5473b7bb1e5f09"}, + {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:1286eb30261894e4c70d124d44b7fd07825340869945c79d05bda53a40caa079"}, + {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:493d389a2b63c88ad56cdc35d0fa5752daac56ca755805b1b0c530f785767d5e"}, + {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:58d7a75d731e8c63614222bcb21dd992b4ab01a399f1f09dd82af17bbfc2368a"}, + {file = "wrapt-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:21f6d9a0d5b3a207cdf7acf8e58d7d13d463e639f0c7e01d82cdb671e6cb7923"}, + {file = "wrapt-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ce42618f67741d4697684e501ef02f29e758a123aa2d669e2d964ff734ee00ee"}, + {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41d07d029dd4157ae27beab04d22b8e261eddfc6ecd64ff7000b10dc8b3a5727"}, + {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54accd4b8bc202966bafafd16e69da9d5640ff92389d33d28555c5fd4f25ccb7"}, + {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fbfbca668dd15b744418265a9607baa970c347eefd0db6a518aaf0cfbd153c0"}, + {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:76e9c727a874b4856d11a32fb0b389afc61ce8aaf281ada613713ddeadd1cfec"}, + {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e20076a211cd6f9b44a6be58f7eeafa7ab5720eb796975d0c03f05b47d89eb90"}, + {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a74d56552ddbde46c246b5b89199cb3fd182f9c346c784e1a93e4dc3f5ec9975"}, + {file = "wrapt-1.15.0-cp310-cp310-win32.whl", hash = "sha256:26458da5653aa5b3d8dc8b24192f574a58984c749401f98fff994d41d3f08da1"}, + {file = "wrapt-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:75760a47c06b5974aa5e01949bf7e66d2af4d08cb8c1d6516af5e39595397f5e"}, + {file = "wrapt-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ba1711cda2d30634a7e452fc79eabcadaffedf241ff206db2ee93dd2c89a60e7"}, + {file = "wrapt-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:56374914b132c702aa9aa9959c550004b8847148f95e1b824772d453ac204a72"}, + {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a89ce3fd220ff144bd9d54da333ec0de0399b52c9ac3d2ce34b569cf1a5748fb"}, + {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3bbe623731d03b186b3d6b0d6f51865bf598587c38d6f7b0be2e27414f7f214e"}, + {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3abbe948c3cbde2689370a262a8d04e32ec2dd4f27103669a45c6929bcdbfe7c"}, + {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b67b819628e3b748fd3c2192c15fb951f549d0f47c0449af0764d7647302fda3"}, + {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7eebcdbe3677e58dd4c0e03b4f2cfa346ed4049687d839adad68cc38bb559c92"}, + {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:74934ebd71950e3db69960a7da29204f89624dde411afbfb3b4858c1409b1e98"}, + {file = "wrapt-1.15.0-cp311-cp311-win32.whl", hash = "sha256:bd84395aab8e4d36263cd1b9308cd504f6cf713b7d6d3ce25ea55670baec5416"}, + {file = "wrapt-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:a487f72a25904e2b4bbc0817ce7a8de94363bd7e79890510174da9d901c38705"}, + {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:4ff0d20f2e670800d3ed2b220d40984162089a6e2c9646fdb09b85e6f9a8fc29"}, + {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9ed6aa0726b9b60911f4aed8ec5b8dd7bf3491476015819f56473ffaef8959bd"}, + {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:896689fddba4f23ef7c718279e42f8834041a21342d95e56922e1c10c0cc7afb"}, + {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:75669d77bb2c071333417617a235324a1618dba66f82a750362eccbe5b61d248"}, + {file = "wrapt-1.15.0-cp35-cp35m-win32.whl", hash = "sha256:fbec11614dba0424ca72f4e8ba3c420dba07b4a7c206c8c8e4e73f2e98f4c559"}, + {file = "wrapt-1.15.0-cp35-cp35m-win_amd64.whl", hash = "sha256:fd69666217b62fa5d7c6aa88e507493a34dec4fa20c5bd925e4bc12fce586639"}, + {file = "wrapt-1.15.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b0724f05c396b0a4c36a3226c31648385deb6a65d8992644c12a4963c70326ba"}, + {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbeccb1aa40ab88cd29e6c7d8585582c99548f55f9b2581dfc5ba68c59a85752"}, + {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38adf7198f8f154502883242f9fe7333ab05a5b02de7d83aa2d88ea621f13364"}, + {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:578383d740457fa790fdf85e6d346fda1416a40549fe8db08e5e9bd281c6a475"}, + {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:a4cbb9ff5795cd66f0066bdf5947f170f5d63a9274f99bdbca02fd973adcf2a8"}, + {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:af5bd9ccb188f6a5fdda9f1f09d9f4c86cc8a539bd48a0bfdc97723970348418"}, + {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:b56d5519e470d3f2fe4aa7585f0632b060d532d0696c5bdfb5e8319e1d0f69a2"}, + {file = "wrapt-1.15.0-cp36-cp36m-win32.whl", hash = "sha256:77d4c1b881076c3ba173484dfa53d3582c1c8ff1f914c6461ab70c8428b796c1"}, + {file = "wrapt-1.15.0-cp36-cp36m-win_amd64.whl", hash = "sha256:077ff0d1f9d9e4ce6476c1a924a3332452c1406e59d90a2cf24aeb29eeac9420"}, + {file = "wrapt-1.15.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5c5aa28df055697d7c37d2099a7bc09f559d5053c3349b1ad0c39000e611d317"}, + {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a8564f283394634a7a7054b7983e47dbf39c07712d7b177b37e03f2467a024e"}, + {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780c82a41dc493b62fc5884fb1d3a3b81106642c5c5c78d6a0d4cbe96d62ba7e"}, + {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e169e957c33576f47e21864cf3fc9ff47c223a4ebca8960079b8bd36cb014fd0"}, + {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b02f21c1e2074943312d03d243ac4388319f2456576b2c6023041c4d57cd7019"}, + {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f2e69b3ed24544b0d3dbe2c5c0ba5153ce50dcebb576fdc4696d52aa22db6034"}, + {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d787272ed958a05b2c86311d3a4135d3c2aeea4fc655705f074130aa57d71653"}, + {file = "wrapt-1.15.0-cp37-cp37m-win32.whl", hash = "sha256:02fce1852f755f44f95af51f69d22e45080102e9d00258053b79367d07af39c0"}, + {file = "wrapt-1.15.0-cp37-cp37m-win_amd64.whl", hash = "sha256:abd52a09d03adf9c763d706df707c343293d5d106aea53483e0ec8d9e310ad5e"}, + {file = "wrapt-1.15.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cdb4f085756c96a3af04e6eca7f08b1345e94b53af8921b25c72f096e704e145"}, + {file = "wrapt-1.15.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:230ae493696a371f1dbffaad3dafbb742a4d27a0afd2b1aecebe52b740167e7f"}, + {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63424c681923b9f3bfbc5e3205aafe790904053d42ddcc08542181a30a7a51bd"}, + {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6bcbfc99f55655c3d93feb7ef3800bd5bbe963a755687cbf1f490a71fb7794b"}, + {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c99f4309f5145b93eca6e35ac1a988f0dc0a7ccf9ccdcd78d3c0adf57224e62f"}, + {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b130fe77361d6771ecf5a219d8e0817d61b236b7d8b37cc045172e574ed219e6"}, + {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:96177eb5645b1c6985f5c11d03fc2dbda9ad24ec0f3a46dcce91445747e15094"}, + {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5fe3e099cf07d0fb5a1e23d399e5d4d1ca3e6dfcbe5c8570ccff3e9208274f7"}, + {file = "wrapt-1.15.0-cp38-cp38-win32.whl", hash = "sha256:abd8f36c99512755b8456047b7be10372fca271bf1467a1caa88db991e7c421b"}, + {file = "wrapt-1.15.0-cp38-cp38-win_amd64.whl", hash = "sha256:b06fa97478a5f478fb05e1980980a7cdf2712015493b44d0c87606c1513ed5b1"}, + {file = "wrapt-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2e51de54d4fb8fb50d6ee8327f9828306a959ae394d3e01a1ba8b2f937747d86"}, + {file = "wrapt-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0970ddb69bba00670e58955f8019bec4a42d1785db3faa043c33d81de2bf843c"}, + {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76407ab327158c510f44ded207e2f76b657303e17cb7a572ffe2f5a8a48aa04d"}, + {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd525e0e52a5ff16653a3fc9e3dd827981917d34996600bbc34c05d048ca35cc"}, + {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d37ac69edc5614b90516807de32d08cb8e7b12260a285ee330955604ed9dd29"}, + {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:078e2a1a86544e644a68422f881c48b84fef6d18f8c7a957ffd3f2e0a74a0d4a"}, + {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2cf56d0e237280baed46f0b5316661da892565ff58309d4d2ed7dba763d984b8"}, + {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7dc0713bf81287a00516ef43137273b23ee414fe41a3c14be10dd95ed98a2df9"}, + {file = "wrapt-1.15.0-cp39-cp39-win32.whl", hash = "sha256:46ed616d5fb42f98630ed70c3529541408166c22cdfd4540b88d5f21006b0eff"}, + {file = "wrapt-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:eef4d64c650f33347c1f9266fa5ae001440b232ad9b98f1f43dfe7a79435c0a6"}, + {file = "wrapt-1.15.0-py3-none-any.whl", hash = "sha256:64b1df0f83706b4ef4cfb4fb0e4c2669100fd7ecacfb59e091fad300d4e04640"}, + {file = "wrapt-1.15.0.tar.gz", hash = "sha256:d06730c6aed78cee4126234cf2d071e01b44b915e725a6cb439a879ec9754a3a"}, +] + [[package]] name = "xdoctest" version = "1.1.1" description = "A rewrite of the builtin doctest module" +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -2406,10 +2906,100 @@ tests-binary = ["cmake", "cmake", "ninja", "ninja", "pybind11", "pybind11", "sci tests-binary-strict = ["cmake (==3.21.2)", "cmake (==3.25.0)", "ninja (==1.10.2)", "ninja (==1.11.1)", "pybind11 (==2.10.3)", "pybind11 (==2.7.1)", "scikit-build (==0.11.1)", "scikit-build (==0.16.1)"] tests-strict = ["codecov (==2.0.15)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==6.2.5)", "pytest-cov (==3.0.0)", "typing (==3.7.4)"] +[[package]] +name = "yarl" +version = "1.9.2" +description = "Yet another URL library" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8c2ad583743d16ddbdf6bb14b5cd76bf43b0d0006e918809d5d4ddf7bde8dd82"}, + {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:82aa6264b36c50acfb2424ad5ca537a2060ab6de158a5bd2a72a032cc75b9eb8"}, + {file = "yarl-1.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c0c77533b5ed4bcc38e943178ccae29b9bcf48ffd1063f5821192f23a1bd27b9"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee4afac41415d52d53a9833ebae7e32b344be72835bbb589018c9e938045a560"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9bf345c3a4f5ba7f766430f97f9cc1320786f19584acc7086491f45524a551ac"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a96c19c52ff442a808c105901d0bdfd2e28575b3d5f82e2f5fd67e20dc5f4ea"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:891c0e3ec5ec881541f6c5113d8df0315ce5440e244a716b95f2525b7b9f3608"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c3a53ba34a636a256d767c086ceb111358876e1fb6b50dfc4d3f4951d40133d5"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:566185e8ebc0898b11f8026447eacd02e46226716229cea8db37496c8cdd26e0"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:2b0738fb871812722a0ac2154be1f049c6223b9f6f22eec352996b69775b36d4"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:32f1d071b3f362c80f1a7d322bfd7b2d11e33d2adf395cc1dd4df36c9c243095"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:e9fdc7ac0d42bc3ea78818557fab03af6181e076a2944f43c38684b4b6bed8e3"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:56ff08ab5df8429901ebdc5d15941b59f6253393cb5da07b4170beefcf1b2528"}, + {file = "yarl-1.9.2-cp310-cp310-win32.whl", hash = "sha256:8ea48e0a2f931064469bdabca50c2f578b565fc446f302a79ba6cc0ee7f384d3"}, + {file = "yarl-1.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:50f33040f3836e912ed16d212f6cc1efb3231a8a60526a407aeb66c1c1956dde"}, + {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:646d663eb2232d7909e6601f1a9107e66f9791f290a1b3dc7057818fe44fc2b6"}, + {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aff634b15beff8902d1f918012fc2a42e0dbae6f469fce134c8a0dc51ca423bb"}, + {file = "yarl-1.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a83503934c6273806aed765035716216cc9ab4e0364f7f066227e1aaea90b8d0"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b25322201585c69abc7b0e89e72790469f7dad90d26754717f3310bfe30331c2"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22a94666751778629f1ec4280b08eb11815783c63f52092a5953faf73be24191"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ec53a0ea2a80c5cd1ab397925f94bff59222aa3cf9c6da938ce05c9ec20428d"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:159d81f22d7a43e6eabc36d7194cb53f2f15f498dbbfa8edc8a3239350f59fe7"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:832b7e711027c114d79dffb92576acd1bd2decc467dec60e1cac96912602d0e6"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:95d2ecefbcf4e744ea952d073c6922e72ee650ffc79028eb1e320e732898d7e8"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d4e2c6d555e77b37288eaf45b8f60f0737c9efa3452c6c44626a5455aeb250b9"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:783185c75c12a017cc345015ea359cc801c3b29a2966c2655cd12b233bf5a2be"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:b8cc1863402472f16c600e3e93d542b7e7542a540f95c30afd472e8e549fc3f7"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:822b30a0f22e588b32d3120f6d41e4ed021806418b4c9f0bc3048b8c8cb3f92a"}, + {file = "yarl-1.9.2-cp311-cp311-win32.whl", hash = "sha256:a60347f234c2212a9f0361955007fcf4033a75bf600a33c88a0a8e91af77c0e8"}, + {file = "yarl-1.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:be6b3fdec5c62f2a67cb3f8c6dbf56bbf3f61c0f046f84645cd1ca73532ea051"}, + {file = "yarl-1.9.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:38a3928ae37558bc1b559f67410df446d1fbfa87318b124bf5032c31e3447b74"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac9bb4c5ce3975aeac288cfcb5061ce60e0d14d92209e780c93954076c7c4367"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3da8a678ca8b96c8606bbb8bfacd99a12ad5dd288bc6f7979baddd62f71c63ef"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:13414591ff516e04fcdee8dc051c13fd3db13b673c7a4cb1350e6b2ad9639ad3"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf74d08542c3a9ea97bb8f343d4fcbd4d8f91bba5ec9d5d7f792dbe727f88938"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e7221580dc1db478464cfeef9b03b95c5852cc22894e418562997df0d074ccc"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:494053246b119b041960ddcd20fd76224149cfea8ed8777b687358727911dd33"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:52a25809fcbecfc63ac9ba0c0fb586f90837f5425edfd1ec9f3372b119585e45"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:e65610c5792870d45d7b68c677681376fcf9cc1c289f23e8e8b39c1485384185"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:1b1bba902cba32cdec51fca038fd53f8beee88b77efc373968d1ed021024cc04"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:662e6016409828ee910f5d9602a2729a8a57d74b163c89a837de3fea050c7582"}, + {file = "yarl-1.9.2-cp37-cp37m-win32.whl", hash = "sha256:f364d3480bffd3aa566e886587eaca7c8c04d74f6e8933f3f2c996b7f09bee1b"}, + {file = "yarl-1.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6a5883464143ab3ae9ba68daae8e7c5c95b969462bbe42e2464d60e7e2698368"}, + {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5610f80cf43b6202e2c33ba3ec2ee0a2884f8f423c8f4f62906731d876ef4fac"}, + {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b9a4e67ad7b646cd6f0938c7ebfd60e481b7410f574c560e455e938d2da8e0f4"}, + {file = "yarl-1.9.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:83fcc480d7549ccebe9415d96d9263e2d4226798c37ebd18c930fce43dfb9574"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fcd436ea16fee7d4207c045b1e340020e58a2597301cfbcfdbe5abd2356c2fb"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84e0b1599334b1e1478db01b756e55937d4614f8654311eb26012091be109d59"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3458a24e4ea3fd8930e934c129b676c27452e4ebda80fbe47b56d8c6c7a63a9e"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:838162460b3a08987546e881a2bfa573960bb559dfa739e7800ceeec92e64417"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f4e2d08f07a3d7d3e12549052eb5ad3eab1c349c53ac51c209a0e5991bbada78"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:de119f56f3c5f0e2fb4dee508531a32b069a5f2c6e827b272d1e0ff5ac040333"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:149ddea5abf329752ea5051b61bd6c1d979e13fbf122d3a1f9f0c8be6cb6f63c"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:674ca19cbee4a82c9f54e0d1eee28116e63bc6fd1e96c43031d11cbab8b2afd5"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:9b3152f2f5677b997ae6c804b73da05a39daa6a9e85a512e0e6823d81cdad7cc"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5415d5a4b080dc9612b1b63cba008db84e908b95848369aa1da3686ae27b6d2b"}, + {file = "yarl-1.9.2-cp38-cp38-win32.whl", hash = "sha256:f7a3d8146575e08c29ed1cd287068e6d02f1c7bdff8970db96683b9591b86ee7"}, + {file = "yarl-1.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:63c48f6cef34e6319a74c727376e95626f84ea091f92c0250a98e53e62c77c72"}, + {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:75df5ef94c3fdc393c6b19d80e6ef1ecc9ae2f4263c09cacb178d871c02a5ba9"}, + {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c027a6e96ef77d401d8d5a5c8d6bc478e8042f1e448272e8d9752cb0aff8b5c8"}, + {file = "yarl-1.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3b078dbe227f79be488ffcfc7a9edb3409d018e0952cf13f15fd6512847f3f7"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59723a029760079b7d991a401386390c4be5bfec1e7dd83e25a6a0881859e716"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b03917871bf859a81ccb180c9a2e6c1e04d2f6a51d953e6a5cdd70c93d4e5a2a"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c1012fa63eb6c032f3ce5d2171c267992ae0c00b9e164efe4d73db818465fac3"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a74dcbfe780e62f4b5a062714576f16c2f3493a0394e555ab141bf0d746bb955"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8c56986609b057b4839968ba901944af91b8e92f1725d1a2d77cbac6972b9ed1"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2c315df3293cd521033533d242d15eab26583360b58f7ee5d9565f15fee1bef4"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:b7232f8dfbd225d57340e441d8caf8652a6acd06b389ea2d3222b8bc89cbfca6"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:53338749febd28935d55b41bf0bcc79d634881195a39f6b2f767870b72514caf"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:066c163aec9d3d073dc9ffe5dd3ad05069bcb03fcaab8d221290ba99f9f69ee3"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8288d7cd28f8119b07dd49b7230d6b4562f9b61ee9a4ab02221060d21136be80"}, + {file = "yarl-1.9.2-cp39-cp39-win32.whl", hash = "sha256:b124e2a6d223b65ba8768d5706d103280914d61f5cae3afbc50fc3dfcc016623"}, + {file = "yarl-1.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:61016e7d582bc46a5378ffdd02cd0314fb8ba52f40f9cf4d9a5e7dbef88dee18"}, + {file = "yarl-1.9.2.tar.gz", hash = "sha256:04ab9d4b9f587c06d801c2abfe9317b77cdf996c65a90d5e84ecc45010823571"}, +] + +[package.dependencies] +idna = ">=2.0" +multidict = ">=4.0" +typing-extensions = {version = ">=3.7.4", markers = "python_version < \"3.8\""} + [[package]] name = "zipp" version = "3.15.0" description = "Backport of pathlib-compatible object wrapper for zip files" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2429,4 +3019,4 @@ testing = ["pytest", "pytest-durations"] [metadata] lock-version = "2.0" python-versions = ">=3.7.1,<4" -content-hash = "ed32d2c7223d26e4562494c0e37680ae344a7eba60917445bb5a4bd5adbc0129" +content-hash = "b1e49eacb32e9a38016d024dc71b58408c92b2a41c5b6c0de7f935b9449f91c0" diff --git a/pyproject.toml b/pyproject.toml index a6049f8c6..a5ac28188 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -79,6 +79,7 @@ fs-s3fs = {version = ">=1.1.1", optional = true} # Testing dependencies installed as optional 'testing' extras pytest = {version=">=7.2.1", optional = true} pytest-durations = {version = ">=1.2.0", optional = true} +simpleeval = "^0.9.13" [tool.poetry.extras] docs = [ diff --git a/singer_sdk/helpers/_simpleeval.py b/singer_sdk/helpers/_simpleeval.py deleted file mode 100644 index c3fb41c3f..000000000 --- a/singer_sdk/helpers/_simpleeval.py +++ /dev/null @@ -1,679 +0,0 @@ -""" -Simpleeval module originally imported on 2021-09-16 from: -- https://github.com/danthedeckie/simpleeval - -For more information: -- https://gitlab.com/meltano/sdk/-/issues/213 - -------------------------------------- -SimpleEval - (C) 2013-2019 Daniel Fairhead -------------------------------------- - -An short, easy to use, safe and reasonably extensible expression evaluator. -Designed for things like in a website where you want to allow the user to -generate a string, or a number from some other input, without allowing full -eval() or other unsafe or needlessly complex linguistics. - -------------------------------------- - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -------------------------------------- - -Initial idea copied from J.F. Sebastian on Stack Overflow -( http://stackoverflow.com/a/9558001/1973500 ) with -modifications and many improvements. - -------------------------------------- -Contributors: -- corro (Robin Baumgartner) (py3k) -- dratchkov (David R) (nested dicts) -- marky1991 (Mark Young) (slicing) -- T045T (Nils Berg) (!=, py3kstr, obj. -- perkinslr (Logan Perkins) (.__globals__ or .func_ breakouts) -- impala2 (Kirill Stepanov) (massive _eval refactor) -- gk (ugik) (Other iterables than str can DOS too, and can be made) -- daveisfera (Dave Johansen) 'not' Boolean op, Pycharm, pep8, various other fixes -- xaled (Khalid Grandi) method chaining correctly, double-eval bugfix. -- EdwardBetts (Edward Betts) spelling correction. -- charlax (Charles-Axel Dein charlax) Makefile and cleanups -- mommothazaz123 (Andrew Zhu) f"string" support, Python 3.8 support -- lubieowoce (Uryga) various potential vulnerabilities -- JCavallo (Jean Cavallo) names dict shouldn't be modified -- Birne94 (Daniel Birnstiel) for fixing leaking generators. -- patricksurry (Patrick Surry) or should return last value, even if falsy. -- shughes-uk (Samantha Hughes) python w/o 'site' should not fail to import. - -------------------------------------- -Basic Usage: - ->>> s = SimpleEval() ->>> s.eval("20 + 30") -50 - -You can add your own functions easily too: - -if file.txt contents is "11" - ->>> def get_file(): -... with open("file.txt", 'r') as f: -... return f.read() - ->>> s.functions["get_file"] = get_file ->>> s.eval("int(get_file()) + 31") -42 - -For more information, see the full package documentation on pypi, or the github -repo. - ------------ - -If you don't need to re-use the evaluator (with it's names, functions, etc), -then you can use the simple_eval() function: - ->>> simple_eval("21 + 19") -40 - -You can pass names, operators and functions to the simple_eval function as -well: - ->>> simple_eval("40 + two", names={"two": 2}) -42 - -""" -# flake8: noqa # Ignoring flake errors in imported module -# isort: dont-add-imports - -import ast -import operator as op -import sys -import warnings -from random import random - -PYTHON3 = sys.version_info[0] == 3 - -######################################## -# Module wide 'globals' - -MAX_STRING_LENGTH = 100000 -MAX_COMPREHENSION_LENGTH = 10000 -MAX_POWER = 4000000 # highest exponent -DISALLOW_PREFIXES = ["_", "func_"] -DISALLOW_METHODS = ["format", "format_map", "mro"] - -# Disallow functions: -# This, strictly speaking, is not necessary. These /should/ never be accessable anyway, -# if DISALLOW_PREFIXES and DISALLOW_METHODS are all right. This is here to try and help -# people not be stupid. Allowing these functions opens up all sorts of holes - if any of -# their functionality is required, then please wrap them up in a safe container. And think -# very hard about it first. And don't say I didn't warn you. -# builtins is a dict in python >3.6 but a module before -DISALLOW_FUNCTIONS = {type, isinstance, eval, getattr, setattr, repr, compile, open} -if hasattr(__builtins__, "help") or ( - hasattr(__builtins__, "__contains__") and "help" in __builtins__ -): - # PyInstaller environment doesn't include this module. - DISALLOW_FUNCTIONS.add(help) - - -if PYTHON3: - exec("DISALLOW_FUNCTIONS.add(exec)") # exec is not a function in Python2... - - -######################################## -# Exceptions: - - -class InvalidExpression(Exception): - """ Generic Exception """ - - pass - - -class FunctionNotDefined(InvalidExpression): - """ sorry! That function isn't defined! """ - - def __init__(self, func_name, expression): - self.message = "Function '{0}' not defined," " for expression '{1}'.".format( - func_name, expression - ) - setattr(self, "func_name", func_name) # bypass 2to3 confusion. - self.expression = expression - - # pylint: disable=bad-super-call - super(InvalidExpression, self).__init__(self.message) - - -class NameNotDefined(InvalidExpression): - """ a name isn't defined. """ - - def __init__(self, name, expression): - self.name = name - self.message = "'{0}' is not defined for expression '{1}'".format( - name, expression - ) - self.expression = expression - - # pylint: disable=bad-super-call - super(InvalidExpression, self).__init__(self.message) - - -class AttributeDoesNotExist(InvalidExpression): - """attribute does not exist""" - - def __init__(self, attr, expression): - self.message = "Attribute '{0}' does not exist in expression '{1}'".format( - attr, expression - ) - self.attr = attr - self.expression = expression - - -class FeatureNotAvailable(InvalidExpression): - """ What you're trying to do is not allowed. """ - - pass - - -class NumberTooHigh(InvalidExpression): - """Sorry! That number is too high. I don't want to spend the - next 10 years evaluating this expression!""" - - pass - - -class IterableTooLong(InvalidExpression): - """ That iterable is **way** too long, baby. """ - - pass - - -class AssignmentAttempted(UserWarning): - pass - - -######################################## -# Default simple functions to include: - - -def random_int(top): - """ return a random int below """ - - return int(random() * top) - - -def safe_power(a, b): # pylint: disable=invalid-name - """ a limited exponent/to-the-power-of function, for safety reasons """ - - if abs(a) > MAX_POWER or abs(b) > MAX_POWER: - raise NumberTooHigh("Sorry! I don't want to evaluate {0} ** {1}".format(a, b)) - return a ** b - - -def safe_mult(a, b): # pylint: disable=invalid-name - """ limit the number of times an iterable can be repeated... """ - - if hasattr(a, "__len__") and b * len(a) > MAX_STRING_LENGTH: - raise IterableTooLong("Sorry, I will not evalute something that long.") - if hasattr(b, "__len__") and a * len(b) > MAX_STRING_LENGTH: - raise IterableTooLong("Sorry, I will not evalute something that long.") - - return a * b - - -def safe_add(a, b): # pylint: disable=invalid-name - """ iterable length limit again """ - - if hasattr(a, "__len__") and hasattr(b, "__len__"): - if len(a) + len(b) > MAX_STRING_LENGTH: - raise IterableTooLong( - "Sorry, adding those two together would" " make something too long." - ) - return a + b - - -######################################## -# Defaults for the evaluator: - -DEFAULT_OPERATORS = { - ast.Add: safe_add, - ast.Sub: op.sub, - ast.Mult: safe_mult, - ast.Div: op.truediv, - ast.FloorDiv: op.floordiv, - ast.Pow: safe_power, - ast.Mod: op.mod, - ast.Eq: op.eq, - ast.NotEq: op.ne, - ast.Gt: op.gt, - ast.Lt: op.lt, - ast.GtE: op.ge, - ast.LtE: op.le, - ast.Not: op.not_, - ast.USub: op.neg, - ast.UAdd: op.pos, - ast.In: lambda x, y: op.contains(y, x), - ast.NotIn: lambda x, y: not op.contains(y, x), - ast.Is: lambda x, y: x is y, - ast.IsNot: lambda x, y: x is not y, -} - -DEFAULT_FUNCTIONS = { - "rand": random, - "randint": random_int, - "int": int, - "float": float, - "str": str if PYTHON3 else unicode, # type: ignore # 'unicode' not defined -} - -DEFAULT_NAMES = {"True": True, "False": False, "None": None} - -ATTR_INDEX_FALLBACK = True - - -######################################## -# And the actual evaluator: - - -class SimpleEval(object): # pylint: disable=too-few-public-methods - """A very simple expression parser. - >>> s = SimpleEval() - >>> s.eval("20 + 30 - ( 10 * 5)") - 0 - """ - - expr = "" - - def __init__(self, operators=None, functions=None, names=None): - """ - Create the evaluator instance. Set up valid operators (+,-, etc) - functions (add, random, get_val, whatever) and names.""" - - if not operators: - operators = DEFAULT_OPERATORS.copy() - if not functions: - functions = DEFAULT_FUNCTIONS.copy() - if not names: - names = DEFAULT_NAMES.copy() - - self.operators = operators - self.functions = functions - self.names = names - - self.nodes = { - ast.Expr: self._eval_expr, - ast.Assign: self._eval_assign, - ast.AugAssign: self._eval_aug_assign, - ast.Import: self._eval_import, - ast.Num: self._eval_num, - ast.Str: self._eval_str, - ast.Name: self._eval_name, - ast.UnaryOp: self._eval_unaryop, - ast.BinOp: self._eval_binop, - ast.BoolOp: self._eval_boolop, - ast.Compare: self._eval_compare, - ast.IfExp: self._eval_ifexp, - ast.Call: self._eval_call, - ast.keyword: self._eval_keyword, - ast.Subscript: self._eval_subscript, - ast.Attribute: self._eval_attribute, - ast.Index: self._eval_index, - ast.Slice: self._eval_slice, - } - - # py3k stuff: - if hasattr(ast, "NameConstant"): - self.nodes[ast.NameConstant] = self._eval_constant - - # py3.6, f-strings - if hasattr(ast, "JoinedStr"): - self.nodes[ast.JoinedStr] = self._eval_joinedstr # f-string - self.nodes[ - ast.FormattedValue - ] = self._eval_formattedvalue # formatted value in f-string - - # py3.8 uses ast.Constant instead of ast.Num, ast.Str, ast.NameConstant - if hasattr(ast, "Constant"): - self.nodes[ast.Constant] = self._eval_constant - - # Defaults: - - self.ATTR_INDEX_FALLBACK = ATTR_INDEX_FALLBACK - - # Check for forbidden functions: - - for f in self.functions.values(): - if f in DISALLOW_FUNCTIONS: - raise FeatureNotAvailable( - "This function {} is a really bad idea.".format(f) - ) - - def eval(self, expr): - """evaluate an expresssion, using the operators, functions and - names previously set up.""" - - # set a copy of the expression aside, so we can give nice errors... - - self.expr = expr - - # and evaluate: - return self._eval(ast.parse(expr.strip()).body[0]) - - def _eval(self, node): - """ The internal evaluator used on each node in the parsed tree. """ - - try: - handler = self.nodes[type(node)] - except KeyError: - raise FeatureNotAvailable( - "Sorry, {0} is not available in this " - "evaluator".format(type(node).__name__) - ) - - return handler(node) - - def _eval_expr(self, node): - return self._eval(node.value) - - def _eval_assign(self, node): - warnings.warn( - "Assignment ({}) attempted, but this is ignored".format(self.expr), - AssignmentAttempted, - ) - return self._eval(node.value) - - def _eval_aug_assign(self, node): - warnings.warn( - "Assignment ({}) attempted, but this is ignored".format(self.expr), - AssignmentAttempted, - ) - return self._eval(node.value) - - def _eval_import(self, node): - raise FeatureNotAvailable("Sorry, 'import' is not allowed.") - return self._eval(node.value) - - @staticmethod - def _eval_num(node): - return node.n - - @staticmethod - def _eval_str(node): - if len(node.s) > MAX_STRING_LENGTH: - raise IterableTooLong( - "String Literal in statement is too long!" - " ({0}, when {1} is max)".format(len(node.s), MAX_STRING_LENGTH) - ) - return node.s - - @staticmethod - def _eval_constant(node): - if hasattr(node.value, "__len__") and len(node.value) > MAX_STRING_LENGTH: - raise IterableTooLong( - "Literal in statement is too long!" - " ({0}, when {1} is max)".format(len(node.value), MAX_STRING_LENGTH) - ) - return node.value - - def _eval_unaryop(self, node): - return self.operators[type(node.op)](self._eval(node.operand)) - - def _eval_binop(self, node): - return self.operators[type(node.op)]( - self._eval(node.left), self._eval(node.right) - ) - - def _eval_boolop(self, node): - if isinstance(node.op, ast.And): - vout = False - for value in node.values: - vout = self._eval(value) - if not vout: - return vout - return vout - elif isinstance(node.op, ast.Or): - for value in node.values: - vout = self._eval(value) - if vout: - return vout - return vout - - def _eval_compare(self, node): - right = self._eval(node.left) - to_return = True - for operation, comp in zip(node.ops, node.comparators): - if not to_return: - break - left = right - right = self._eval(comp) - to_return = self.operators[type(operation)](left, right) - return to_return - - def _eval_ifexp(self, node): - return ( - self._eval(node.body) if self._eval(node.test) else self._eval(node.orelse) - ) - - def _eval_call(self, node): - if isinstance(node.func, ast.Attribute): - func = self._eval(node.func) - else: - try: - func = self.functions[node.func.id] - except KeyError: - raise FunctionNotDefined(node.func.id, self.expr) - except AttributeError as e: - raise FeatureNotAvailable("Lambda Functions not implemented") - - if func in DISALLOW_FUNCTIONS: - raise FeatureNotAvailable("This function is forbidden") - - return func( - *(self._eval(a) for a in node.args), - **dict(self._eval(k) for k in node.keywords) - ) - - def _eval_keyword(self, node): - return node.arg, self._eval(node.value) - - def _eval_name(self, node): - try: - # This happens at least for slicing - # This is a safe thing to do because it is impossible - # that there is a true exression assigning to none - # (the compiler rejects it, so you can't even - # pass that to ast.parse) - if hasattr(self.names, "__getitem__"): - return self.names[node.id] - elif callable(self.names): - return self.names(node) - else: - raise InvalidExpression( - 'Trying to use name (variable) "{0}"' - ' when no "names" defined for' - " evaluator".format(node.id) - ) - - except KeyError: - if node.id in self.functions: - return self.functions[node.id] - - raise NameNotDefined(node.id, self.expr) - - def _eval_subscript(self, node): - container = self._eval(node.value) - key = self._eval(node.slice) - try: - return container[key] - except KeyError: - raise - - def _eval_attribute(self, node): - for prefix in DISALLOW_PREFIXES: - if node.attr.startswith(prefix): - raise FeatureNotAvailable( - "Sorry, access to __attributes " - " or func_ attributes is not available. " - "({0})".format(node.attr) - ) - if node.attr in DISALLOW_METHODS: - raise FeatureNotAvailable( - "Sorry, this method is not available. " "({0})".format(node.attr) - ) - # eval node - node_evaluated = self._eval(node.value) - - # Maybe the base object is an actual object, not just a dict - try: - return getattr(node_evaluated, node.attr) - except (AttributeError, TypeError): - pass - - # TODO: is this a good idea? Try and look for [x] if .x doesn't work? - if self.ATTR_INDEX_FALLBACK: - try: - return node_evaluated[node.attr] - except (KeyError, TypeError): - pass - - # If it is neither, raise an exception - raise AttributeDoesNotExist(node.attr, self.expr) - - def _eval_index(self, node): - return self._eval(node.value) - - def _eval_slice(self, node): - lower = upper = step = None - if node.lower is not None: - lower = self._eval(node.lower) - if node.upper is not None: - upper = self._eval(node.upper) - if node.step is not None: - step = self._eval(node.step) - return slice(lower, upper, step) - - def _eval_joinedstr(self, node): - length = 0 - evaluated_values = [] - for n in node.values: - val = str(self._eval(n)) - if len(val) + length > MAX_STRING_LENGTH: - raise IterableTooLong("Sorry, I will not evaluate something this long.") - evaluated_values.append(val) - return "".join(evaluated_values) - - def _eval_formattedvalue(self, node): - if node.format_spec: - fmt = "{:" + self._eval(node.format_spec) + "}" - return fmt.format(self._eval(node.value)) - return self._eval(node.value) - - -class EvalWithCompoundTypes(SimpleEval): - """ - SimpleEval with additional Compound Types, and their respective - function editions. (list, tuple, dict, set). - """ - - def __init__(self, operators=None, functions=None, names=None): - super(EvalWithCompoundTypes, self).__init__(operators, functions, names) - - self.functions.update(list=list, tuple=tuple, dict=dict, set=set) - - self.nodes.update( - { - ast.Dict: self._eval_dict, - ast.Tuple: self._eval_tuple, - ast.List: self._eval_list, - ast.Set: self._eval_set, - ast.ListComp: self._eval_comprehension, - ast.GeneratorExp: self._eval_comprehension, - } - ) - - def eval(self, expr): - self._max_count = 0 - return super(EvalWithCompoundTypes, self).eval(expr) - - def _eval_dict(self, node): - return {self._eval(k): self._eval(v) for (k, v) in zip(node.keys, node.values)} - - def _eval_tuple(self, node): - return tuple(self._eval(x) for x in node.elts) - - def _eval_list(self, node): - return list(self._eval(x) for x in node.elts) - - def _eval_set(self, node): - return set(self._eval(x) for x in node.elts) - - def _eval_comprehension(self, node): - to_return = [] - - extra_names = {} - - previous_name_evaller = self.nodes[ast.Name] - - def eval_names_extra(node): - """ - Here we hide our extra scope for within this comprehension - """ - if node.id in extra_names: - return extra_names[node.id] - return previous_name_evaller(node) - - self.nodes.update({ast.Name: eval_names_extra}) - - def recurse_targets(target, value): - """ - Recursively (enter, (into, (nested, name), unpacking)) = \ - and, (assign, (values, to), each - """ - if isinstance(target, ast.Name): - extra_names[target.id] = value - else: - for t, v in zip(target.elts, value): - recurse_targets(t, v) - - def do_generator(gi=0): - g = node.generators[gi] - for i in self._eval(g.iter): - self._max_count += 1 - - if self._max_count > MAX_COMPREHENSION_LENGTH: - raise IterableTooLong("Comprehension generates too many elements") - recurse_targets(g.target, i) - if all(self._eval(iff) for iff in g.ifs): - if len(node.generators) > gi + 1: - do_generator(gi + 1) - else: - to_return.append(self._eval(node.elt)) - - try: - do_generator() - finally: - self.nodes.update({ast.Name: previous_name_evaller}) - - return to_return - - -def simple_eval(expr, operators=None, functions=None, names=None): - """ Simply evaluate an expresssion """ - s = SimpleEval(operators=operators, functions=functions, names=names) - return s.eval(expr) diff --git a/singer_sdk/mapper.py b/singer_sdk/mapper.py index 9b56d5089..b6e8b11db 100644 --- a/singer_sdk/mapper.py +++ b/singer_sdk/mapper.py @@ -6,15 +6,17 @@ from __future__ import annotations import abc +import ast import copy import datetime import hashlib import logging import typing as t +import simpleeval + import singer_sdk.typing as th from singer_sdk.exceptions import MapExpressionError, StreamMapConfigError -from singer_sdk.helpers import _simpleeval as simpleeval from singer_sdk.helpers._catalog import get_selected_schema from singer_sdk.helpers._flattening import ( FlatteningOptions, @@ -54,27 +56,6 @@ def md5(string: str) -> str: return hashlib.md5(string.encode("utf-8")).hexdigest() # noqa: S324 -def compound_eval( - expr: str, - operators: t.Dict[str, t.Callable[[dict], dict | None]] = None, - functions: t.Dict[str, t.Callable[[dict], dict | None]] = None, - names=t.Dict[str, t.Any] - ) -> t.Union[str, int, float, t.List, t.Set, t.Dict]: - """Evaluate inline maps using the `EvalWithCompoundTypes` class - - Args: - expr: expression to evaluate - operators: dictionary of operators and the functions they map to in the evaluation context - functions: dictionary of function names and definitions available in the evaluation context - names: dictionary of variable names available in the evaluation context - - Returns: - result of the evaluated expression - """ - s = simpleeval.EvalWithCompoundTypes(operators=operators, functions=functions, names=names) - return s.eval(expr) - - StreamMapsDict: TypeAlias = t.Dict[str, t.Union[str, dict, None]] @@ -280,6 +261,7 @@ def __init__( self._transform_fn, self.transformed_schema, ) = self._init_functions_and_schema(stream_map=map_transform) + self.expr_evaluator = simpleeval.EvalWithCompoundTypes(functions=self.functions) def transform(self, record: dict) -> dict | None: """Return a transformed record. @@ -323,13 +305,15 @@ def functions(self) -> dict[str, t.Callable]: def _eval( self, expr: str, + expr_parsed: ast.Expr, record: dict, property_name: str | None, ) -> str | int | float: """Solve an expression. Args: - expr: String expression to evaluate. + expr: String expression to evaluate (used to raise human readable errors). + expr_parsed: Parsed expression abstract syntax tree. record: Individual stream record. property_name: Name of property to transform in the record. @@ -347,10 +331,10 @@ def _eval( # Allow access to original property value if applicable names["self"] = record[property_name] try: - result: str | int | float = compound_eval( + self.expr_evaluator.names = names + result: str | int | float = self.expr_evaluator.eval( expr, - functions=self.functions, - names=names, + previously_parsed=expr_parsed, ) except (simpleeval.InvalidExpression, SyntaxError) as ex: msg = f"Failed to evaluate simpleeval expressions {expr}." @@ -398,7 +382,7 @@ def _eval_type( if expr.startswith("bool("): return th.BooleanType() - + return th.StringType() if expr[0] == "'" and expr[-1] == "'" else default def _init_functions_and_schema( # noqa: PLR0912, PLR0915, C901 @@ -416,6 +400,7 @@ def _init_functions_and_schema( # noqa: PLR0912, PLR0915, C901 Raises: NotImplementedError: TODO StreamMapConfigError: TODO + MapExpressionError: TODO """ stream_map = copy.copy(stream_map) @@ -423,6 +408,12 @@ def _init_functions_and_schema( # noqa: PLR0912, PLR0915, C901 include_by_default = True if stream_map and MAPPER_FILTER_OPTION in stream_map: filter_rule = stream_map.pop(MAPPER_FILTER_OPTION) + try: + filter_rule_parsed: ast.Expr = ast.parse(filter_rule).body[0] + except (SyntaxError, IndexError) as ex: + msg = f"Failed to parse expression {filter_rule}." + raise MapExpressionError(msg) from ex + logging.info( "Found '%s' filter rule: %s", self.stream_alias, @@ -465,6 +456,7 @@ def _init_functions_and_schema( # noqa: PLR0912, PLR0915, C901 if "properties" not in transformed_schema: transformed_schema["properties"] = {} + stream_map_parsed: list[tuple[str, str | None, ast.Expr | None]] = [] for prop_key, prop_def in list(stream_map.items()): if prop_def in {None, NULL_STRING}: if prop_key in (self.transformed_key_properties or []): @@ -477,6 +469,7 @@ def _init_functions_and_schema( # noqa: PLR0912, PLR0915, C901 ) raise StreamMapConfigError(msg) transformed_schema["properties"].pop(prop_key, None) + stream_map_parsed.append((prop_key, prop_def, None)) elif isinstance(prop_def, str): default_type: th.JSONTypeHelper = th.StringType() # Fallback to string existing_schema: dict = ( @@ -495,6 +488,13 @@ def _init_functions_and_schema( # noqa: PLR0912, PLR0915, C901 self._eval_type(prop_def, default=default_type), ).to_dict(), ) + try: + parsed_def: ast.Expr = ast.parse(prop_def).body[0] + stream_map_parsed.append((prop_key, prop_def, parsed_def)) + except (SyntaxError, IndexError) as ex: + msg = f"Failed to parse expression {prop_def}." + raise MapExpressionError(msg) from ex + else: msg = ( f"Unexpected type '{type(prop_def).__name__}' in stream map for " @@ -516,10 +516,14 @@ def _init_functions_and_schema( # noqa: PLR0912, PLR0915, C901 # Declare function variables - def eval_filter(filter_rule: str) -> t.Callable[[dict], bool]: + def eval_filter( + filter_rule: str, + filter_rule_parsed: ast.Expr, + ) -> t.Callable[[dict], bool]: def _inner(record: dict) -> bool: filter_result = self._eval( expr=filter_rule, + expr_parsed=filter_rule_parsed, record=record, property_name=None, ) @@ -541,7 +545,7 @@ def always_true(record: dict) -> bool: return True if isinstance(filter_rule, str): - filter_fn = eval_filter(filter_rule) + filter_fn = eval_filter(filter_rule, filter_rule_parsed) elif filter_rule is None: filter_fn = always_true else: @@ -566,16 +570,17 @@ def transform_fn(record: dict) -> dict | None: if key_property in record: result[key_property] = record[key_property] - for prop_key, prop_def in list(stream_map.items()): + for prop_key, prop_def, prop_def_parsed in stream_map_parsed: if prop_def in {None, NULL_STRING}: # Remove property from result result.pop(prop_key, None) continue - if isinstance(prop_def, str): + if isinstance(prop_def_parsed, ast.Expr): # Apply property transform result[prop_key] = self._eval( expr=prop_def, + expr_parsed=prop_def_parsed, record=record, property_name=prop_key, ) diff --git a/tests/core/test_mapper.py b/tests/core/test_mapper.py index 2afcb59b4..cae6773ef 100644 --- a/tests/core/test_mapper.py +++ b/tests/core/test_mapper.py @@ -22,14 +22,14 @@ from singer_sdk.tap_base import Tap from singer_sdk.typing import ( ArrayType, + BooleanType, IntegerType, NumberType, ObjectType, + OneOf, PropertiesList, Property, StringType, - BooleanType, - OneOf, ) if t.TYPE_CHECKING: @@ -60,11 +60,15 @@ def sample_catalog_dict() -> dict: ).to_dict() nested_jellybean_schema = PropertiesList( Property("id", IntegerType), - Property("custom_fields", - ArrayType(ObjectType( - Property("id", IntegerType), - Property("value", OneOf(StringType, IntegerType, BooleanType)))) - ) + Property( + "custom_fields", + ArrayType( + ObjectType( + Property("id", IntegerType), + Property("value", OneOf(StringType, IntegerType, BooleanType)), + ) + ), + ), ).to_dict() return { "streams": [ @@ -81,8 +85,8 @@ def sample_catalog_dict() -> dict: { "stream": "nested_jellybean", "tap_stream_id": "nested_jellybean", - "schema": nested_jellybean_schema - } + "schema": nested_jellybean_schema, + }, ], } @@ -126,8 +130,22 @@ def sample_stream(): {"brown": "fox"}, ], "nested_jellybean": [ - {"id": 123, "custom_fields": [{"id": 1, "value": "abc"}, {"id": 2, "value": 1212}, {"id": 3, "value": None}]}, - {"id": 124, "custom_fields": [{"id": 1, "value": "foo"}, {"id": 2, "value": 9009}, {"id": 3, "value": True}]} + { + "id": 123, + "custom_fields": [ + {"id": 1, "value": "abc"}, + {"id": 2, "value": 1212}, + {"id": 3, "value": None}, + ], + }, + { + "id": 124, + "custom_fields": [ + {"id": 1, "value": "foo"}, + {"id": 2, "value": 9009}, + {"id": 3, "value": True}, + ], + }, ], } @@ -153,7 +171,7 @@ def transform_stream_maps(): "custom_field_1": 'dict([(x["id"], x["value"]) for x in custom_fields]).get(1)', "custom_field_2": 'int(dict([(x["id"], x["value"]) for x in custom_fields]).get(2)) if dict([(x["id"], x["value"]) for x in custom_fields]).get(2) else None', "custom_field_3": 'bool(dict([(x["id"], x["value"]) for x in custom_fields]).get(3)) if dict([(x["id"], x["value"]) for x in custom_fields]).get(3) else None', - } + }, } @@ -211,8 +229,18 @@ def transformed_result(stream_map_config): {"brown": "fox"}, ], "nested_jellybean": [ - {"id": 123, "custom_field_1": "abc", "custom_field_2": 1212, "custom_field_3": None}, - {"id": 124, "custom_field_1": "foo", "custom_field_2": 9009, "custom_field_3": True} + { + "id": 123, + "custom_field_1": "abc", + "custom_field_2": 1212, + "custom_field_3": None, + }, + { + "id": 124, + "custom_field_1": "foo", + "custom_field_2": 9009, + "custom_field_3": True, + }, ], } @@ -237,8 +265,8 @@ def transformed_schemas(): Property("id", IntegerType), Property("custom_field_1", StringType), Property("custom_field_2", IntegerType), - Property("custom_field_3", BooleanType) - ).to_dict() + Property("custom_field_3", BooleanType), + ).to_dict(), } diff --git a/tests/core/test_simpleeval.py b/tests/core/test_simpleeval.py index d5cacb30f..8e7c06f52 100644 --- a/tests/core/test_simpleeval.py +++ b/tests/core/test_simpleeval.py @@ -18,8 +18,8 @@ import unittest import warnings -from singer_sdk.helpers import _simpleeval as simpleeval -from singer_sdk.helpers._simpleeval import ( +import simpleeval +from simpleeval import ( AttributeDoesNotExist, EvalWithCompoundTypes, FeatureNotAvailable, From a900de389f1764b24c4f35d4a3ae822d130b046e Mon Sep 17 00:00:00 2001 From: Haleemur Ali Date: Mon, 9 Oct 2023 16:50:52 -0400 Subject: [PATCH 3/7] tap factory tests now test with stream map --- singer_sdk/testing/factory.py | 23 +++++++++++------------ singer_sdk/testing/tap_tests.py | 22 ++++++++++++++-------- 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/singer_sdk/testing/factory.py b/singer_sdk/testing/factory.py index 1c15f4844..ce6d2ec4c 100644 --- a/singer_sdk/testing/factory.py +++ b/singer_sdk/testing/factory.py @@ -197,32 +197,31 @@ def _annotate_test_class( # noqa: C901 test_params = [] test_ids: list[str] = [] for stream in streams: + final_schema = stream.stream_maps[-1].transformed_schema[ + "properties" + ] test_params.extend( [ { "stream": stream, - "attribute_name": property_name, + "attribute_name": prop_name, } - for property_name, property_schema in stream.schema[ - "properties" - ].items() + for prop_name, prop_schema in final_schema.items() if test_class.evaluate( stream=stream, - property_name=property_name, - property_schema=property_schema, + property_name=prop_name, + property_schema=prop_schema, ) ], ) test_ids.extend( [ - f"{stream.name}.{property_name}" - for property_name, property_schema in stream.schema[ - "properties" - ].items() + f"{stream.name}.{prop_name}" + for prop_name, prop_schema in final_schema.items() if test_class.evaluate( stream=stream, - property_name=property_name, - property_schema=property_schema, + property_name=prop_name, + property_schema=prop_schema, ) ], ) diff --git a/singer_sdk/testing/tap_tests.py b/singer_sdk/testing/tap_tests.py index ecb7eb811..8008f2ffc 100644 --- a/singer_sdk/testing/tap_tests.py +++ b/singer_sdk/testing/tap_tests.py @@ -93,16 +93,20 @@ def test(self) -> None: class StreamCatalogSchemaMatchesRecordTest(StreamTestTemplate): """Test all attributes in the catalog schema are present in the record schema.""" - name = "catalog_schema_matches_record" + name = "transformed_catalog_schema_matches_record" def test(self) -> None: """Run test.""" - stream_catalog_keys = set(self.stream.schema["properties"].keys()) + stream_transformed_keys = set( + self.stream.stream_maps[-1].transformed_schema["properties"].keys(), + ) stream_record_keys = set().union(*(d.keys() for d in self.stream_records)) - diff = stream_catalog_keys - stream_record_keys + diff = stream_transformed_keys - stream_record_keys if diff: warnings.warn( - UserWarning(f"Fields in catalog but not in records: ({diff})"), + UserWarning( + f"Fields in transformed catalog but not in records: ({diff})", + ), stacklevel=2, ) @@ -110,14 +114,16 @@ def test(self) -> None: class StreamRecordSchemaMatchesCatalogTest(StreamTestTemplate): """Test all attributes in the record schema are present in the catalog schema.""" - name = "record_schema_matches_catalog" + name = "record_schema_matches_transformed_catalog" def test(self) -> None: """Run test.""" - stream_catalog_keys = set(self.stream.schema["properties"].keys()) + stream_transformed_keys = set( + self.stream.stream_maps[-1].transformed_schema["properties"].keys(), + ) stream_record_keys = set().union(*(d.keys() for d in self.stream_records)) - diff = stream_record_keys - stream_catalog_keys - assert not diff, f"Fields in records but not in catalog: ({diff})" + diff = stream_record_keys - stream_transformed_keys + assert not diff, f"Fields in records but not in transformed catalog: ({diff})" class StreamRecordMatchesStreamSchema(StreamTestTemplate): From a10519921024993c7c04010679672bde37f082c9 Mon Sep 17 00:00:00 2001 From: Haleemur Ali Date: Mon, 9 Oct 2023 17:32:02 -0400 Subject: [PATCH 4/7] remove old vendored file `test_simpleeval.py` --- tests/core/test_simpleeval.py | 1146 --------------------------------- 1 file changed, 1146 deletions(-) delete mode 100644 tests/core/test_simpleeval.py diff --git a/tests/core/test_simpleeval.py b/tests/core/test_simpleeval.py deleted file mode 100644 index 8e7c06f52..000000000 --- a/tests/core/test_simpleeval.py +++ /dev/null @@ -1,1146 +0,0 @@ -""" -Simpleeval tests originally imported on 2021-09-16 from: -- https://github.com/danthedeckie/simpleeval - -For more information: -- https://gitlab.com/meltano/sdk/-/issues/213 - -""" -from __future__ import annotations - -import ast -import operator -import os - -# flake8: noqa # Ignoring flake errors in imported module -# pylint: disable=too-many-public-methods, missing-docstring -import sys -import unittest -import warnings - -import simpleeval -from simpleeval import ( - AttributeDoesNotExist, - EvalWithCompoundTypes, - FeatureNotAvailable, - FunctionNotDefined, - InvalidExpression, - NameNotDefined, - SimpleEval, - simple_eval, -) - - -class DRYTest(unittest.TestCase): - """Stuff we need to do every test, let's do here instead.. - Don't Repeat Yourself.""" - - def setUp(self): - """ initialize a SimpleEval """ - self.s = SimpleEval() - - def t(self, expr, shouldbe): # pylint: disable=invalid-name - """ test an evaluation of an expression against an expected answer """ - return self.assertEqual(self.s.eval(expr), shouldbe) - - -class TestBasic(DRYTest): - """ Simple expressions. """ - - def test_maths_with_ints(self): - """ simple maths expressions """ - - self.t("21 + 21", 42) - self.t("6*7", 42) - self.t("20 + 1 + (10*2) + 1", 42) - self.t("100/10", 10) - self.t("12*12", 144) - self.t("2 ** 10", 1024) - self.t("100 % 9", 1) - - def test_bools_and_or(self): - self.t('True and ""', "") - self.t("True and False", False) - self.t("True or False", True) - self.t("False or False", False) - self.t("1 - 1 or 21", 21) - self.t("1 - 1 and 11", 0) - self.t("110 == 100 + 10 and True", True) - self.t("110 != 100 + 10 and True", False) - self.t("False or 42", 42) - - self.t("False or None", None) - self.t("None or None", None) - - self.s.names = {"out": True, "position": 3} - self.t( - "(out and position <=6 and -10)" - " or (out and position > 6 and -5)" - " or (not out and 15)", - -10, - ) - - def test_not(self): - self.t("not False", True) - self.t("not True", False) - self.t("not 0", True) - self.t("not 1", False) - - def test_maths_with_floats(self): - self.t("11.02 - 9.1", 1.92) - self.t("29.1+39", 68.1) - - def test_comparisons(self): - # GT & LT: - self.t("1 > 0", True) - self.t("100000 < 28", False) - self.t("-2 < 11", True) - self.t("+2 < 5", True) - self.t("0 == 0", True) - - # GtE, LtE - self.t("-2 <= -2", True) - self.t("2 >= 2", True) - self.t("1 >= 12", False) - self.t("1.09 <= 1967392", True) - - self.t("1 < 2 < 3 < 4", 1 < 2 < 3 < 4) - self.t("1 < 2 > 3 < 4", 1 < 2 > 3 < 4) - - self.t("1<2<1+1", 1 < 2 < 1 + 1) - self.t("1 == 1 == 2", 1 == 1 == 2) - self.t("1 == 1 < 2", 1 == 1 < 2) - - def test_mixed_comparisons(self): - self.t("1 > 0.999999", True) - self.t("1 == True", True) # Note ==, not 'is'. - self.t("0 == False", True) # Note ==, not 'is'. - self.t("False == False", True) - self.t("False < True", True) - - def test_if_else(self): - """ x if y else z """ - - # and test if/else expressions: - self.t("'a' if 1 == 1 else 'b'", "a") - self.t("'a' if 1 > 2 else 'b'", "b") - - # and more complex expressions: - self.t("'a' if 4 < 1 else 'b' if 1 == 2 else 'c'", "c") - - def test_default_conversions(self): - """ conversion between types """ - - self.t('int("20") + int(0.22*100)', 42) - self.t('float("42")', 42.0) - self.t('"Test Stuff!" + str(11)', "Test Stuff!11") - - def test_slicing(self): - self.s.operators[ast.Slice] = ( - operator.getslice if hasattr(operator, "getslice") else operator.getitem - ) - self.t("'hello'[1]", "e") - self.t("'hello'[:]", "hello") - self.t("'hello'[:3]", "hel") - self.t("'hello'[3:]", "lo") - self.t("'hello'[::2]", "hlo") - self.t("'hello'[::-1]", "olleh") - self.t("'hello'[3::]", "lo") - self.t("'hello'[:3:]", "hel") - self.t("'hello'[1:3]", "el") - self.t("'hello'[1:3:]", "el") - self.t("'hello'[1::2]", "el") - self.t("'hello'[:1:2]", "h") - self.t("'hello'[1:3:1]", "el") - self.t("'hello'[1:3:2]", "e") - - with self.assertRaises(IndexError): - self.t("'hello'[90]", 0) - - self.t('"spam" not in "my breakfast"', True) - self.t('"silly" in "ministry of silly walks"', True) - self.t('"I" not in "team"', True) - self.t('"U" in "RUBBISH"', True) - - def test_is(self): - self.t("1 is 1", True) - self.t("1 is 2", False) - self.t('1 is "a"', False) - self.t("1 is None", False) - self.t("None is None", True) - - self.t("1 is not 1", False) - self.t("1 is not 2", True) - self.t('1 is not "a"', True) - self.t("1 is not None", True) - self.t("None is not None", False) - - def test_fstring(self): - if sys.version_info >= (3, 6, 0): - self.t('f""', "") - self.t('f"stuff"', "stuff") - self.t('f"one is {1} and two is {2}"', "one is 1 and two is 2") - self.t('f"1+1 is {1+1}"', "1+1 is 2") - self.t("f\"{'dramatic':!<11}\"", "dramatic!!!") - - def test_set_not_allowed(self): - with self.assertRaises(FeatureNotAvailable): - self.t("{22}", False) - - -class TestFunctions(DRYTest): - """ Functions for expressions to play with """ - - def test_load_file(self): - """ add in a function which loads data from an external file. """ - - # write to the file: - - with open("testfile.txt", "w") as f: - f.write("42") - - # define the function we'll send to the eval'er - - def load_file(filename): - """ load a file and return its contents """ - with open(filename) as f2: - return f2.read() - - # simple load: - - self.s.functions = {"read": load_file} - self.t("read('testfile.txt')", "42") - - # and we should have *replaced* the default functions. Let's check: - - with self.assertRaises(simpleeval.FunctionNotDefined): - self.t("int(read('testfile.txt'))", 42) - - # OK, so we can load in the default functions as well... - - self.s.functions.update(simpleeval.DEFAULT_FUNCTIONS) - - # now it works: - - self.t("int(read('testfile.txt'))", 42) - - os.remove("testfile.txt") - - def test_randoms(self): - """ test the rand() and randint() functions """ - - i = self.s.eval("randint(1000)") - self.assertEqual(type(i), int) - self.assertLessEqual(i, 1000) - - f = self.s.eval("rand()") - self.assertEqual(type(f), float) - - self.t("randint(20)<20", True) - self.t("rand()<1.0", True) - - # I don't know how to further test these functions. Ideas? - - def test_methods(self): - self.t('"WORD".lower()', "word") - x = simpleeval.DISALLOW_METHODS - simpleeval.DISALLOW_METHODS = [] - self.t('"{}:{}".format(1, 2)', "1:2") - simpleeval.DISALLOW_METHODS = x - - def test_function_args_none(self): - def foo(): - return 42 - - self.s.functions["foo"] = foo - self.t("foo()", 42) - - def test_function_args_required(self): - def foo(toret): - return toret - - self.s.functions["foo"] = foo - with self.assertRaises(TypeError): - self.t("foo()", 42) - - self.t("foo(12)", 12) - self.t("foo(toret=100)", 100) - - def test_function_args_defaults(self): - def foo(toret=9999): - return toret - - self.s.functions["foo"] = foo - self.t("foo()", 9999) - - self.t("foo(12)", 12) - self.t("foo(toret=100)", 100) - - def test_function_args_bothtypes(self): - def foo(mult, toret=100): - return toret * mult - - self.s.functions["foo"] = foo - with self.assertRaises(TypeError): - self.t("foo()", 9999) - - self.t("foo(2)", 200) - - with self.assertRaises(TypeError): - self.t("foo(toret=100)", 100) - - self.t("foo(4, toret=4)", 16) - self.t("foo(mult=2, toret=4)", 8) - self.t("foo(2, 10)", 20) - - -class TestOperators(DRYTest): - """ Test adding in new operators, removing them, make sure it works. """ - - # TODO - pass - - -class TestNewFeatures(DRYTest): - """ Tests which will break when new features are added...""" - - def test_lambda(self): - with self.assertRaises(FeatureNotAvailable): - self.t("lambda x:22", None) - - def test_lambda_application(self): - with self.assertRaises(FeatureNotAvailable): - self.t("(lambda x:22)(44)", None) - - -class TestTryingToBreakOut(DRYTest): - """ Test various weird methods to break the security sandbox... """ - - def test_import(self): - """ usual suspect. import """ - # cannot import things: - with self.assertRaises(FeatureNotAvailable): - self.t("import sys", None) - - def test_long_running(self): - """ exponent operations can take a long time. """ - old_max = simpleeval.MAX_POWER - - self.t("9**9**5", 9 ** 9 ** 5) - - with self.assertRaises(simpleeval.NumberTooHigh): - self.t("9**9**8", 0) - - # and does limiting work? - - simpleeval.MAX_POWER = 100 - - with self.assertRaises(simpleeval.NumberTooHigh): - self.t("101**2", 0) - - # good, so set it back: - - simpleeval.MAX_POWER = old_max - - def test_encode_bignums(self): - # thanks gk - if hasattr(1, "from_bytes"): # python3 only - with self.assertRaises(simpleeval.IterableTooLong): - self.t( - '(1).from_bytes(("123123123123123123123123").encode()*999999, "big")', - 0, - ) - - def test_string_length(self): - with self.assertRaises(simpleeval.IterableTooLong): - self.t("50000*'text'", 0) - - with self.assertRaises(simpleeval.IterableTooLong): - self.t("'text'*50000", 0) - - with self.assertRaises(simpleeval.IterableTooLong): - self.t("('text'*50000)*1000", 0) - - with self.assertRaises(simpleeval.IterableTooLong): - self.t("(50000*'text')*1000", 0) - - self.t("'stuff'*20000", 20000 * "stuff") - - self.t("20000*'stuff'", 20000 * "stuff") - - with self.assertRaises(simpleeval.IterableTooLong): - self.t("('stuff'*20000) + ('stuff'*20000) ", 0) - - with self.assertRaises(simpleeval.IterableTooLong): - self.t("'stuff'*100000", 100000 * "stuff") - - with self.assertRaises(simpleeval.IterableTooLong): - self.t("'" + (10000 * "stuff") + "'*100", 0) - - with self.assertRaises(simpleeval.IterableTooLong): - self.t("'" + (50000 * "stuff") + "'", 0) - - if sys.version_info >= (3, 6, 0): - with self.assertRaises(simpleeval.IterableTooLong): - self.t("f'{\"foo\"*50000}'", 0) - - def test_bytes_array_test(self): - self.t( - "'20000000000000000000'.encode() * 5000", - "20000000000000000000".encode() * 5000, - ) - - with self.assertRaises(simpleeval.IterableTooLong): - self.t("'123121323123131231223'.encode() * 5000", 20) - - def test_list_length_test(self): - self.t("'spam spam spam'.split() * 5000", ["spam", "spam", "spam"] * 5000) - - with self.assertRaises(simpleeval.IterableTooLong): - self.t("('spam spam spam' * 5000).split() * 5000", None) - - def test_python_stuff(self): - """ other various pythony things. """ - # it only evaluates the first statement: - self.t("11; x = 21; x + x", 11) - - def test_function_globals_breakout(self): - """ by accessing function.__globals__ or func_... """ - # thanks perkinslr. - - self.s.functions["x"] = lambda y: y + y - self.t("x(100)", 200) - - with self.assertRaises(simpleeval.FeatureNotAvailable): - self.t("x.__globals__", None) - - class EscapeArtist(object): - @staticmethod - def trapdoor(): - return 42 - - @staticmethod - def _quasi_private(): - return 84 - - self.s.names["houdini"] = EscapeArtist() - - with self.assertRaises(simpleeval.FeatureNotAvailable): - self.t("houdini.trapdoor.__globals__", 0) - - with self.assertRaises(simpleeval.FeatureNotAvailable): - self.t("houdini.trapdoor.func_globals", 0) - - with self.assertRaises(simpleeval.FeatureNotAvailable): - self.t("houdini._quasi_private()", 0) - - # and test for changing '_' to '__': - - dis = simpleeval.DISALLOW_PREFIXES - simpleeval.DISALLOW_PREFIXES = ["func_"] - - self.t("houdini.trapdoor()", 42) - self.t("houdini._quasi_private()", 84) - - # and return things to normal - - simpleeval.DISALLOW_PREFIXES = dis - - def test_mro_breakout(self): - class Blah(object): - x = 42 - - self.s.names["b"] = Blah - - with self.assertRaises(simpleeval.FeatureNotAvailable): - self.t("b.mro()", None) - - def test_builtins_private_access(self): - # explicit attempt of the exploit from perkinslr - with self.assertRaises(simpleeval.FeatureNotAvailable): - self.t( - "True.__class__.__class__.__base__.__subclasses__()[-1]" - ".__init__.func_globals['sys'].exit(1)", - 42, - ) - - def test_string_format(self): - # python has so many ways to break out! - with self.assertRaises(simpleeval.FeatureNotAvailable): - self.t('"{string.__class__}".format(string="things")', 0) - - with self.assertRaises(simpleeval.FeatureNotAvailable): - self.s.names["x"] = {"a": 1} - self.t('"{a.__class__}".format_map(x)', 0) - - if sys.version_info >= (3, 6, 0): - self.s.names["x"] = 42 - - with self.assertRaises(simpleeval.FeatureNotAvailable): - self.t('f"{x.__class__}"', 0) - - self.s.names["x"] = lambda y: y - - with self.assertRaises(simpleeval.FeatureNotAvailable): - self.t('f"{x.__globals__}"', 0) - - class EscapeArtist(object): - @staticmethod - def trapdoor(): - return 42 - - @staticmethod - def _quasi_private(): - return 84 - - self.s.names[ - "houdini" - ] = EscapeArtist() # let's just retest this, but in a f-string - - with self.assertRaises(simpleeval.FeatureNotAvailable): - self.t('f"{houdini.trapdoor.__globals__}"', 0) - - with self.assertRaises(simpleeval.FeatureNotAvailable): - self.t('f"{houdini.trapdoor.func_globals}"', 0) - - with self.assertRaises(simpleeval.FeatureNotAvailable): - self.t('f"{houdini._quasi_private()}"', 0) - - # and test for changing '_' to '__': - - dis = simpleeval.DISALLOW_PREFIXES - simpleeval.DISALLOW_PREFIXES = ["func_"] - - self.t('f"{houdini.trapdoor()}"', "42") - self.t('f"{houdini._quasi_private()}"', "84") - - # and return things to normal - - simpleeval.DISALLOW_PREFIXES = dis - - -class TestCompoundTypes(DRYTest): - """ Test the compound-types edition of the library """ - - def setUp(self): - self.s = EvalWithCompoundTypes() - - def test_dict(self): - self.t("{}", {}) - self.t('{"foo": "bar"}', {"foo": "bar"}) - self.t('{"foo": "bar"}["foo"]', "bar") - self.t("dict()", {}) - self.t("dict(a=1)", {"a": 1}) - - def test_dict_contains(self): - self.t('{"a":22}["a"]', 22) - with self.assertRaises(KeyError): - self.t('{"a":22}["b"]', 22) - - self.t('{"a": 24}.get("b", 11)', 11) - self.t('"a" in {"a": 24}', True) - - def test_tuple(self): - self.t("()", ()) - self.t("(1,)", (1,)) - self.t("(1, 2, 3, 4, 5, 6)", (1, 2, 3, 4, 5, 6)) - self.t("(1, 2) + (3, 4)", (1, 2, 3, 4)) - self.t("(1, 2, 3)[1]", 2) - self.t("tuple()", ()) - self.t('tuple("foo")', ("f", "o", "o")) - - def test_tuple_contains(self): - self.t('("a","b")[1]', "b") - with self.assertRaises(IndexError): - self.t('("a","b")[5]', "b") - self.t('"a" in ("b","c","a")', True) - - def test_list(self): - self.t("[]", []) - self.t("[1]", [1]) - self.t("[1, 2, 3, 4, 5]", [1, 2, 3, 4, 5]) - self.t("[1, 2, 3][1]", 2) - self.t("list()", []) - self.t('list("foo")', ["f", "o", "o"]) - - def test_list_contains(self): - self.t('["a","b"][1]', "b") - with self.assertRaises(IndexError): - self.t('("a","b")[5]', "b") - - self.t('"b" in ["a","b"]', True) - - def test_set(self): - self.t("{1}", {1}) - self.t("{1, 2, 1, 2, 1, 2, 1}", {1, 2}) - self.t("set()", set()) - self.t('set("foo")', {"f", "o"}) - - self.t("2 in {1,2,3,4}", True) - self.t("22 not in {1,2,3,4}", True) - - def test_not(self): - self.t("not []", True) - self.t("not [0]", False) - self.t("not {}", True) - self.t("not {0: 1}", False) - self.t("not {0}", False) - - def test_use_func(self): - self.s = EvalWithCompoundTypes(functions={"map": map, "str": str}) - self.t("list(map(str, [-1, 0, 1]))", ["-1", "0", "1"]) - with self.assertRaises(NameNotDefined): - self.s.eval("list(map(bad, [-1, 0, 1]))") - - with self.assertRaises(FunctionNotDefined): - self.s.eval("dir(str)") - with self.assertRaises(FeatureNotAvailable): - self.s.eval("str.__dict__") - - self.s = EvalWithCompoundTypes(functions={"dir": dir, "str": str}) - self.t("dir(str)", dir(str)) - - -class TestComprehensions(DRYTest): - """ Test the comprehensions support of the compound-types edition of the class. """ - - def setUp(self): - self.s = EvalWithCompoundTypes() - - def test_basic(self): - self.t("[a + 1 for a in [1,2,3]]", [2, 3, 4]) - - def test_with_self_reference(self): - self.t("[a + a for a in [1,2,3]]", [2, 4, 6]) - - def test_with_if(self): - self.t("[a for a in [1,2,3,4,5] if a <= 3]", [1, 2, 3]) - - def test_with_multiple_if(self): - self.t("[a for a in [1,2,3,4,5] if a <= 3 and a > 1 ]", [2, 3]) - - def test_attr_access_fails(self): - with self.assertRaises(FeatureNotAvailable): - self.t("[a.__class__ for a in [1,2,3]]", None) - - def test_unpack(self): - self.t("[a+b for a,b in ((1,2),(3,4))]", [3, 7]) - - def test_nested_unpack(self): - self.t("[a+b+c for a, (b, c) in ((1,(1,1)),(3,(2,2)))]", [3, 7]) - - def test_other_places(self): - self.s.functions = {"sum": sum} - self.t("sum([a+1 for a in [1,2,3,4,5]])", 20) - self.t("sum(a+1 for a in [1,2,3,4,5])", 20) - - def test_external_names_work(self): - self.s.names = {"x": [22, 102, 12.3]} - self.t("[a/2 for a in x]", [11.0, 51.0, 6.15]) - - self.s.names = lambda x: ord(x.id) - self.t("[a + a for a in [b, c, d]]", [ord(x) * 2 for x in "bcd"]) - - def test_multiple_generators(self): - self.s.functions = {"range": range} - s = "[j for i in range(100) if i > 10 for j in range(i) if j < 20]" - self.t(s, eval(s)) - - def test_triple_generators(self): - self.s.functions = {"range": range} - s = "[(a,b,c) for a in range(4) for b in range(a) for c in range(b)]" - self.t(s, eval(s)) - - def test_too_long_generator(self): - self.s.functions = {"range": range} - s = "[j for i in range(1000) if i > 10 for j in range(i) if j < 20]" - with self.assertRaises(simpleeval.IterableTooLong): - self.s.eval(s) - - def test_too_long_generator_2(self): - self.s.functions = {"range": range} - s = "[j for i in range(100) if i > 1 for j in range(i+10) if j < 100 for k in range(i*j)]" - with self.assertRaises(simpleeval.IterableTooLong): - self.s.eval(s) - - def test_nesting_generators_to_cheat(self): - self.s.functions = {"range": range} - s = "[[[c for c in range(a)] for a in range(b)] for b in range(200)]" - - with self.assertRaises(simpleeval.IterableTooLong): - self.s.eval(s) - - def test_no_leaking_names(self): - # see issue #52, failing list comprehensions could leak locals - with self.assertRaises(simpleeval.NameNotDefined): - self.s.eval('[x if x == "2" else y for x in "123"]') - - with self.assertRaises(simpleeval.NameNotDefined): - self.s.eval("x") - - -class TestNames(DRYTest): - """ 'names', what other languages call variables... """ - - def test_none(self): - """ what to do when names isn't defined, or is 'none' """ - with self.assertRaises(NameNotDefined): - self.t("a == 2", None) - - self.s.names["s"] = 21 - - with self.assertRaises(NameNotDefined): - with warnings.catch_warnings(record=True) as ws: - self.t("s += a", 21) - - self.s.names = None - - with self.assertRaises(InvalidExpression): - self.t("s", 21) - - self.s.names = {"a": {"b": {"c": 42}}} - - with self.assertRaises(AttributeDoesNotExist): - self.t("a.b.d**2", 42) - - def test_dict(self): - """ using a normal dict for names lookup """ - - self.s.names = {"a": 42} - self.t("a + a", 84) - - self.s.names["also"] = 100 - - self.t("a + also - a", 100) - - # however, you can't assign to those names: - with warnings.catch_warnings(record=True) as ws: - self.t("a = 200", 200) - - self.assertEqual(self.s.names["a"], 42) - - # or assign to lists - - self.s.names["b"] = [0] - - with warnings.catch_warnings(record=True) as ws: - self.t("b[0] = 11", 11) - - self.assertEqual(self.s.names["b"], [0]) - - # but you can get items from a list: - - self.s.names["b"] = [6, 7] - - self.t("b[0] * b[1]", 42) - - # or from a dict - - self.s.names["c"] = {"i": 11} - - self.t("c['i']", 11) - self.t("c.get('i')", 11) - self.t("c.get('j', 11)", 11) - self.t("c.get('j')", None) - - # you still can't assign though: - - with warnings.catch_warnings(record=True) as ws: - self.t("c['b'] = 99", 99) - - self.assertFalse("b" in self.s.names["c"]) - - # and going all 'inception' on it doesn't work either: - - self.s.names["c"]["c"] = {"c": 11} - - with warnings.catch_warnings(record=True) as ws: - self.t("c['c']['c'] = 21", 21) - - self.assertEqual(self.s.names["c"]["c"]["c"], 11) - - def test_dict_attr_access(self): - # nested dict - - self.assertEqual(self.s.ATTR_INDEX_FALLBACK, True) - - self.s.names = {"a": {"b": {"c": 42}}} - - self.t("a.b.c*2", 84) - - with warnings.catch_warnings(record=True) as ws: - self.t("a.b.c = 11", 11) - - self.assertEqual(self.s.names["a"]["b"]["c"], 42) - - # TODO: Wat? - with warnings.catch_warnings(record=True) as ws: - self.t("a.d = 11", 11) - - with self.assertRaises(KeyError): - self.assertEqual(self.s.names["a"]["d"], 11) - - def test_dict_attr_access_disabled(self): - # nested dict - - self.s.ATTR_INDEX_FALLBACK = False - self.assertEqual(self.s.ATTR_INDEX_FALLBACK, False) - - self.s.names = {"a": {"b": {"c": 42}}} - - with self.assertRaises(simpleeval.AttributeDoesNotExist): - self.t("a.b.c * 2", 84) - - self.t("a['b']['c'] * 2", 84) - - self.assertEqual(self.s.names["a"]["b"]["c"], 42) - - def test_object(self): - """ using an object for name lookup """ - - class TestObject(object): - @staticmethod - def method_thing(): - return 42 - - o = TestObject() - o.a = 23 - o.b = 42 - o.c = TestObject() - o.c.d = 9001 - - self.s.names = {"o": o} - - self.t("o", o) - self.t("o.a", 23) - self.t("o.b + o.c.d", 9043) - - self.t("o.method_thing()", 42) - - with self.assertRaises(AttributeDoesNotExist): - self.t("o.d", None) - - def test_func(self): - """ using a function for 'names lookup' """ - - def resolver(_): - """ all names now equal 1024! """ - return 1024 - - self.s.names = resolver - - self.t("a", 1024) - self.t("a + b - c - d", 0) - - # the function can do stuff with the value it's sent: - - def my_name(node): - """ all names equal their textual name, twice. """ - return node.id + node.id - - self.s.names = my_name - - self.t("a", "aa") - - def test_from_doc(self): - """ the 'name first letter as value' example from the docs """ - - def name_handler(node): - """return the alphabet number of the first letter of - the name's textual name""" - return ord(node.id[0].lower()) - 96 - - self.s.names = name_handler - self.t("a", 1) - self.t("a + b", 3) - - -class TestWhitespace(DRYTest): - """ test that incorrect whitespace (preceding/trailing) doesn't matter. """ - - def test_no_whitespace(self): - self.t("200 + 200", 400) - - def test_trailing(self): - self.t("200 + 200 ", 400) - - def test_preciding_whitespace(self): - self.t(" 200 + 200", 400) - - def test_preceding_tab_whitespace(self): - self.t("\t200 + 200", 400) - - def test_preceding_mixed_whitespace(self): - self.t(" \t 200 + 200", 400) - - def test_both_ends_whitespace(self): - self.t(" \t 200 + 200 ", 400) - - -class TestSimpleEval(unittest.TestCase): - """ test the 'simple_eval' wrapper function """ - - def test_basic_run(self): - self.assertEqual(simple_eval("6*7"), 42) - - def test_default_functions(self): - self.assertEqual(simple_eval("rand() < 1.0 and rand() > -0.01"), True) - self.assertEqual(simple_eval("randint(200) < 200 and rand() > 0"), True) - - -class TestMethodChaining(unittest.TestCase): - def test_chaining_correct(self): - """ - Contributed by Khalid Grandi (xaled). - """ - - class A(object): - def __init__(self): - self.a = "0" - - def add(self, b): - self.a += "-add" + str(b) - return self - - def sub(self, b): - self.a += "-sub" + str(b) - return self - - def tostring(self): - return str(self.a) - - x = A() - self.assertEqual( - simple_eval("x.add(1).sub(2).sub(3).tostring()", names={"x": x}), - "0-add1-sub2-sub3", - ) - - -class TestExtendingClass(unittest.TestCase): - """ - It should be pretty easy to extend / inherit from the SimpleEval class, - to further lock things down, or unlock stuff, or whatever. - """ - - def test_methods_forbidden(self): - # Example from README - class EvalNoMethods(simpleeval.SimpleEval): - def _eval_call(self, node): - if isinstance(node.func, ast.Attribute): - raise simpleeval.FeatureNotAvailable( - "No methods please, we're British" - ) - return super(EvalNoMethods, self)._eval_call(node) - - e = EvalNoMethods() - - self.assertEqual(e.eval('"stuff happens"'), "stuff happens") - self.assertEqual(e.eval("22 + 20"), 42) - self.assertEqual(e.eval('int("42")'), 42) - - with self.assertRaises(simpleeval.FeatureNotAvailable): - e.eval('" blah ".strip()') - - -class TestExceptions(unittest.TestCase): - """ - confirm a few attributes exist properly and haven't been - eaten by 2to3 or whatever... (see #41) - """ - - def test_functionnotdefined(self): - try: - raise FunctionNotDefined("foo", "foo in bar") - except FunctionNotDefined as e: - assert hasattr(e, "func_name") - assert getattr(e, "func_name") == "foo" - assert hasattr(e, "expression") - assert getattr(e, "expression") == "foo in bar" - - def test_namenotdefined(self): - try: - raise NameNotDefined("foo", "foo in bar") - except NameNotDefined as e: - assert hasattr(e, "name") - assert getattr(e, "name") == "foo" - assert hasattr(e, "expression") - assert getattr(e, "expression") == "foo in bar" - - def test_attributedoesnotexist(self): - try: - raise AttributeDoesNotExist("foo", "foo in bar") - except AttributeDoesNotExist as e: - assert hasattr(e, "attr") - assert getattr(e, "attr") == "foo" - assert hasattr(e, "expression") - assert getattr(e, "expression") == "foo in bar" - - -class TestUnusualComparisons(DRYTest): - def test_custom_comparison_returner(self): - class Blah(object): - def __gt__(self, other): - return self - - b = Blah() - self.s.names = {"b": b} - self.t("b > 2", b) - - def test_custom_comparison_doesnt_return_boolable(self): - """ - SqlAlchemy, bless it's cotton socks, returns BinaryExpression objects - when asking for comparisons between things. These BinaryExpressions - raise a TypeError if you try and check for Truthyiness. - """ - - class BinaryExpression(object): - def __init__(self, value): - self.value = value - - def __eq__(self, other): - return self.value == getattr(other, "value", other) - - def __repr__(self): - return "".format(self.value) - - def __bool__(self): - # This is the only important part, to match SqlAlchemy - the rest - # of the methods are just to make testing a bit easier... - raise TypeError("Boolean value of this clause is not defined") - - class Blah(object): - def __gt__(self, other): - return BinaryExpression("GT") - - def __lt__(self, other): - return BinaryExpression("LT") - - b = Blah() - self.s.names = {"b": b} - # This should not crash: - e = eval("b > 2", self.s.names) - - self.t("b > 2", BinaryExpression("GT")) - self.t("1 < 5 > b", BinaryExpression("LT")) - - -class TestGetItemUnhappy(DRYTest): - # Again, SqlAlchemy doing unusual things. Throwing it's own errors, rather than - # expected types... - - def test_getitem_not_implemented(self): - class Meh(object): - def __getitem__(self, key): - raise NotImplementedError("booya!") - - def __getattr__(self, key): - return 42 - - m = Meh() - - self.assertEqual(m.anything, 42) - with self.assertRaises(NotImplementedError): - m["nothing"] - - self.s.names = {"m": m} - self.t("m.anything", 42) - - with self.assertRaises(NotImplementedError): - self.t("m['nothing']", None) - - self.s.ATTR_INDEX_FALLBACK = False - - self.t("m.anything", 42) - - with self.assertRaises(NotImplementedError): - self.t("m['nothing']", None) - - -class TestShortCircuiting(DRYTest): - def test_shortcircuit_if(self): - x = [] - - def foo(y): - x.append(y) - return y - - self.s.functions = {"foo": foo} - self.t("foo(1) if foo(2) else foo(3)", 1) - self.assertListEqual(x, [2, 1]) - - x = [] - self.t("42 if True else foo(99)", 42) - self.assertListEqual(x, []) - - def test_shortcircuit_comparison(self): - x = [] - - def foo(y): - x.append(y) - return y - - self.s.functions = {"foo": foo} - self.t("foo(11) < 12", True) - self.assertListEqual(x, [11]) - x = [] - - self.t("1 > 2 < foo(22)", False) - self.assertListEqual(x, []) - - -class TestDisallowedFunctions(DRYTest): - def test_functions_are_disallowed_at_init(self): - DISALLOWED = [ - type, - isinstance, - eval, - getattr, - setattr, - help, - repr, - compile, - open, - ] - if simpleeval.PYTHON3: - exec("DISALLOWED.append(exec)") # exec is not a function in Python2... - - for f in simpleeval.DISALLOW_FUNCTIONS: - assert f in DISALLOWED - - for x in DISALLOWED: - with self.assertRaises(FeatureNotAvailable): - s = SimpleEval(functions={"foo": x}) - - def test_functions_are_disallowed_in_expressions(self): - DISALLOWED = [ - type, - isinstance, - eval, - getattr, - setattr, - help, - repr, - compile, - open, - ] - - if simpleeval.PYTHON3: - exec("DISALLOWED.append(exec)") # exec is not a function in Python2... - - for f in simpleeval.DISALLOW_FUNCTIONS: - assert f in DISALLOWED - - DF = simpleeval.DEFAULT_FUNCTIONS.copy() - - for x in DISALLOWED: - simpleeval.DEFAULT_FUNCTIONS = DF.copy() - with self.assertRaises(FeatureNotAvailable): - s = SimpleEval() - s.functions["foo"] = x - s.eval("foo(42)") - - simpleeval.DEFAULT_FUNCTIONS = DF.copy() - - -if __name__ == "__main__": # pragma: no cover - unittest.main() From d6acb91e9dfa1496e906da0bf16f8f38ffe04f80 Mon Sep 17 00:00:00 2001 From: Haleemur Ali Date: Mon, 9 Oct 2023 17:33:46 -0400 Subject: [PATCH 5/7] generate poetry-lock with poetry-v1.6.1 --- poetry.lock | 125 +------------------------------------- tests/core/test_mapper.py | 21 +++++-- 2 files changed, 18 insertions(+), 128 deletions(-) diff --git a/poetry.lock b/poetry.lock index b79bd28e7..8e0534f1f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,10 +1,9 @@ -# This file is automatically @generated by Poetry 1.4.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. [[package]] name = "alabaster" version = "0.7.13" description = "A configurable sidebar-enabled Sphinx theme" -category = "main" optional = true python-versions = ">=3.6" files = [ @@ -16,7 +15,6 @@ files = [ name = "appdirs" version = "1.4.4" description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -category = "main" optional = false python-versions = "*" files = [ @@ -28,7 +26,6 @@ files = [ name = "argcomplete" version = "3.1.2" description = "Bash tab completion for argparse" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -46,7 +43,6 @@ test = ["coverage", "mypy", "pexpect", "ruff", "wheel"] name = "arrow" version = "1.2.3" description = "Better dates & times for Python" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -62,7 +58,6 @@ typing-extensions = {version = "*", markers = "python_version < \"3.8\""} name = "attrs" version = "23.1.0" description = "Classes Without Boilerplate" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -84,7 +79,6 @@ tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pyte name = "babel" version = "2.12.1" description = "Internationalization utilities" -category = "main" optional = true python-versions = ">=3.7" files = [ @@ -99,7 +93,6 @@ pytz = {version = ">=2015.7", markers = "python_version < \"3.9\""} name = "backoff" version = "2.2.1" description = "Function decoration for backoff and retry" -category = "main" optional = false python-versions = ">=3.7,<4.0" files = [ @@ -111,7 +104,6 @@ files = [ name = "beautifulsoup4" version = "4.12.2" description = "Screen-scraping library" -category = "main" optional = true python-versions = ">=3.6.0" files = [ @@ -130,7 +122,6 @@ lxml = ["lxml"] name = "binaryornot" version = "0.4.4" description = "Ultra-lightweight pure Python package to check if a file is binary or text." -category = "dev" optional = false python-versions = "*" files = [ @@ -145,7 +136,6 @@ chardet = ">=3.0.2" name = "boto3" version = "1.28.52" description = "The AWS SDK for Python" -category = "main" optional = true python-versions = ">= 3.7" files = [ @@ -165,7 +155,6 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] name = "botocore" version = "1.31.52" description = "Low-level, data-driven core of boto 3." -category = "main" optional = true python-versions = ">= 3.7" files = [ @@ -185,7 +174,6 @@ crt = ["awscrt (==0.16.26)"] name = "certifi" version = "2023.7.22" description = "Python package for providing Mozilla's CA Bundle." -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -197,7 +185,6 @@ files = [ name = "cffi" version = "1.15.1" description = "Foreign Function Interface for Python calling C code." -category = "main" optional = false python-versions = "*" files = [ @@ -274,7 +261,6 @@ pycparser = "*" name = "chardet" version = "5.2.0" description = "Universal encoding detector for Python 3" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -286,7 +272,6 @@ files = [ name = "charset-normalizer" version = "3.2.0" 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 = [ @@ -371,7 +356,6 @@ files = [ name = "click" version = "8.1.7" description = "Composable command line interface toolkit" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -387,7 +371,6 @@ importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} 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 = [ @@ -399,7 +382,6 @@ files = [ name = "commitizen" version = "3.9.0" description = "Python commitizen client tool" -category = "dev" optional = false python-versions = ">=3.7,<4.0" files = [ @@ -425,7 +407,6 @@ typing-extensions = {version = ">=4.0.1,<5.0.0", markers = "python_version < \"3 name = "commitizen-version-bump" version = "0.1.0" description = "Commitizen customized for Meltano projects (https://commitizen-tools.github.io/commitizen/customization)" -category = "dev" optional = false python-versions = "^3.7" files = [] @@ -445,7 +426,6 @@ resolved_reference = "32fa072821bff397466b55be2abda62bd93e6a8d" name = "cookiecutter" version = "2.4.0" description = "A command-line utility that creates projects from project templates, e.g. creating a Python package project from a Python package project template." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -467,7 +447,6 @@ rich = "*" name = "coverage" version = "7.2.7" description = "Code coverage measurement for Python" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -543,7 +522,6 @@ toml = ["tomli"] name = "cryptography" version = "41.0.4" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -589,7 +567,6 @@ test-randomorder = ["pytest-randomly"] name = "decli" version = "0.6.1" description = "Minimal, easy-to-use, declarative cli tool" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -601,7 +578,6 @@ files = [ name = "deprecated" version = "1.2.14" description = "Python @deprecated decorator to deprecate old python classes, functions or methods." -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -619,7 +595,6 @@ dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "sphinx (<2)", "tox"] name = "docutils" version = "0.19" description = "Docutils -- Python Documentation Utilities" -category = "main" optional = true python-versions = ">=3.7" files = [ @@ -631,7 +606,6 @@ files = [ name = "duckdb" version = "0.9.0" description = "DuckDB embedded database" -category = "dev" optional = false python-versions = ">=3.7.0" files = [ @@ -680,7 +654,6 @@ files = [ name = "duckdb-engine" version = "0.9.2" description = "SQLAlchemy driver for duckdb" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -696,7 +669,6 @@ sqlalchemy = ">=1.3.22" name = "exceptiongroup" version = "1.1.3" description = "Backport of PEP 654 (exception groups)" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -711,7 +683,6 @@ test = ["pytest (>=6)"] name = "fs" version = "2.4.16" description = "Python's filesystem abstraction layer" -category = "main" optional = false python-versions = "*" files = [ @@ -731,7 +702,6 @@ scandir = ["scandir (>=1.5,<2.0)"] name = "fs-s3fs" version = "1.1.1" description = "Amazon S3 filesystem for PyFilesystem2" -category = "main" optional = true python-versions = "*" files = [ @@ -748,7 +718,6 @@ six = ">=1.10,<2.0" name = "furo" version = "2023.3.27" description = "A clean customisable Sphinx documentation theme." -category = "main" optional = true python-versions = ">=3.7" files = [ @@ -766,7 +735,6 @@ sphinx-basic-ng = "*" name = "greenlet" version = "2.0.2" description = "Lightweight in-process concurrent programming" -category = "main" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" files = [ @@ -840,7 +808,6 @@ test = ["objgraph", "psutil"] name = "idna" version = "3.4" description = "Internationalized Domain Names in Applications (IDNA)" -category = "main" optional = false python-versions = ">=3.5" files = [ @@ -852,7 +819,6 @@ 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 = [ @@ -864,7 +830,6 @@ files = [ name = "importlib-metadata" version = "6.7.0" description = "Read metadata from Python packages" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -885,7 +850,6 @@ testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs name = "importlib-resources" version = "5.12.0" description = "Read resources from Python packages" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -904,7 +868,6 @@ testing = ["flake8 (<5)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-chec name = "inflection" version = "0.5.1" description = "A port of Ruby on Rails inflector to Python" -category = "main" optional = false python-versions = ">=3.5" files = [ @@ -916,7 +879,6 @@ files = [ name = "iniconfig" version = "2.0.0" description = "brain-dead simple config-ini parsing" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -928,7 +890,6 @@ files = [ name = "jinja2" version = "3.1.2" description = "A very fast and expressive template engine." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -946,7 +907,6 @@ i18n = ["Babel (>=2.7)"] name = "jmespath" version = "1.0.1" description = "JSON Matching Expressions" -category = "main" optional = true python-versions = ">=3.7" files = [ @@ -958,7 +918,6 @@ files = [ name = "joblib" version = "1.3.2" description = "Lightweight pipelining with Python functions" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -970,7 +929,6 @@ files = [ name = "jsonpath-ng" version = "1.6.0" description = "A final implementation of JSONPath for Python that aims to be standard compliant, including arithmetic and binary comparison operators and providing clear AST for metaprogramming." -category = "main" optional = false python-versions = "*" files = [ @@ -985,7 +943,6 @@ ply = "*" name = "jsonschema" version = "4.17.3" description = "An implementation of JSON Schema validation for Python" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1009,7 +966,6 @@ format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339- name = "livereload" version = "2.6.3" description = "Python LiveReload is an awesome tool for web developers" -category = "main" optional = true python-versions = "*" files = [ @@ -1025,7 +981,6 @@ tornado = {version = "*", markers = "python_version > \"2.7\""} name = "markdown-it-py" version = "2.2.0" description = "Python port of markdown-it. Markdown parsing, done right!" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1051,7 +1006,6 @@ testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] name = "markupsafe" version = "2.1.3" description = "Safely add untrusted strings to HTML/XML markup." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1111,7 +1065,6 @@ files = [ name = "mdit-py-plugins" version = "0.3.5" description = "Collection of plugins for markdown-it-py" -category = "main" optional = true python-versions = ">=3.7" files = [ @@ -1131,7 +1084,6 @@ 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 = [ @@ -1143,7 +1095,6 @@ files = [ name = "memoization" version = "0.4.0" description = "A powerful caching library for Python, with TTL support and multiple algorithm options. (https://github.com/lonelyenvoy/python-memoization)" -category = "main" optional = false python-versions = ">=3, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, <4" files = [ @@ -1154,7 +1105,6 @@ files = [ name = "multidict" version = "6.0.4" description = "multidict implementation" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1238,7 +1188,6 @@ files = [ name = "mypy" version = "1.4.1" description = "Optional static typing for Python" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1286,7 +1235,6 @@ 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 = [ @@ -1298,7 +1246,6 @@ files = [ name = "myst-parser" version = "1.0.0" description = "An extended [CommonMark](https://spec.commonmark.org/) compliant parser," -category = "main" optional = true python-versions = ">=3.7" files = [ @@ -1326,7 +1273,6 @@ testing-docutils = ["pygments", "pytest (>=7,<8)", "pytest-param-files (>=0.3.4, name = "numpy" version = "1.21.6" description = "NumPy is the fundamental package for array computing with Python." -category = "dev" optional = false python-versions = ">=3.7,<3.11" files = [ @@ -1367,7 +1313,6 @@ files = [ name = "numpy" version = "1.24.4" description = "Fundamental package for array computing in Python" -category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -1405,7 +1350,6 @@ files = [ name = "packaging" version = "23.2" description = "Core utilities for Python packages" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1417,7 +1361,6 @@ files = [ name = "pendulum" version = "2.1.2" description = "Python datetimes made easy" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -1452,7 +1395,6 @@ pytzdata = ">=2020.1" name = "pkgutil-resolve-name" version = "1.3.10" description = "Resolve a name to an object." -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -1464,7 +1406,6 @@ files = [ name = "pluggy" version = "1.2.0" description = "plugin and hook calling mechanisms for python" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1483,7 +1424,6 @@ testing = ["pytest", "pytest-benchmark"] name = "ply" version = "3.11" description = "Python Lex & Yacc" -category = "main" optional = false python-versions = "*" files = [ @@ -1495,7 +1435,6 @@ files = [ name = "prompt-toolkit" version = "3.0.39" description = "Library for building powerful interactive command lines in Python" -category = "dev" optional = false python-versions = "*" files = [ @@ -1507,7 +1446,6 @@ files = [ name = "pyarrow" version = "12.0.1" description = "Python library for Apache Arrow" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1545,7 +1483,6 @@ numpy = ">=1.16.6" name = "pycparser" version = "2.21" description = "C parser in Python" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -1557,7 +1494,6 @@ files = [ name = "pygithub" version = "1.59.1" description = "Use the full Github API v3" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1575,7 +1511,6 @@ requests = ">=2.14.0" name = "pygments" version = "2.16.1" description = "Pygments is a syntax highlighting package written in Python." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1590,7 +1525,6 @@ plugins = ["importlib-metadata"] name = "pyjwt" version = "2.8.0" description = "JSON Web Token implementation in Python" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1611,7 +1545,6 @@ tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] name = "pynacl" version = "1.5.0" description = "Python binding to the Networking and Cryptography (NaCl) library" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -1638,7 +1571,6 @@ tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"] name = "pyrsistent" version = "0.19.3" description = "Persistent/Functional/Immutable data structures" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1675,7 +1607,6 @@ files = [ name = "pytest" version = "7.4.2" description = "pytest: simple powerful testing with Python" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1719,7 +1650,6 @@ histogram = ["pygal", "pygaljs"] name = "pytest-durations" version = "1.2.0" description = "Pytest plugin reporting fixtures and test functions execution time." -category = "main" optional = true python-versions = ">=3.6.2" files = [ @@ -1734,7 +1664,6 @@ pytest = ">=4.6" name = "pytest-snapshot" version = "0.9.0" description = "A plugin for snapshot testing with pytest." -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -1749,7 +1678,6 @@ pytest = ">=3.0.0" name = "python-dateutil" version = "2.8.2" description = "Extensions to the standard Python datetime module" -category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" files = [ @@ -1764,7 +1692,6 @@ six = ">=1.5" name = "python-dotenv" version = "0.21.1" description = "Read key-value pairs from a .env file and set them as environment variables" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1779,7 +1706,6 @@ cli = ["click (>=5.0)"] name = "python-slugify" version = "8.0.1" description = "A Python slugify application that also handles Unicode" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1797,7 +1723,6 @@ unidecode = ["Unidecode (>=1.1.1)"] name = "pytz" version = "2023.3.post1" description = "World timezone definitions, modern and historical" -category = "main" optional = false python-versions = "*" files = [ @@ -1809,7 +1734,6 @@ files = [ name = "pytzdata" version = "2020.1" description = "The Olson timezone database for Python." -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -1821,7 +1745,6 @@ files = [ name = "pyyaml" version = "6.0.1" description = "YAML parser and emitter for Python" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -1881,7 +1804,6 @@ files = [ name = "questionary" version = "1.10.0" description = "Python library to build pretty command line user prompts ⭐️" -category = "dev" optional = false python-versions = ">=3.6,<4.0" files = [ @@ -1899,7 +1821,6 @@ docs = ["Sphinx (>=3.3,<4.0)", "sphinx-autobuild (>=2020.9.1,<2021.0.0)", "sphin name = "referencing" version = "0.8.9" description = "JSON Referencing + Python" -category = "dev" optional = false python-versions = "*" files = [ @@ -1916,7 +1837,6 @@ yarl = "*" name = "requests" version = "2.31.0" description = "Python HTTP for Humans." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1938,7 +1858,6 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] name = "requests-mock" version = "1.11.0" description = "Mock out responses from the requests package" -category = "dev" optional = false python-versions = "*" files = [ @@ -1958,7 +1877,6 @@ test = ["fixtures", "mock", "purl", "pytest", "requests-futures", "sphinx", "tes name = "rich" version = "13.5.3" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" -category = "dev" optional = false python-versions = ">=3.7.0" files = [ @@ -1978,7 +1896,6 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] name = "s3transfer" version = "0.6.2" description = "An Amazon S3 Transfer Manager" -category = "main" optional = true python-versions = ">= 3.7" files = [ @@ -1996,7 +1913,6 @@ crt = ["botocore[crt] (>=1.20.29,<2.0a.0)"] name = "setuptools" version = "68.0.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2013,7 +1929,6 @@ testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs ( name = "simpleeval" version = "0.9.13" description = "A simple, safe single expression evaluator library." -category = "main" optional = false python-versions = "*" files = [ @@ -2025,7 +1940,6 @@ files = [ name = "simplejson" version = "3.19.2" description = "Simple, fast, extensible JSON encoder/decoder for Python" -category = "main" optional = false python-versions = ">=2.5, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -2133,7 +2047,6 @@ 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 = [ @@ -2145,7 +2058,6 @@ files = [ name = "snowballstemmer" version = "2.2.0" description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." -category = "main" optional = true python-versions = "*" files = [ @@ -2157,7 +2069,6 @@ files = [ name = "soupsieve" version = "2.4.1" description = "A modern CSS selector implementation for Beautiful Soup." -category = "main" optional = true python-versions = ">=3.7" files = [ @@ -2169,7 +2080,6 @@ files = [ name = "sphinx" version = "5.3.0" description = "Python documentation generator" -category = "main" optional = true python-versions = ">=3.6" files = [ @@ -2205,7 +2115,6 @@ test = ["cython", "html5lib", "pytest (>=4.6)", "typed_ast"] name = "sphinx-autobuild" version = "2021.3.14" description = "Rebuild Sphinx documentation on changes, with live-reload in the browser." -category = "main" optional = true python-versions = ">=3.6" files = [ @@ -2225,7 +2134,6 @@ test = ["pytest", "pytest-cov"] name = "sphinx-basic-ng" version = "1.0.0b2" description = "A modern skeleton for Sphinx themes." -category = "main" optional = true python-versions = ">=3.7" files = [ @@ -2243,7 +2151,6 @@ docs = ["furo", "ipython", "myst-parser", "sphinx-copybutton", "sphinx-inline-ta name = "sphinx-copybutton" version = "0.5.2" description = "Add a copy button to each of your code cells." -category = "main" optional = true python-versions = ">=3.7" files = [ @@ -2262,7 +2169,6 @@ rtd = ["ipython", "myst-nb", "sphinx", "sphinx-book-theme", "sphinx-examples"] name = "sphinx-inline-tabs" version = "2023.4.21" description = "Add inline tabbed content to your Sphinx documentation." -category = "main" optional = true python-versions = ">=3.8" files = [ @@ -2281,7 +2187,6 @@ test = ["pytest", "pytest-cov", "pytest-xdist"] name = "sphinx-reredirects" version = "0.1.2" description = "Handles redirects for moved pages in Sphinx documentation projects" -category = "main" optional = true python-versions = ">=3.5" files = [ @@ -2296,7 +2201,6 @@ sphinx = "*" name = "sphinxcontrib-applehelp" version = "1.0.2" description = "sphinxcontrib-applehelp is a sphinx extension which outputs Apple help books" -category = "main" optional = true python-versions = ">=3.5" files = [ @@ -2312,7 +2216,6 @@ test = ["pytest"] name = "sphinxcontrib-devhelp" version = "1.0.2" description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document." -category = "main" optional = true python-versions = ">=3.5" files = [ @@ -2328,7 +2231,6 @@ test = ["pytest"] name = "sphinxcontrib-htmlhelp" version = "2.0.0" description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" -category = "main" optional = true python-versions = ">=3.6" files = [ @@ -2344,7 +2246,6 @@ test = ["html5lib", "pytest"] 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 = [ @@ -2359,7 +2260,6 @@ test = ["flake8", "mypy", "pytest"] name = "sphinxcontrib-qthelp" version = "1.0.3" description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document." -category = "main" optional = true python-versions = ">=3.5" files = [ @@ -2375,7 +2275,6 @@ test = ["pytest"] name = "sphinxcontrib-serializinghtml" version = "1.1.5" description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)." -category = "main" optional = true python-versions = ">=3.5" files = [ @@ -2391,7 +2290,6 @@ test = ["pytest"] name = "sqlalchemy" version = "2.0.21" description = "Database Abstraction Library" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2479,7 +2377,6 @@ sqlcipher = ["sqlcipher3-binary"] name = "termcolor" version = "2.3.0" description = "ANSI color formatting for output in terminal" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2494,7 +2391,6 @@ tests = ["pytest", "pytest-cov"] name = "text-unidecode" version = "1.3" description = "The most basic Text::Unidecode port" -category = "dev" optional = false python-versions = "*" files = [ @@ -2506,7 +2402,6 @@ files = [ name = "time-machine" version = "2.10.0" description = "Travel through time in your tests." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2573,7 +2468,6 @@ python-dateutil = "*" name = "tomli" version = "2.0.1" description = "A lil' TOML parser" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2585,7 +2479,6 @@ files = [ name = "tomlkit" version = "0.12.1" description = "Style preserving TOML library" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2597,7 +2490,6 @@ files = [ name = "tornado" version = "6.2" description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." -category = "main" optional = true python-versions = ">= 3.7" files = [ @@ -2618,7 +2510,6 @@ files = [ name = "typed-ast" version = "1.5.5" description = "a fork of Python 2 and 3 ast modules with type comment support" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -2669,7 +2560,6 @@ files = [ name = "types-jsonschema" version = "4.17.0.10" description = "Typing stubs for jsonschema" -category = "dev" optional = false python-versions = "*" files = [ @@ -2681,7 +2571,6 @@ files = [ name = "types-python-dateutil" version = "2.8.19.14" description = "Typing stubs for python-dateutil" -category = "dev" optional = false python-versions = "*" files = [ @@ -2693,7 +2582,6 @@ files = [ name = "types-pytz" version = "2023.3.1.1" description = "Typing stubs for pytz" -category = "dev" optional = false python-versions = "*" files = [ @@ -2705,7 +2593,6 @@ files = [ name = "types-pyyaml" version = "6.0.12.12" description = "Typing stubs for PyYAML" -category = "dev" optional = false python-versions = "*" files = [ @@ -2717,7 +2604,6 @@ files = [ name = "types-requests" version = "2.31.0.6" description = "Typing stubs for requests" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2732,7 +2618,6 @@ types-urllib3 = "*" name = "types-simplejson" version = "3.19.0.2" description = "Typing stubs for simplejson" -category = "dev" optional = false python-versions = "*" files = [ @@ -2744,7 +2629,6 @@ files = [ name = "types-urllib3" version = "1.26.25.14" description = "Typing stubs for urllib3" -category = "dev" optional = false python-versions = "*" files = [ @@ -2756,7 +2640,6 @@ files = [ name = "typing-extensions" version = "4.7.1" description = "Backported and Experimental Type Hints for Python 3.7+" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2768,7 +2651,6 @@ files = [ name = "urllib3" version = "1.26.17" description = "HTTP library with thread-safe connection pooling, file post, and more." -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" files = [ @@ -2785,7 +2667,6 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] name = "wcwidth" version = "0.2.6" description = "Measures the displayed width of unicode strings in a terminal" -category = "dev" optional = false python-versions = "*" files = [ @@ -2797,7 +2678,6 @@ files = [ name = "wrapt" version = "1.15.0" description = "Module for decorators, wrappers and monkey patching." -category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" files = [ @@ -2882,7 +2762,6 @@ files = [ name = "xdoctest" version = "1.1.1" description = "A rewrite of the builtin doctest module" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -2910,7 +2789,6 @@ tests-strict = ["codecov (==2.0.15)", "pytest (==4.6.0)", "pytest (==4.6.0)", "p name = "yarl" version = "1.9.2" description = "Yet another URL library" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2999,7 +2877,6 @@ typing-extensions = {version = ">=3.7.4", markers = "python_version < \"3.8\""} name = "zipp" version = "3.15.0" description = "Backport of pathlib-compatible object wrapper for zip files" -category = "main" optional = false python-versions = ">=3.7" files = [ diff --git a/tests/core/test_mapper.py b/tests/core/test_mapper.py index cae6773ef..10f65cf8e 100644 --- a/tests/core/test_mapper.py +++ b/tests/core/test_mapper.py @@ -66,7 +66,7 @@ def sample_catalog_dict() -> dict: ObjectType( Property("id", IntegerType), Property("value", OneOf(StringType, IntegerType, BooleanType)), - ) + ), ), ), ).to_dict() @@ -155,6 +155,19 @@ def sample_stream(): @pytest.fixture def transform_stream_maps(): + nested_jellybean_custom_field_1 = ( + 'dict([(x["id"], x["value"]) for x in custom_fields]).get(1)' + ) + nested_jellybean_custom_field_2 = ( + 'int(dict([(x["id"], x["value"]) for x in custom_fields]).get(2)) ' + 'if dict([(x["id"], x["value"]) for x in custom_fields]).get(2) ' + "else None" + ) + nested_jellybean_custom_field_3 = ( + 'bool(dict([(x["id"], x["value"]) for x in custom_fields]).get(3)) ' + 'if dict([(x["id"], x["value"]) for x in custom_fields]).get(3) ' + "else None" + ) return { "repositories": { "repo_name": "_['name']", @@ -168,9 +181,9 @@ def transform_stream_maps(): }, "nested_jellybean": { "custom_fields": "__NULL__", - "custom_field_1": 'dict([(x["id"], x["value"]) for x in custom_fields]).get(1)', - "custom_field_2": 'int(dict([(x["id"], x["value"]) for x in custom_fields]).get(2)) if dict([(x["id"], x["value"]) for x in custom_fields]).get(2) else None', - "custom_field_3": 'bool(dict([(x["id"], x["value"]) for x in custom_fields]).get(3)) if dict([(x["id"], x["value"]) for x in custom_fields]).get(3) else None', + "custom_field_1": nested_jellybean_custom_field_1, + "custom_field_2": nested_jellybean_custom_field_2, + "custom_field_3": nested_jellybean_custom_field_3, }, } From 22ea165aa7b7aa6bff811e2826859d85077bb12c Mon Sep 17 00:00:00 2001 From: Haleemur Ali Date: Tue, 10 Oct 2023 17:04:23 -0400 Subject: [PATCH 6/7] regenerate lock file --- poetry.lock | 464 +--------------------------------------------------- 1 file changed, 4 insertions(+), 460 deletions(-) diff --git a/poetry.lock b/poetry.lock index 8e0534f1f..9697e01e1 100644 --- a/poetry.lock +++ b/poetry.lock @@ -22,23 +22,6 @@ files = [ {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, ] -[[package]] -name = "argcomplete" -version = "3.1.2" -description = "Bash tab completion for argparse" -optional = false -python-versions = ">=3.6" -files = [ - {file = "argcomplete-3.1.2-py3-none-any.whl", hash = "sha256:d97c036d12a752d1079f190bc1521c545b941fda89ad85d15afa909b4d1b9a99"}, - {file = "argcomplete-3.1.2.tar.gz", hash = "sha256:d5d1e5efd41435260b8f85673b74ea2e883affcbec9f4230c582689e8e78251b"}, -] - -[package.dependencies] -importlib-metadata = {version = ">=0.23,<7", markers = "python_version < \"3.8\""} - -[package.extras] -test = ["coverage", "mypy", "pexpect", "ruff", "wheel"] - [[package]] name = "arrow" version = "1.2.3" @@ -378,50 +361,6 @@ files = [ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] -[[package]] -name = "commitizen" -version = "3.9.0" -description = "Python commitizen client tool" -optional = false -python-versions = ">=3.7,<4.0" -files = [ - {file = "commitizen-3.9.0-py3-none-any.whl", hash = "sha256:ae6a525a0acdb65437e7ba0cf4714dfb3c5f528316a0bbf4368f8e537432f815"}, - {file = "commitizen-3.9.0.tar.gz", hash = "sha256:36630bea53a35bc2c578346d516ca6b9870f13c7e009c68265e2f098423de2a2"}, -] - -[package.dependencies] -argcomplete = ">=1.12.1,<3.2" -charset-normalizer = ">=2.1.0,<4" -colorama = ">=0.4.1,<0.5.0" -decli = ">=0.6.0,<0.7.0" -importlib_metadata = ">=4.13,<7" -jinja2 = ">=2.10.3" -packaging = ">=19" -pyyaml = ">=3.08" -questionary = ">=1.4.0,<2.0.0" -termcolor = ">=1.1,<3" -tomlkit = ">=0.5.3,<1.0.0" -typing-extensions = {version = ">=4.0.1,<5.0.0", markers = "python_version < \"3.8\""} - -[[package]] -name = "commitizen-version-bump" -version = "0.1.0" -description = "Commitizen customized for Meltano projects (https://commitizen-tools.github.io/commitizen/customization)" -optional = false -python-versions = "^3.7" -files = [] -develop = false - -[package.dependencies] -commitizen = ">=3.0.0,<4.0.0" -PyGithub = "^1.57" - -[package.source] -type = "git" -url = "https://github.com/meltano/commitizen-version-bump.git" -reference = "main" -resolved_reference = "32fa072821bff397466b55be2abda62bd93e6a8d" - [[package]] name = "cookiecutter" version = "2.4.0" @@ -563,34 +502,6 @@ ssh = ["bcrypt (>=3.1.5)"] test = ["pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] test-randomorder = ["pytest-randomly"] -[[package]] -name = "decli" -version = "0.6.1" -description = "Minimal, easy-to-use, declarative cli tool" -optional = false -python-versions = ">=3.7" -files = [ - {file = "decli-0.6.1-py3-none-any.whl", hash = "sha256:7815ac58617764e1a200d7cadac6315fcaacc24d727d182f9878dd6378ccf869"}, - {file = "decli-0.6.1.tar.gz", hash = "sha256:ed88ccb947701e8e5509b7945fda56e150e2ac74a69f25d47ac85ef30ab0c0f0"}, -] - -[[package]] -name = "deprecated" -version = "1.2.14" -description = "Python @deprecated decorator to deprecate old python classes, functions or methods." -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -files = [ - {file = "Deprecated-1.2.14-py2.py3-none-any.whl", hash = "sha256:6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c"}, - {file = "Deprecated-1.2.14.tar.gz", hash = "sha256:e5323eb936458dccc2582dc6f9c322c852a775a27065ff2b0c4970b9d53d01b3"}, -] - -[package.dependencies] -wrapt = ">=1.10,<2" - -[package.extras] -dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "sphinx (<2)", "tox"] - [[package]] name = "docutils" version = "0.19" @@ -1101,89 +1012,6 @@ files = [ {file = "memoization-0.4.0.tar.gz", hash = "sha256:fde5e7cd060ef45b135e0310cfec17b2029dc472ccb5bbbbb42a503d4538a135"}, ] -[[package]] -name = "multidict" -version = "6.0.4" -description = "multidict implementation" -optional = false -python-versions = ">=3.7" -files = [ - {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8"}, - {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eeb6dcc05e911516ae3d1f207d4b0520d07f54484c49dfc294d6e7d63b734171"}, - {file = "multidict-6.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d6d635d5209b82a3492508cf5b365f3446afb65ae7ebd755e70e18f287b0adf7"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c048099e4c9e9d615545e2001d3d8a4380bd403e1a0578734e0d31703d1b0c0b"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea20853c6dbbb53ed34cb4d080382169b6f4554d394015f1bef35e881bf83547"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16d232d4e5396c2efbbf4f6d4df89bfa905eb0d4dc5b3549d872ab898451f569"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36c63aaa167f6c6b04ef2c85704e93af16c11d20de1d133e39de6a0e84582a93"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:64bdf1086b6043bf519869678f5f2757f473dee970d7abf6da91ec00acb9cb98"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:43644e38f42e3af682690876cff722d301ac585c5b9e1eacc013b7a3f7b696a0"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7582a1d1030e15422262de9f58711774e02fa80df0d1578995c76214f6954988"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ddff9c4e225a63a5afab9dd15590432c22e8057e1a9a13d28ed128ecf047bbdc"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ee2a1ece51b9b9e7752e742cfb661d2a29e7bcdba2d27e66e28a99f1890e4fa0"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a2e4369eb3d47d2034032a26c7a80fcb21a2cb22e1173d761a162f11e562caa5"}, - {file = "multidict-6.0.4-cp310-cp310-win32.whl", hash = "sha256:574b7eae1ab267e5f8285f0fe881f17efe4b98c39a40858247720935b893bba8"}, - {file = "multidict-6.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:4dcbb0906e38440fa3e325df2359ac6cb043df8e58c965bb45f4e406ecb162cc"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:64da238a09d6039e3bd39bb3aee9c21a5e34f28bfa5aa22518581f910ff94af3"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5cb09abb18c1ea940fb99360ea0396f34d46566f157122c92dfa069d3e0e982"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:666daae833559deb2d609afa4490b85830ab0dfca811a98b70a205621a6109fe"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d18748f2d30f94f498e852c67d61261c643b349b9d2a581131725595c45ec6c"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:458f37be2d9e4c95e2d8866a851663cbc76e865b78395090786f6cd9b3bbf4f4"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:b1a2eeedcead3a41694130495593a559a668f382eee0727352b9a41e1c45759a"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7d6ae9d593ef8641544d6263c7fa6408cc90370c8cb2bbb65f8d43e5b0351d9c"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5979b5632c3e3534e42ca6ff856bb24b2e3071b37861c2c727ce220d80eee9ed"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dcfe792765fab89c365123c81046ad4103fcabbc4f56d1c1997e6715e8015461"}, - {file = "multidict-6.0.4-cp311-cp311-win32.whl", hash = "sha256:3601a3cece3819534b11d4efc1eb76047488fddd0c85a3948099d5da4d504636"}, - {file = "multidict-6.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:81a4f0b34bd92df3da93315c6a59034df95866014ac08535fc819f043bfd51f0"}, - {file = "multidict-6.0.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:67040058f37a2a51ed8ea8f6b0e6ee5bd78ca67f169ce6122f3e2ec80dfe9b78"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:853888594621e6604c978ce2a0444a1e6e70c8d253ab65ba11657659dcc9100f"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:39ff62e7d0f26c248b15e364517a72932a611a9b75f35b45be078d81bdb86603"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:af048912e045a2dc732847d33821a9d84ba553f5c5f028adbd364dd4765092ac"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e8b901e607795ec06c9e42530788c45ac21ef3aaa11dbd0c69de543bfb79a9"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62501642008a8b9871ddfccbf83e4222cf8ac0d5aeedf73da36153ef2ec222d2"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:99b76c052e9f1bc0721f7541e5e8c05db3941eb9ebe7b8553c625ef88d6eefde"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:509eac6cf09c794aa27bcacfd4d62c885cce62bef7b2c3e8b2e49d365b5003fe"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:21a12c4eb6ddc9952c415f24eef97e3e55ba3af61f67c7bc388dcdec1404a067"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:5cad9430ab3e2e4fa4a2ef4450f548768400a2ac635841bc2a56a2052cdbeb87"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab55edc2e84460694295f401215f4a58597f8f7c9466faec545093045476327d"}, - {file = "multidict-6.0.4-cp37-cp37m-win32.whl", hash = "sha256:5a4dcf02b908c3b8b17a45fb0f15b695bf117a67b76b7ad18b73cf8e92608775"}, - {file = "multidict-6.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:6ed5f161328b7df384d71b07317f4d8656434e34591f20552c7bcef27b0ab88e"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5fc1b16f586f049820c5c5b17bb4ee7583092fa0d1c4e28b5239181ff9532e0c"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1502e24330eb681bdaa3eb70d6358e818e8e8f908a22a1851dfd4e15bc2f8161"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b692f419760c0e65d060959df05f2a531945af31fda0c8a3b3195d4efd06de11"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45e1ecb0379bfaab5eef059f50115b54571acfbe422a14f668fc8c27ba410e7e"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddd3915998d93fbcd2566ddf9cf62cdb35c9e093075f862935573d265cf8f65d"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:59d43b61c59d82f2effb39a93c48b845efe23a3852d201ed2d24ba830d0b4cf2"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc8e1d0c705233c5dd0c5e6460fbad7827d5d36f310a0fadfd45cc3029762258"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6aa0418fcc838522256761b3415822626f866758ee0bc6632c9486b179d0b52"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6748717bb10339c4760c1e63da040f5f29f5ed6e59d76daee30305894069a660"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4d1a3d7ef5e96b1c9e92f973e43aa5e5b96c659c9bc3124acbbd81b0b9c8a951"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4372381634485bec7e46718edc71528024fcdc6f835baefe517b34a33c731d60"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b9d9e4e2b37daddb5c23ea33a3417901fa7c7b3dee2d855f63ee67a0b21e5b1"}, - {file = "multidict-6.0.4-cp38-cp38-win32.whl", hash = "sha256:e41b7e2b59679edfa309e8db64fdf22399eec4b0b24694e1b2104fb789207779"}, - {file = "multidict-6.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:d6c254ba6e45d8e72739281ebc46ea5eb5f101234f3ce171f0e9f5cc86991480"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:16ab77bbeb596e14212e7bab8429f24c1579234a3a462105cda4a66904998664"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc779e9e6f7fda81b3f9aa58e3a6091d49ad528b11ed19f6621408806204ad35"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ceef517eca3e03c1cceb22030a3e39cb399ac86bff4e426d4fc6ae49052cc60"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:281af09f488903fde97923c7744bb001a9b23b039a909460d0f14edc7bf59706"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:52f2dffc8acaba9a2f27174c41c9e57f60b907bb9f096b36b1a1f3be71c6284d"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b41156839806aecb3641f3208c0dafd3ac7775b9c4c422d82ee2a45c34ba81ca"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5e3fc56f88cc98ef8139255cf8cd63eb2c586531e43310ff859d6bb3a6b51f1"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8316a77808c501004802f9beebde51c9f857054a0c871bd6da8280e718444449"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bf6774e60d67a9efe02b3616fee22441d86fab4c6d335f9d2051d19d90a40063"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:e69924bfcdda39b722ef4d9aa762b2dd38e4632b3641b1d9a57ca9cd18f2f83a"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:6b181d8c23da913d4ff585afd1155a0e1194c0b50c54fcfe286f70cdaf2b7176"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:52509b5be062d9eafc8170e53026fbc54cf3b32759a23d07fd935fb04fc22d95"}, - {file = "multidict-6.0.4-cp39-cp39-win32.whl", hash = "sha256:27c523fbfbdfd19c6867af7346332b62b586eed663887392cff78d614f9ec313"}, - {file = "multidict-6.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:33029f5734336aa0d4c0384525da0387ef89148dc7191aae00ca5fb23d7aafc2"}, - {file = "multidict-6.0.4.tar.gz", hash = "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49"}, -] - [[package]] name = "mypy" version = "1.4.1" @@ -1432,9 +1260,9 @@ files = [ ] [[package]] -name = "prompt-toolkit" -version = "3.0.39" -description = "Library for building powerful interactive command lines in Python" +name = "py-cpuinfo" +version = "9.0.0" +description = "Get CPU info with pure Python" optional = false python-versions = "*" files = [ @@ -1490,23 +1318,6 @@ files = [ {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, ] -[[package]] -name = "pygithub" -version = "1.59.1" -description = "Use the full Github API v3" -optional = false -python-versions = ">=3.7" -files = [ - {file = "PyGithub-1.59.1-py3-none-any.whl", hash = "sha256:3d87a822e6c868142f0c2c4bf16cce4696b5a7a4d142a7bd160e1bdf75bc54a9"}, - {file = "PyGithub-1.59.1.tar.gz", hash = "sha256:c44e3a121c15bf9d3a5cc98d94c9a047a5132a9b01d22264627f58ade9ddc217"}, -] - -[package.dependencies] -deprecated = "*" -pyjwt = {version = ">=2.4.0", extras = ["crypto"]} -pynacl = ">=1.4.0" -requests = ">=2.14.0" - [[package]] name = "pygments" version = "2.16.1" @@ -1541,32 +1352,6 @@ dev = ["coverage[toml] (==5.0.4)", "cryptography (>=3.4.0)", "pre-commit", "pyte docs = ["sphinx (>=4.5.0,<5.0.0)", "sphinx-rtd-theme", "zope.interface"] tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] -[[package]] -name = "pynacl" -version = "1.5.0" -description = "Python binding to the Networking and Cryptography (NaCl) library" -optional = false -python-versions = ">=3.6" -files = [ - {file = "PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858"}, - {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b"}, - {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff"}, - {file = "PyNaCl-1.5.0-cp36-abi3-win32.whl", hash = "sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543"}, - {file = "PyNaCl-1.5.0-cp36-abi3-win_amd64.whl", hash = "sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93"}, - {file = "PyNaCl-1.5.0.tar.gz", hash = "sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba"}, -] - -[package.dependencies] -cffi = ">=1.4.1" - -[package.extras] -docs = ["sphinx (>=1.6.5)", "sphinx-rtd-theme"] -tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"] - [[package]] name = "pyrsistent" version = "0.19.3" @@ -1800,39 +1585,6 @@ files = [ {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, ] -[[package]] -name = "questionary" -version = "1.10.0" -description = "Python library to build pretty command line user prompts ⭐️" -optional = false -python-versions = ">=3.6,<4.0" -files = [ - {file = "questionary-1.10.0-py3-none-any.whl", hash = "sha256:fecfcc8cca110fda9d561cb83f1e97ecbb93c613ff857f655818839dac74ce90"}, - {file = "questionary-1.10.0.tar.gz", hash = "sha256:600d3aefecce26d48d97eee936fdb66e4bc27f934c3ab6dd1e292c4f43946d90"}, -] - -[package.dependencies] -prompt_toolkit = ">=2.0,<4.0" - -[package.extras] -docs = ["Sphinx (>=3.3,<4.0)", "sphinx-autobuild (>=2020.9.1,<2021.0.0)", "sphinx-autodoc-typehints (>=1.11.1,<2.0.0)", "sphinx-copybutton (>=0.3.1,<0.4.0)", "sphinx-rtd-theme (>=0.5.0,<0.6.0)"] - -[[package]] -name = "referencing" -version = "0.8.9" -description = "JSON Referencing + Python" -optional = false -python-versions = "*" -files = [ - {file = "referencing-0.8.9-py2.py3-none-any.whl", hash = "sha256:d144e834a707652a488c4d8b29949a4f7ece7526ea8c889d8d881bebee72bb6d"}, - {file = "referencing-0.8.9.tar.gz", hash = "sha256:2c0bc673a26fa0939d9f0a6bc8b0975f573b6f1fed14b42ee7597a766d4ec416"}, -] - -[package.dependencies] -attrs = "*" -pyrsistent = "*" -yarl = "*" - [[package]] name = "requests" version = "2.31.0" @@ -2373,20 +2125,6 @@ postgresql-psycopgbinary = ["psycopg[binary] (>=3.0.7)"] pymysql = ["pymysql"] sqlcipher = ["sqlcipher3-binary"] -[[package]] -name = "termcolor" -version = "2.3.0" -description = "ANSI color formatting for output in terminal" -optional = false -python-versions = ">=3.7" -files = [ - {file = "termcolor-2.3.0-py3-none-any.whl", hash = "sha256:3afb05607b89aed0ffe25202399ee0867ad4d3cb4180d98aaf8eefa6a5f7d475"}, - {file = "termcolor-2.3.0.tar.gz", hash = "sha256:b5b08f68937f138fe92f6c089b99f1e2da0ae56c52b78bf7075fd95420fd9a5a"}, -] - -[package.extras] -tests = ["pytest", "pytest-cov"] - [[package]] name = "text-unidecode" version = "1.3" @@ -2475,17 +2213,6 @@ files = [ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] -[[package]] -name = "tomlkit" -version = "0.12.1" -description = "Style preserving TOML library" -optional = false -python-versions = ">=3.7" -files = [ - {file = "tomlkit-0.12.1-py3-none-any.whl", hash = "sha256:712cbd236609acc6a3e2e97253dfc52d4c2082982a88f61b640ecf0817eab899"}, - {file = "tomlkit-0.12.1.tar.gz", hash = "sha256:38e1ff8edb991273ec9f6181244a6a391ac30e9f5098e7535640ea6be97a7c86"}, -] - [[package]] name = "tornado" version = "6.2" @@ -2663,101 +2390,6 @@ brotli = ["brotli (==1.0.9)", "brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotl secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] -[[package]] -name = "wcwidth" -version = "0.2.6" -description = "Measures the displayed width of unicode strings in a terminal" -optional = false -python-versions = "*" -files = [ - {file = "wcwidth-0.2.6-py2.py3-none-any.whl", hash = "sha256:795b138f6875577cd91bba52baf9e445cd5118fd32723b460e30a0af30ea230e"}, - {file = "wcwidth-0.2.6.tar.gz", hash = "sha256:a5220780a404dbe3353789870978e472cfe477761f06ee55077256e509b156d0"}, -] - -[[package]] -name = "wrapt" -version = "1.15.0" -description = "Module for decorators, wrappers and monkey patching." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" -files = [ - {file = "wrapt-1.15.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ca1cccf838cd28d5a0883b342474c630ac48cac5df0ee6eacc9c7290f76b11c1"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e826aadda3cae59295b95343db8f3d965fb31059da7de01ee8d1c40a60398b29"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5fc8e02f5984a55d2c653f5fea93531e9836abbd84342c1d1e17abc4a15084c2"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:96e25c8603a155559231c19c0349245eeb4ac0096fe3c1d0be5c47e075bd4f46"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:40737a081d7497efea35ab9304b829b857f21558acfc7b3272f908d33b0d9d4c"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:f87ec75864c37c4c6cb908d282e1969e79763e0d9becdfe9fe5473b7bb1e5f09"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:1286eb30261894e4c70d124d44b7fd07825340869945c79d05bda53a40caa079"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:493d389a2b63c88ad56cdc35d0fa5752daac56ca755805b1b0c530f785767d5e"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:58d7a75d731e8c63614222bcb21dd992b4ab01a399f1f09dd82af17bbfc2368a"}, - {file = "wrapt-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:21f6d9a0d5b3a207cdf7acf8e58d7d13d463e639f0c7e01d82cdb671e6cb7923"}, - {file = "wrapt-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ce42618f67741d4697684e501ef02f29e758a123aa2d669e2d964ff734ee00ee"}, - {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41d07d029dd4157ae27beab04d22b8e261eddfc6ecd64ff7000b10dc8b3a5727"}, - {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54accd4b8bc202966bafafd16e69da9d5640ff92389d33d28555c5fd4f25ccb7"}, - {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fbfbca668dd15b744418265a9607baa970c347eefd0db6a518aaf0cfbd153c0"}, - {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:76e9c727a874b4856d11a32fb0b389afc61ce8aaf281ada613713ddeadd1cfec"}, - {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e20076a211cd6f9b44a6be58f7eeafa7ab5720eb796975d0c03f05b47d89eb90"}, - {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a74d56552ddbde46c246b5b89199cb3fd182f9c346c784e1a93e4dc3f5ec9975"}, - {file = "wrapt-1.15.0-cp310-cp310-win32.whl", hash = "sha256:26458da5653aa5b3d8dc8b24192f574a58984c749401f98fff994d41d3f08da1"}, - {file = "wrapt-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:75760a47c06b5974aa5e01949bf7e66d2af4d08cb8c1d6516af5e39595397f5e"}, - {file = "wrapt-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ba1711cda2d30634a7e452fc79eabcadaffedf241ff206db2ee93dd2c89a60e7"}, - {file = "wrapt-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:56374914b132c702aa9aa9959c550004b8847148f95e1b824772d453ac204a72"}, - {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a89ce3fd220ff144bd9d54da333ec0de0399b52c9ac3d2ce34b569cf1a5748fb"}, - {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3bbe623731d03b186b3d6b0d6f51865bf598587c38d6f7b0be2e27414f7f214e"}, - {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3abbe948c3cbde2689370a262a8d04e32ec2dd4f27103669a45c6929bcdbfe7c"}, - {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b67b819628e3b748fd3c2192c15fb951f549d0f47c0449af0764d7647302fda3"}, - {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7eebcdbe3677e58dd4c0e03b4f2cfa346ed4049687d839adad68cc38bb559c92"}, - {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:74934ebd71950e3db69960a7da29204f89624dde411afbfb3b4858c1409b1e98"}, - {file = "wrapt-1.15.0-cp311-cp311-win32.whl", hash = "sha256:bd84395aab8e4d36263cd1b9308cd504f6cf713b7d6d3ce25ea55670baec5416"}, - {file = "wrapt-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:a487f72a25904e2b4bbc0817ce7a8de94363bd7e79890510174da9d901c38705"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:4ff0d20f2e670800d3ed2b220d40984162089a6e2c9646fdb09b85e6f9a8fc29"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9ed6aa0726b9b60911f4aed8ec5b8dd7bf3491476015819f56473ffaef8959bd"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:896689fddba4f23ef7c718279e42f8834041a21342d95e56922e1c10c0cc7afb"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:75669d77bb2c071333417617a235324a1618dba66f82a750362eccbe5b61d248"}, - {file = "wrapt-1.15.0-cp35-cp35m-win32.whl", hash = "sha256:fbec11614dba0424ca72f4e8ba3c420dba07b4a7c206c8c8e4e73f2e98f4c559"}, - {file = "wrapt-1.15.0-cp35-cp35m-win_amd64.whl", hash = "sha256:fd69666217b62fa5d7c6aa88e507493a34dec4fa20c5bd925e4bc12fce586639"}, - {file = "wrapt-1.15.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b0724f05c396b0a4c36a3226c31648385deb6a65d8992644c12a4963c70326ba"}, - {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbeccb1aa40ab88cd29e6c7d8585582c99548f55f9b2581dfc5ba68c59a85752"}, - {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38adf7198f8f154502883242f9fe7333ab05a5b02de7d83aa2d88ea621f13364"}, - {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:578383d740457fa790fdf85e6d346fda1416a40549fe8db08e5e9bd281c6a475"}, - {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:a4cbb9ff5795cd66f0066bdf5947f170f5d63a9274f99bdbca02fd973adcf2a8"}, - {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:af5bd9ccb188f6a5fdda9f1f09d9f4c86cc8a539bd48a0bfdc97723970348418"}, - {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:b56d5519e470d3f2fe4aa7585f0632b060d532d0696c5bdfb5e8319e1d0f69a2"}, - {file = "wrapt-1.15.0-cp36-cp36m-win32.whl", hash = "sha256:77d4c1b881076c3ba173484dfa53d3582c1c8ff1f914c6461ab70c8428b796c1"}, - {file = "wrapt-1.15.0-cp36-cp36m-win_amd64.whl", hash = "sha256:077ff0d1f9d9e4ce6476c1a924a3332452c1406e59d90a2cf24aeb29eeac9420"}, - {file = "wrapt-1.15.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5c5aa28df055697d7c37d2099a7bc09f559d5053c3349b1ad0c39000e611d317"}, - {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a8564f283394634a7a7054b7983e47dbf39c07712d7b177b37e03f2467a024e"}, - {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780c82a41dc493b62fc5884fb1d3a3b81106642c5c5c78d6a0d4cbe96d62ba7e"}, - {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e169e957c33576f47e21864cf3fc9ff47c223a4ebca8960079b8bd36cb014fd0"}, - {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b02f21c1e2074943312d03d243ac4388319f2456576b2c6023041c4d57cd7019"}, - {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f2e69b3ed24544b0d3dbe2c5c0ba5153ce50dcebb576fdc4696d52aa22db6034"}, - {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d787272ed958a05b2c86311d3a4135d3c2aeea4fc655705f074130aa57d71653"}, - {file = "wrapt-1.15.0-cp37-cp37m-win32.whl", hash = "sha256:02fce1852f755f44f95af51f69d22e45080102e9d00258053b79367d07af39c0"}, - {file = "wrapt-1.15.0-cp37-cp37m-win_amd64.whl", hash = "sha256:abd52a09d03adf9c763d706df707c343293d5d106aea53483e0ec8d9e310ad5e"}, - {file = "wrapt-1.15.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cdb4f085756c96a3af04e6eca7f08b1345e94b53af8921b25c72f096e704e145"}, - {file = "wrapt-1.15.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:230ae493696a371f1dbffaad3dafbb742a4d27a0afd2b1aecebe52b740167e7f"}, - {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63424c681923b9f3bfbc5e3205aafe790904053d42ddcc08542181a30a7a51bd"}, - {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6bcbfc99f55655c3d93feb7ef3800bd5bbe963a755687cbf1f490a71fb7794b"}, - {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c99f4309f5145b93eca6e35ac1a988f0dc0a7ccf9ccdcd78d3c0adf57224e62f"}, - {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b130fe77361d6771ecf5a219d8e0817d61b236b7d8b37cc045172e574ed219e6"}, - {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:96177eb5645b1c6985f5c11d03fc2dbda9ad24ec0f3a46dcce91445747e15094"}, - {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5fe3e099cf07d0fb5a1e23d399e5d4d1ca3e6dfcbe5c8570ccff3e9208274f7"}, - {file = "wrapt-1.15.0-cp38-cp38-win32.whl", hash = "sha256:abd8f36c99512755b8456047b7be10372fca271bf1467a1caa88db991e7c421b"}, - {file = "wrapt-1.15.0-cp38-cp38-win_amd64.whl", hash = "sha256:b06fa97478a5f478fb05e1980980a7cdf2712015493b44d0c87606c1513ed5b1"}, - {file = "wrapt-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2e51de54d4fb8fb50d6ee8327f9828306a959ae394d3e01a1ba8b2f937747d86"}, - {file = "wrapt-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0970ddb69bba00670e58955f8019bec4a42d1785db3faa043c33d81de2bf843c"}, - {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76407ab327158c510f44ded207e2f76b657303e17cb7a572ffe2f5a8a48aa04d"}, - {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd525e0e52a5ff16653a3fc9e3dd827981917d34996600bbc34c05d048ca35cc"}, - {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d37ac69edc5614b90516807de32d08cb8e7b12260a285ee330955604ed9dd29"}, - {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:078e2a1a86544e644a68422f881c48b84fef6d18f8c7a957ffd3f2e0a74a0d4a"}, - {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2cf56d0e237280baed46f0b5316661da892565ff58309d4d2ed7dba763d984b8"}, - {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7dc0713bf81287a00516ef43137273b23ee414fe41a3c14be10dd95ed98a2df9"}, - {file = "wrapt-1.15.0-cp39-cp39-win32.whl", hash = "sha256:46ed616d5fb42f98630ed70c3529541408166c22cdfd4540b88d5f21006b0eff"}, - {file = "wrapt-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:eef4d64c650f33347c1f9266fa5ae001440b232ad9b98f1f43dfe7a79435c0a6"}, - {file = "wrapt-1.15.0-py3-none-any.whl", hash = "sha256:64b1df0f83706b4ef4cfb4fb0e4c2669100fd7ecacfb59e091fad300d4e04640"}, - {file = "wrapt-1.15.0.tar.gz", hash = "sha256:d06730c6aed78cee4126234cf2d071e01b44b915e725a6cb439a879ec9754a3a"}, -] - [[package]] name = "xdoctest" version = "1.1.1" @@ -2785,94 +2417,6 @@ tests-binary = ["cmake", "cmake", "ninja", "ninja", "pybind11", "pybind11", "sci tests-binary-strict = ["cmake (==3.21.2)", "cmake (==3.25.0)", "ninja (==1.10.2)", "ninja (==1.11.1)", "pybind11 (==2.10.3)", "pybind11 (==2.7.1)", "scikit-build (==0.11.1)", "scikit-build (==0.16.1)"] tests-strict = ["codecov (==2.0.15)", "pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==6.2.5)", "pytest-cov (==3.0.0)", "typing (==3.7.4)"] -[[package]] -name = "yarl" -version = "1.9.2" -description = "Yet another URL library" -optional = false -python-versions = ">=3.7" -files = [ - {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8c2ad583743d16ddbdf6bb14b5cd76bf43b0d0006e918809d5d4ddf7bde8dd82"}, - {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:82aa6264b36c50acfb2424ad5ca537a2060ab6de158a5bd2a72a032cc75b9eb8"}, - {file = "yarl-1.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c0c77533b5ed4bcc38e943178ccae29b9bcf48ffd1063f5821192f23a1bd27b9"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee4afac41415d52d53a9833ebae7e32b344be72835bbb589018c9e938045a560"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9bf345c3a4f5ba7f766430f97f9cc1320786f19584acc7086491f45524a551ac"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a96c19c52ff442a808c105901d0bdfd2e28575b3d5f82e2f5fd67e20dc5f4ea"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:891c0e3ec5ec881541f6c5113d8df0315ce5440e244a716b95f2525b7b9f3608"}, - {file = "yarl-1.9.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c3a53ba34a636a256d767c086ceb111358876e1fb6b50dfc4d3f4951d40133d5"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:566185e8ebc0898b11f8026447eacd02e46226716229cea8db37496c8cdd26e0"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:2b0738fb871812722a0ac2154be1f049c6223b9f6f22eec352996b69775b36d4"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:32f1d071b3f362c80f1a7d322bfd7b2d11e33d2adf395cc1dd4df36c9c243095"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:e9fdc7ac0d42bc3ea78818557fab03af6181e076a2944f43c38684b4b6bed8e3"}, - {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:56ff08ab5df8429901ebdc5d15941b59f6253393cb5da07b4170beefcf1b2528"}, - {file = "yarl-1.9.2-cp310-cp310-win32.whl", hash = "sha256:8ea48e0a2f931064469bdabca50c2f578b565fc446f302a79ba6cc0ee7f384d3"}, - {file = "yarl-1.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:50f33040f3836e912ed16d212f6cc1efb3231a8a60526a407aeb66c1c1956dde"}, - {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:646d663eb2232d7909e6601f1a9107e66f9791f290a1b3dc7057818fe44fc2b6"}, - {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aff634b15beff8902d1f918012fc2a42e0dbae6f469fce134c8a0dc51ca423bb"}, - {file = "yarl-1.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a83503934c6273806aed765035716216cc9ab4e0364f7f066227e1aaea90b8d0"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b25322201585c69abc7b0e89e72790469f7dad90d26754717f3310bfe30331c2"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22a94666751778629f1ec4280b08eb11815783c63f52092a5953faf73be24191"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ec53a0ea2a80c5cd1ab397925f94bff59222aa3cf9c6da938ce05c9ec20428d"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:159d81f22d7a43e6eabc36d7194cb53f2f15f498dbbfa8edc8a3239350f59fe7"}, - {file = "yarl-1.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:832b7e711027c114d79dffb92576acd1bd2decc467dec60e1cac96912602d0e6"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:95d2ecefbcf4e744ea952d073c6922e72ee650ffc79028eb1e320e732898d7e8"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d4e2c6d555e77b37288eaf45b8f60f0737c9efa3452c6c44626a5455aeb250b9"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:783185c75c12a017cc345015ea359cc801c3b29a2966c2655cd12b233bf5a2be"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:b8cc1863402472f16c600e3e93d542b7e7542a540f95c30afd472e8e549fc3f7"}, - {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:822b30a0f22e588b32d3120f6d41e4ed021806418b4c9f0bc3048b8c8cb3f92a"}, - {file = "yarl-1.9.2-cp311-cp311-win32.whl", hash = "sha256:a60347f234c2212a9f0361955007fcf4033a75bf600a33c88a0a8e91af77c0e8"}, - {file = "yarl-1.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:be6b3fdec5c62f2a67cb3f8c6dbf56bbf3f61c0f046f84645cd1ca73532ea051"}, - {file = "yarl-1.9.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:38a3928ae37558bc1b559f67410df446d1fbfa87318b124bf5032c31e3447b74"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac9bb4c5ce3975aeac288cfcb5061ce60e0d14d92209e780c93954076c7c4367"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3da8a678ca8b96c8606bbb8bfacd99a12ad5dd288bc6f7979baddd62f71c63ef"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:13414591ff516e04fcdee8dc051c13fd3db13b673c7a4cb1350e6b2ad9639ad3"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf74d08542c3a9ea97bb8f343d4fcbd4d8f91bba5ec9d5d7f792dbe727f88938"}, - {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e7221580dc1db478464cfeef9b03b95c5852cc22894e418562997df0d074ccc"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:494053246b119b041960ddcd20fd76224149cfea8ed8777b687358727911dd33"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:52a25809fcbecfc63ac9ba0c0fb586f90837f5425edfd1ec9f3372b119585e45"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:e65610c5792870d45d7b68c677681376fcf9cc1c289f23e8e8b39c1485384185"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:1b1bba902cba32cdec51fca038fd53f8beee88b77efc373968d1ed021024cc04"}, - {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:662e6016409828ee910f5d9602a2729a8a57d74b163c89a837de3fea050c7582"}, - {file = "yarl-1.9.2-cp37-cp37m-win32.whl", hash = "sha256:f364d3480bffd3aa566e886587eaca7c8c04d74f6e8933f3f2c996b7f09bee1b"}, - {file = "yarl-1.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6a5883464143ab3ae9ba68daae8e7c5c95b969462bbe42e2464d60e7e2698368"}, - {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5610f80cf43b6202e2c33ba3ec2ee0a2884f8f423c8f4f62906731d876ef4fac"}, - {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b9a4e67ad7b646cd6f0938c7ebfd60e481b7410f574c560e455e938d2da8e0f4"}, - {file = "yarl-1.9.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:83fcc480d7549ccebe9415d96d9263e2d4226798c37ebd18c930fce43dfb9574"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fcd436ea16fee7d4207c045b1e340020e58a2597301cfbcfdbe5abd2356c2fb"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84e0b1599334b1e1478db01b756e55937d4614f8654311eb26012091be109d59"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3458a24e4ea3fd8930e934c129b676c27452e4ebda80fbe47b56d8c6c7a63a9e"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:838162460b3a08987546e881a2bfa573960bb559dfa739e7800ceeec92e64417"}, - {file = "yarl-1.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f4e2d08f07a3d7d3e12549052eb5ad3eab1c349c53ac51c209a0e5991bbada78"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:de119f56f3c5f0e2fb4dee508531a32b069a5f2c6e827b272d1e0ff5ac040333"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:149ddea5abf329752ea5051b61bd6c1d979e13fbf122d3a1f9f0c8be6cb6f63c"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:674ca19cbee4a82c9f54e0d1eee28116e63bc6fd1e96c43031d11cbab8b2afd5"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:9b3152f2f5677b997ae6c804b73da05a39daa6a9e85a512e0e6823d81cdad7cc"}, - {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5415d5a4b080dc9612b1b63cba008db84e908b95848369aa1da3686ae27b6d2b"}, - {file = "yarl-1.9.2-cp38-cp38-win32.whl", hash = "sha256:f7a3d8146575e08c29ed1cd287068e6d02f1c7bdff8970db96683b9591b86ee7"}, - {file = "yarl-1.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:63c48f6cef34e6319a74c727376e95626f84ea091f92c0250a98e53e62c77c72"}, - {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:75df5ef94c3fdc393c6b19d80e6ef1ecc9ae2f4263c09cacb178d871c02a5ba9"}, - {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c027a6e96ef77d401d8d5a5c8d6bc478e8042f1e448272e8d9752cb0aff8b5c8"}, - {file = "yarl-1.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3b078dbe227f79be488ffcfc7a9edb3409d018e0952cf13f15fd6512847f3f7"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59723a029760079b7d991a401386390c4be5bfec1e7dd83e25a6a0881859e716"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b03917871bf859a81ccb180c9a2e6c1e04d2f6a51d953e6a5cdd70c93d4e5a2a"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c1012fa63eb6c032f3ce5d2171c267992ae0c00b9e164efe4d73db818465fac3"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a74dcbfe780e62f4b5a062714576f16c2f3493a0394e555ab141bf0d746bb955"}, - {file = "yarl-1.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8c56986609b057b4839968ba901944af91b8e92f1725d1a2d77cbac6972b9ed1"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2c315df3293cd521033533d242d15eab26583360b58f7ee5d9565f15fee1bef4"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:b7232f8dfbd225d57340e441d8caf8652a6acd06b389ea2d3222b8bc89cbfca6"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:53338749febd28935d55b41bf0bcc79d634881195a39f6b2f767870b72514caf"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:066c163aec9d3d073dc9ffe5dd3ad05069bcb03fcaab8d221290ba99f9f69ee3"}, - {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8288d7cd28f8119b07dd49b7230d6b4562f9b61ee9a4ab02221060d21136be80"}, - {file = "yarl-1.9.2-cp39-cp39-win32.whl", hash = "sha256:b124e2a6d223b65ba8768d5706d103280914d61f5cae3afbc50fc3dfcc016623"}, - {file = "yarl-1.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:61016e7d582bc46a5378ffdd02cd0314fb8ba52f40f9cf4d9a5e7dbef88dee18"}, - {file = "yarl-1.9.2.tar.gz", hash = "sha256:04ab9d4b9f587c06d801c2abfe9317b77cdf996c65a90d5e84ecc45010823571"}, -] - -[package.dependencies] -idna = ">=2.0" -multidict = ">=4.0" -typing-extensions = {version = ">=3.7.4", markers = "python_version < \"3.8\""} - [[package]] name = "zipp" version = "3.15.0" @@ -2896,4 +2440,4 @@ testing = ["pytest", "pytest-durations"] [metadata] lock-version = "2.0" python-versions = ">=3.7.1,<4" -content-hash = "b1e49eacb32e9a38016d024dc71b58408c92b2a41c5b6c0de7f935b9449f91c0" +content-hash = "1074b3c2c3ec920f94b3f8503f5af099e4ff96399245e9b47415574f64321000" From fd56bb217b5697457058e9defe35d7f1891210f4 Mon Sep 17 00:00:00 2001 From: Haleemur Ali Date: Tue, 10 Oct 2023 17:48:43 -0400 Subject: [PATCH 7/7] ignore mypy-3.8 failures --- singer_sdk/mapper.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/singer_sdk/mapper.py b/singer_sdk/mapper.py index b6e8b11db..5b19f0b07 100644 --- a/singer_sdk/mapper.py +++ b/singer_sdk/mapper.py @@ -13,7 +13,7 @@ import logging import typing as t -import simpleeval +import simpleeval # type: ignore[import] import singer_sdk.typing as th from singer_sdk.exceptions import MapExpressionError, StreamMapConfigError @@ -409,7 +409,7 @@ def _init_functions_and_schema( # noqa: PLR0912, PLR0915, C901 if stream_map and MAPPER_FILTER_OPTION in stream_map: filter_rule = stream_map.pop(MAPPER_FILTER_OPTION) try: - filter_rule_parsed: ast.Expr = ast.parse(filter_rule).body[0] + filter_rule_parsed: ast.Expr = ast.parse(filter_rule).body[0] # type: ignore[arg-type,assignment] except (SyntaxError, IndexError) as ex: msg = f"Failed to parse expression {filter_rule}." raise MapExpressionError(msg) from ex @@ -489,7 +489,7 @@ def _init_functions_and_schema( # noqa: PLR0912, PLR0915, C901 ).to_dict(), ) try: - parsed_def: ast.Expr = ast.parse(prop_def).body[0] + parsed_def: ast.Expr = ast.parse(prop_def).body[0] # type: ignore[assignment] stream_map_parsed.append((prop_key, prop_def, parsed_def)) except (SyntaxError, IndexError) as ex: msg = f"Failed to parse expression {prop_def}." @@ -579,7 +579,7 @@ def transform_fn(record: dict) -> dict | None: if isinstance(prop_def_parsed, ast.Expr): # Apply property transform result[prop_key] = self._eval( - expr=prop_def, + expr=prop_def, # type: ignore[arg-type] expr_parsed=prop_def_parsed, record=record, property_name=prop_key,