From f4a5ad44e888e16b8a8b6f1537146d78970fb129 Mon Sep 17 00:00:00 2001 From: Altay Sansal Date: Tue, 25 Jun 2024 10:09:02 -0500 Subject: [PATCH] Parsing local and cloud SEG-Y files with new I/O library (#381) * Refactor text_header setter type check Removed the list type check from the text_header setter in accessor.py. The application now expects a string input instead of a list, simplifying the validation process. * Refactor text_header setter type check Removed the list type check from the text_header setter in accessor.py. The application now expects a string input instead of a list, simplifying the validation process. * Refactor text_header setter type check Removed the list type check from the text_header setter in accessor.py. The application now expects a string input instead of a list, simplifying the validation process. * Refactor workers for SEG-Y parsing Simplify `header_scan_worker` and `trace_worker` in SEG-Y module by removing unused imports and streamlining parameter list. Update functions to work directly with `SegyFile` instances and clean up data handling logic for efficiency. * Refactor SEG-Y parser and streamline imports Refactor the parsing functions in `src/mdio/segy/parsers.py` to simplify the codebase and improve maintainability. Redundant functions such as `parse_binary_header`, `parse_text_header`, and `get_trace_count` have been removed, while imports have been condensed to only essential modules. The `NUM_CORES` logic is updated to count logical cores instead of just physical ones. * Refactor SEG-Y converter and simplify imports Removed unused imports and functions in the SEG-Y converter module to enhance code maintainability. Simplified the arguments for the `segy_to_mdio` function to increase ease of use and readability. Reduced complexity by utilizing `SegyFile` class for SEG-Y file operations. * Refactor get_grid_plan and remove unused imports The get_grid_plan function in utilities.py has been refactored to accept a SegyFile instance instead of individual parameters for the file path. Unused imports were eliminated, and type checking imports are now conditional, improving readability and modularity. * use NDArray typing since we now return struct * Refactor to use 'segy' instead of 'segyio'. The changes involve major refactoring of the code base to use the 'segy' library instead of 'segyio'. Most notably, this included updating the handling of SEG-Y dtypes, byte order, and trace headers. Unused imports have been removed to clean up the code. A new multiprocessing chunk size has been introduced and set attributes to SegyFile instance instead of passing them as function arguments. * refactor override tests to use ndarray headers instead of a dictionary to make it work with 'segy'. * Remove unit tests for IBM/IEEE conversions and text headers * Refactor and simplify 6D tests related to SEG-Y * Refactor and simplify 6D tests related to SEG-Y * Upgrade segy package version The segy package version has been updated from 0.0.13 to 0.0.14 in the pyproject.toml file. This upgrade was performed to update software dependencies and to integrate the latest bug fixes and features delivered with the new version. * Refactored segy factory creation in mdio_to_segy function A new helper function, 'make_segy_factory', has been created to handle the generation of SegyFactory. This function accepts more parameters to provide better control over the creation of the SEG-Y based on the MDIO metadata. Changes also include updates in import declarations and reorganization of some code blocks in the 'mdio_spec_to_segy' function. * Update segy library version * Multiply sample_interval by 1000 in SegyFactory In the SegyFactory initialization within creation.py, the sample_interval parameter has been modified to be multiplied by 1000. This change ensures that the value is correctly represented in microseconds, aligning with the expected data format. * fix docstring errors * Update dependency package versions * update field name for segy data * import Endianness from new location * use bleeding edge segy during dev * allow configuring endianness on export * update binary header * Update the 'segy' git repository link * Update virtualenv version in constraints.txt * Update poetry version in workflow constraints * update RtD dependencies * switch myst-nb to stable * fix broken tests * fix broken tests * simplify factory usage and fix tests * add original segyio fields as spec * Add pytest-dependency to project dev dependencies * fix: headers were missed due to early return * streamline mdio segy spec * simplify mock 4d generation * enforce mdio segy spec * update type hints to the correct segy type. * revert api * update type hints * remove endian from segy import because its inferred * remove output format from seg-y export. we only export as its set in "binary header" * update endian kwarg name * revert to old api * enable all tests * Update get_grid_plan * Remove unused byte swapping function from segy creation module. * Remove now unused byte utils module * Add temporary safety check ignore for specific CVE The safety check in noxfile.py has been updated to temporarily ignore a specific Common Vulnerabilities and Exposures (CVE) number because it's not deemed critical. A TODO note is added to remind removal of this exception once the issue is resolved. * fix safety ignore syntax * make temp zarr files module scoped * revert to_segy endian api * simplify changes * Correct variable in default chunk selection * Update segy package version in pyproject.toml * use correct spec for factory * use new endian inference from `segy` * get header dtype from spec instead of reading a header * remove unnecessary cast * remove commented line * Implement dynamic CPU count for header parsing * backward_compat: revert text header to write as list[str] instead of str with newline * generate spec as needed and avoid singleton bugs * bump version * add missing return doc * Add future annotations import for type hints --- .github/workflows/constraints-poetry.txt | 2 +- .github/workflows/constraints.txt | 2 +- docs/requirements.txt | 5 +- noxfile.py | 18 +- poetry.lock | 1551 ++++++++++++------ pyproject.toml | 62 +- src/mdio/commands/segy.py | 24 - src/mdio/converters/mdio.py | 21 +- src/mdio/converters/segy.py | 79 +- src/mdio/segy/_standards_common.py | 37 - src/mdio/segy/_standards_rev0.py | 124 -- src/mdio/segy/_workers.py | 183 +-- src/mdio/segy/blocked_io.py | 53 +- src/mdio/segy/byte_utils.py | 92 -- src/mdio/segy/compat.py | 73 + src/mdio/segy/creation.py | 175 +- src/mdio/segy/ebcdic.py | 71 - src/mdio/segy/geometry.py | 85 +- src/mdio/segy/headers.py | 102 -- src/mdio/segy/headers_text.py | 112 -- src/mdio/segy/ibm_float.py | 189 --- src/mdio/segy/parsers.py | 124 +- src/mdio/segy/utilities.py | 55 +- tests/conftest.py | 17 +- tests/integration/conftest.py | 103 +- tests/integration/test_segy_import_export.py | 256 ++- tests/unit/test_ibm_ieee.py | 88 - tests/unit/test_segy_grid_overrides.py | 44 +- tests/unit/test_text_header.py | 136 -- 29 files changed, 1577 insertions(+), 2306 deletions(-) delete mode 100644 src/mdio/segy/_standards_common.py delete mode 100644 src/mdio/segy/_standards_rev0.py delete mode 100644 src/mdio/segy/byte_utils.py create mode 100644 src/mdio/segy/compat.py delete mode 100644 src/mdio/segy/ebcdic.py delete mode 100644 src/mdio/segy/headers.py delete mode 100644 src/mdio/segy/headers_text.py delete mode 100644 src/mdio/segy/ibm_float.py delete mode 100644 tests/unit/test_ibm_ieee.py delete mode 100644 tests/unit/test_text_header.py diff --git a/.github/workflows/constraints-poetry.txt b/.github/workflows/constraints-poetry.txt index db76d9bc..65e7a6ca 100644 --- a/.github/workflows/constraints-poetry.txt +++ b/.github/workflows/constraints-poetry.txt @@ -1 +1 @@ -poetry==1.8.2 +poetry==1.8.3 diff --git a/.github/workflows/constraints.txt b/.github/workflows/constraints.txt index f13e3b5d..421e9f39 100644 --- a/.github/workflows/constraints.txt +++ b/.github/workflows/constraints.txt @@ -1,4 +1,4 @@ pip==24.0 nox==2024.4.15 nox-poetry==1.0.3 -virtualenv==20.26.1 +virtualenv==20.26.2 diff --git a/docs/requirements.txt b/docs/requirements.txt index b9320d5b..60fd533e 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,7 +1,6 @@ furo==2024.5.6 sphinx==7.3.7 -sphinx-click==5.1.0 +sphinx-click==6.0.0 sphinx-copybutton==0.5.2 -# myst-nb==0.17.2 -myst-nb @ git+https://github.com/executablebooks/MyST-NB@35ebd54 +myst-nb==1.1.0 linkify-it-py==2.0.3 diff --git a/noxfile.py b/noxfile.py index 83a6e2b8..a6b088c5 100644 --- a/noxfile.py +++ b/noxfile.py @@ -144,7 +144,15 @@ def safety(session: Session) -> None: """Scan dependencies for insecure packages.""" requirements = session.poetry.export_requirements() session.install("safety") - session.run("safety", "check", "--full-report", f"--file={requirements}") + # TODO(Altay): Remove the CVE ignore once its resolved. Its not critical, so ignoring now. + ignore = ["70612"] + session.run( + "safety", + "check", + "--full-report", + f"--file={requirements}", + f"--ignore={','.join(ignore)}", + ) @session(python=python_versions) @@ -219,9 +227,7 @@ def docs_build(session: Session) -> None: "sphinx-click", "sphinx-copybutton", "furo", - # TODO(Altay): Update this to v1.0.0 when its out. Right now we - # use this because myst-nb stable doesn't work with Sphinx 7. - "myst-nb@git+https://github.com/executablebooks/MyST-NB@35ebd54", + "myst-nb", "linkify-it-py", ) @@ -243,9 +249,7 @@ def docs(session: Session) -> None: "sphinx-click", "sphinx-copybutton", "furo", - # TODO(Altay): Update this to v1.0.0 when its out. Right now we - # use this because myst-nb stable doesn't work with Sphinx 7. - "myst-nb@git+https://github.com/executablebooks/MyST-NB@35ebd54", + "myst-nb", "linkify-it-py", ) diff --git a/poetry.lock b/poetry.lock index d0b699e0..4bb74c86 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. [[package]] name = "adlfs" @@ -25,24 +25,24 @@ tests = ["arrow", "dask[dataframe]", "docker", "pytest", "pytest-mock"] [[package]] name = "aiobotocore" -version = "2.13.0" +version = "2.13.1" description = "Async client for aws services using botocore and aiohttp" optional = true python-versions = ">=3.8" files = [ - {file = "aiobotocore-2.13.0-py3-none-any.whl", hash = "sha256:f812afc678d71b0038fd1ce712ff111ab7f47bab81ce5b4c7d222d4b83bc0cb2"}, - {file = "aiobotocore-2.13.0.tar.gz", hash = "sha256:4badf5cab6ad400216319d14278e2c99ad9b708e28a0f231605a412e632de401"}, + {file = "aiobotocore-2.13.1-py3-none-any.whl", hash = "sha256:1bef121b99841ee3cc788e4ed97c332ba32353b1f00e886d1beb3aae95520858"}, + {file = "aiobotocore-2.13.1.tar.gz", hash = "sha256:134f9606c2f91abde38cbc61c3241113e26ff244633e0c31abb7e09da3581c9b"}, ] [package.dependencies] aiohttp = ">=3.9.2,<4.0.0" aioitertools = ">=0.5.1,<1.0.0" -botocore = ">=1.34.70,<1.34.107" +botocore = ">=1.34.70,<1.34.132" wrapt = ">=1.10.10,<2.0.0" [package.extras] -awscli = ["awscli (>=1.32.70,<1.32.107)"] -boto3 = ["boto3 (>=1.34.70,<1.34.107)"] +awscli = ["awscli (>=1.32.70,<1.33.14)"] +boto3 = ["boto3 (>=1.34.70,<1.34.132)"] [[package]] name = "aiohttp" @@ -179,6 +179,39 @@ files = [ {file = "alabaster-0.7.16.tar.gz", hash = "sha256:75a8b99c28a5dad50dd7f8ccdd447a121ddb3892da9e53d1ca5cca3106d58d65"}, ] +[[package]] +name = "annotated-types" +version = "0.7.0" +description = "Reusable constraint types to use with typing.Annotated" +optional = false +python-versions = ">=3.8" +files = [ + {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, + {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, +] + +[[package]] +name = "anyio" +version = "4.4.0" +description = "High level compatibility layer for multiple asynchronous event loop implementations" +optional = false +python-versions = ">=3.8" +files = [ + {file = "anyio-4.4.0-py3-none-any.whl", hash = "sha256:c1b2d8f46a8a812513012e1107cb0e68c17159a7a594208005a57dc776e1bdc7"}, + {file = "anyio-4.4.0.tar.gz", hash = "sha256:5aadc6a1bbb7cdb0bede386cac5e2940f5e2ff3aa20277e991cf028e0585ce94"}, +] + +[package.dependencies] +exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} +idna = ">=2.8" +sniffio = ">=1.1" +typing-extensions = {version = ">=4.1", markers = "python_version < \"3.11\""} + +[package.extras] +doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] +test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] +trio = ["trio (>=0.23)"] + [[package]] name = "asciitree" version = "0.3.3" @@ -219,15 +252,29 @@ tests = ["attrs[tests-no-zope]", "zope-interface"] tests-mypy = ["mypy (>=1.6)", "pytest-mypy-plugins"] tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"] +[[package]] +name = "authlib" +version = "1.3.1" +description = "The ultimate Python library in building OAuth and OpenID Connect servers and clients." +optional = false +python-versions = ">=3.8" +files = [ + {file = "Authlib-1.3.1-py2.py3-none-any.whl", hash = "sha256:d35800b973099bbadc49b42b256ecb80041ad56b7fe1216a362c7943c088f377"}, + {file = "authlib-1.3.1.tar.gz", hash = "sha256:7ae843f03c06c5c0debd63c9db91f9fda64fa62a42a77419fa15fbb7e7a58917"}, +] + +[package.dependencies] +cryptography = "*" + [[package]] name = "azure-core" -version = "1.30.1" +version = "1.30.2" description = "Microsoft Azure Core Library for Python" optional = true -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "azure-core-1.30.1.tar.gz", hash = "sha256:26273a254131f84269e8ea4464f3560c731f29c0c1f69ac99010845f239c1a8f"}, - {file = "azure_core-1.30.1-py3-none-any.whl", hash = "sha256:7c5ee397e48f281ec4dd773d67a0a47a0962ed6fa833036057f9ea067f688e74"}, + {file = "azure-core-1.30.2.tar.gz", hash = "sha256:a14dc210efcd608821aa472d9fb8e8d035d29b68993819147bc290a8ac224472"}, + {file = "azure_core-1.30.2-py3-none-any.whl", hash = "sha256:cf019c1ca832e96274ae85abd3d9f752397194d9fea3b41487290562ac8abe4a"}, ] [package.dependencies] @@ -256,13 +303,13 @@ requests = ">=2.20.0" [[package]] name = "azure-identity" -version = "1.16.0" +version = "1.17.1" description = "Microsoft Azure Identity Library for Python" optional = true python-versions = ">=3.8" files = [ - {file = "azure-identity-1.16.0.tar.gz", hash = "sha256:6ff1d667cdcd81da1ceab42f80a0be63ca846629f518a922f7317a7e3c844e1b"}, - {file = "azure_identity-1.16.0-py3-none-any.whl", hash = "sha256:722fdb60b8fdd55fa44dc378b8072f4b419b56a5e54c0de391f644949f3a826f"}, + {file = "azure-identity-1.17.1.tar.gz", hash = "sha256:32ecc67cc73f4bd0595e4f64b1ca65cd05186f4fe6f98ed2ae9f1aa32646efea"}, + {file = "azure_identity-1.17.1-py3-none-any.whl", hash = "sha256:db8d59c183b680e763722bfe8ebc45930e6c57df510620985939f7f3191e0382"}, ] [package.dependencies] @@ -270,6 +317,7 @@ azure-core = ">=1.23.0" cryptography = ">=2.5" msal = ">=1.24.0" msal-extensions = ">=0.3.0" +typing-extensions = ">=4.0.0" [[package]] name = "azure-storage-blob" @@ -307,13 +355,13 @@ dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] [[package]] name = "bandit" -version = "1.7.8" +version = "1.7.9" description = "Security oriented static analyser for python code." optional = false python-versions = ">=3.8" files = [ - {file = "bandit-1.7.8-py3-none-any.whl", hash = "sha256:509f7af645bc0cd8fd4587abc1a038fc795636671ee8204d502b933aee44f381"}, - {file = "bandit-1.7.8.tar.gz", hash = "sha256:36de50f720856ab24a24dbaa5fee2c66050ed97c1477e0a1159deab1775eab6b"}, + {file = "bandit-1.7.9-py3-none-any.whl", hash = "sha256:52077cb339000f337fb25f7e045995c4ad01511e716e5daac37014b9752de8ec"}, + {file = "bandit-1.7.9.tar.gz", hash = "sha256:7c395a436743018f7be0a4cbb0a4ea9b902b6d87264ddecf8cfdc73b4f78ff61"}, ] [package.dependencies] @@ -350,6 +398,17 @@ charset-normalizer = ["charset-normalizer"] html5lib = ["html5lib"] lxml = ["lxml"] +[[package]] +name = "bidict" +version = "0.23.1" +description = "The bidirectional mapping library for Python." +optional = false +python-versions = ">=3.8" +files = [ + {file = "bidict-0.23.1-py3-none-any.whl", hash = "sha256:5dae8d4d79b552a71cbabc7deb25dfe8ce710b17ff41711e13010ead2abfc3e5"}, + {file = "bidict-0.23.1.tar.gz", hash = "sha256:03069d763bc387bbd20e7d49914e75fc4132a41937fa3405417e1a5a2d006d71"}, +] + [[package]] name = "black" version = "24.4.2" @@ -398,13 +457,13 @@ uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "bokeh" -version = "3.4.1" +version = "3.4.2" description = "Interactive plots and applications in the browser from Python" optional = true python-versions = ">=3.9" files = [ - {file = "bokeh-3.4.1-py3-none-any.whl", hash = "sha256:1e3c502a0a8205338fc74dadbfa321f8a0965441b39501e36796a47b4017b642"}, - {file = "bokeh-3.4.1.tar.gz", hash = "sha256:d824961e4265367b0750ce58b07e564ad0b83ca64b335521cd3421e9b9f10d89"}, + {file = "bokeh-3.4.2-py3-none-any.whl", hash = "sha256:931a43ee59dbf1720383ab904f8205e126b85561aac55592415b800c96f1b0eb"}, + {file = "bokeh-3.4.2.tar.gz", hash = "sha256:a16d5cc0abb93d2d270d70fc35851f3e1b9208814a985a4678e0ba5ef2d9cd42"}, ] [package.dependencies] @@ -420,13 +479,13 @@ xyzservices = ">=2021.09.1" [[package]] name = "botocore" -version = "1.34.106" +version = "1.34.131" description = "Low-level, data-driven core of boto 3." optional = true python-versions = ">=3.8" files = [ - {file = "botocore-1.34.106-py3-none-any.whl", hash = "sha256:4baf0e27c2dfc4f4d0dee7c217c716e0782f9b30e8e1fff983fce237d88f73ae"}, - {file = "botocore-1.34.106.tar.gz", hash = "sha256:921fa5202f88c3e58fdcb4b3acffd56d65b24bca47092ee4b27aa988556c0be6"}, + {file = "botocore-1.34.131-py3-none-any.whl", hash = "sha256:13b011d7b206ce00727dcee26548fa3b550db9046d5a0e90ac25a6e6c8fde6ef"}, + {file = "botocore-1.34.131.tar.gz", hash = "sha256:502ddafe1d627fcf1e4c007c86454e5dd011dba7c58bd8e8a5368a79f3e387dc"}, ] [package.dependencies] @@ -438,7 +497,7 @@ urllib3 = [ ] [package.extras] -crt = ["awscrt (==0.20.9)"] +crt = ["awscrt (==0.20.11)"] [[package]] name = "cachetools" @@ -453,20 +512,20 @@ files = [ [[package]] name = "certifi" -version = "2024.2.2" +version = "2024.6.2" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, - {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, + {file = "certifi-2024.6.2-py3-none-any.whl", hash = "sha256:ddc6c8ce995e6987e7faf5e3f1b02b302836a0e5d98ece18392cb1a36c72ad56"}, + {file = "certifi-2024.6.2.tar.gz", hash = "sha256:3cd43f1c6fa7dedc5899d69d3ad0398fd018ad1a17fba83ddaf78aa46c747516"}, ] [[package]] name = "cffi" version = "1.16.0" description = "Foreign Function Interface for Python calling C code." -optional = true +optional = false python-versions = ">=3.8" files = [ {file = "cffi-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088"}, @@ -753,63 +812,63 @@ test-no-images = ["pytest", "pytest-cov", "pytest-xdist", "wurlitzer"] [[package]] name = "coverage" -version = "7.5.1" +version = "7.5.4" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.8" files = [ - {file = "coverage-7.5.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c0884920835a033b78d1c73b6d3bbcda8161a900f38a488829a83982925f6c2e"}, - {file = "coverage-7.5.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:39afcd3d4339329c5f58de48a52f6e4e50f6578dd6099961cf22228feb25f38f"}, - {file = "coverage-7.5.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a7b0ceee8147444347da6a66be737c9d78f3353b0681715b668b72e79203e4a"}, - {file = "coverage-7.5.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a9ca3f2fae0088c3c71d743d85404cec8df9be818a005ea065495bedc33da35"}, - {file = "coverage-7.5.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fd215c0c7d7aab005221608a3c2b46f58c0285a819565887ee0b718c052aa4e"}, - {file = "coverage-7.5.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4bf0655ab60d754491004a5efd7f9cccefcc1081a74c9ef2da4735d6ee4a6223"}, - {file = "coverage-7.5.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:61c4bf1ba021817de12b813338c9be9f0ad5b1e781b9b340a6d29fc13e7c1b5e"}, - {file = "coverage-7.5.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:db66fc317a046556a96b453a58eced5024af4582a8dbdc0c23ca4dbc0d5b3146"}, - {file = "coverage-7.5.1-cp310-cp310-win32.whl", hash = "sha256:b016ea6b959d3b9556cb401c55a37547135a587db0115635a443b2ce8f1c7228"}, - {file = "coverage-7.5.1-cp310-cp310-win_amd64.whl", hash = "sha256:df4e745a81c110e7446b1cc8131bf986157770fa405fe90e15e850aaf7619bc8"}, - {file = "coverage-7.5.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:796a79f63eca8814ca3317a1ea443645c9ff0d18b188de470ed7ccd45ae79428"}, - {file = "coverage-7.5.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4fc84a37bfd98db31beae3c2748811a3fa72bf2007ff7902f68746d9757f3746"}, - {file = "coverage-7.5.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6175d1a0559986c6ee3f7fccfc4a90ecd12ba0a383dcc2da30c2b9918d67d8a3"}, - {file = "coverage-7.5.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1fc81d5878cd6274ce971e0a3a18a8803c3fe25457165314271cf78e3aae3aa2"}, - {file = "coverage-7.5.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:556cf1a7cbc8028cb60e1ff0be806be2eded2daf8129b8811c63e2b9a6c43bca"}, - {file = "coverage-7.5.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9981706d300c18d8b220995ad22627647be11a4276721c10911e0e9fa44c83e8"}, - {file = "coverage-7.5.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d7fed867ee50edf1a0b4a11e8e5d0895150e572af1cd6d315d557758bfa9c057"}, - {file = "coverage-7.5.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ef48e2707fb320c8f139424a596f5b69955a85b178f15af261bab871873bb987"}, - {file = "coverage-7.5.1-cp311-cp311-win32.whl", hash = "sha256:9314d5678dcc665330df5b69c1e726a0e49b27df0461c08ca12674bcc19ef136"}, - {file = "coverage-7.5.1-cp311-cp311-win_amd64.whl", hash = "sha256:5fa567e99765fe98f4e7d7394ce623e794d7cabb170f2ca2ac5a4174437e90dd"}, - {file = "coverage-7.5.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b6cf3764c030e5338e7f61f95bd21147963cf6aa16e09d2f74f1fa52013c1206"}, - {file = "coverage-7.5.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2ec92012fefebee89a6b9c79bc39051a6cb3891d562b9270ab10ecfdadbc0c34"}, - {file = "coverage-7.5.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:16db7f26000a07efcf6aea00316f6ac57e7d9a96501e990a36f40c965ec7a95d"}, - {file = "coverage-7.5.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:beccf7b8a10b09c4ae543582c1319c6df47d78fd732f854ac68d518ee1fb97fa"}, - {file = "coverage-7.5.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8748731ad392d736cc9ccac03c9845b13bb07d020a33423fa5b3a36521ac6e4e"}, - {file = "coverage-7.5.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7352b9161b33fd0b643ccd1f21f3a3908daaddf414f1c6cb9d3a2fd618bf2572"}, - {file = "coverage-7.5.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:7a588d39e0925f6a2bff87154752481273cdb1736270642aeb3635cb9b4cad07"}, - {file = "coverage-7.5.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:68f962d9b72ce69ea8621f57551b2fa9c70509af757ee3b8105d4f51b92b41a7"}, - {file = "coverage-7.5.1-cp312-cp312-win32.whl", hash = "sha256:f152cbf5b88aaeb836127d920dd0f5e7edff5a66f10c079157306c4343d86c19"}, - {file = "coverage-7.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:5a5740d1fb60ddf268a3811bcd353de34eb56dc24e8f52a7f05ee513b2d4f596"}, - {file = "coverage-7.5.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e2213def81a50519d7cc56ed643c9e93e0247f5bbe0d1247d15fa520814a7cd7"}, - {file = "coverage-7.5.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5037f8fcc2a95b1f0e80585bd9d1ec31068a9bcb157d9750a172836e98bc7a90"}, - {file = "coverage-7.5.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c3721c2c9e4c4953a41a26c14f4cef64330392a6d2d675c8b1db3b645e31f0e"}, - {file = "coverage-7.5.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca498687ca46a62ae590253fba634a1fe9836bc56f626852fb2720f334c9e4e5"}, - {file = "coverage-7.5.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0cdcbc320b14c3e5877ee79e649677cb7d89ef588852e9583e6b24c2e5072661"}, - {file = "coverage-7.5.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:57e0204b5b745594e5bc14b9b50006da722827f0b8c776949f1135677e88d0b8"}, - {file = "coverage-7.5.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8fe7502616b67b234482c3ce276ff26f39ffe88adca2acf0261df4b8454668b4"}, - {file = "coverage-7.5.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:9e78295f4144f9dacfed4f92935fbe1780021247c2fabf73a819b17f0ccfff8d"}, - {file = "coverage-7.5.1-cp38-cp38-win32.whl", hash = "sha256:1434e088b41594baa71188a17533083eabf5609e8e72f16ce8c186001e6b8c41"}, - {file = "coverage-7.5.1-cp38-cp38-win_amd64.whl", hash = "sha256:0646599e9b139988b63704d704af8e8df7fa4cbc4a1f33df69d97f36cb0a38de"}, - {file = "coverage-7.5.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4cc37def103a2725bc672f84bd939a6fe4522310503207aae4d56351644682f1"}, - {file = "coverage-7.5.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fc0b4d8bfeabd25ea75e94632f5b6e047eef8adaed0c2161ada1e922e7f7cece"}, - {file = "coverage-7.5.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d0a0f5e06881ecedfe6f3dd2f56dcb057b6dbeb3327fd32d4b12854df36bf26"}, - {file = "coverage-7.5.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9735317685ba6ec7e3754798c8871c2f49aa5e687cc794a0b1d284b2389d1bd5"}, - {file = "coverage-7.5.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d21918e9ef11edf36764b93101e2ae8cc82aa5efdc7c5a4e9c6c35a48496d601"}, - {file = "coverage-7.5.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c3e757949f268364b96ca894b4c342b41dc6f8f8b66c37878aacef5930db61be"}, - {file = "coverage-7.5.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:79afb6197e2f7f60c4824dd4b2d4c2ec5801ceb6ba9ce5d2c3080e5660d51a4f"}, - {file = "coverage-7.5.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d1d0d98d95dd18fe29dc66808e1accf59f037d5716f86a501fc0256455219668"}, - {file = "coverage-7.5.1-cp39-cp39-win32.whl", hash = "sha256:1cc0fe9b0b3a8364093c53b0b4c0c2dd4bb23acbec4c9240b5f284095ccf7981"}, - {file = "coverage-7.5.1-cp39-cp39-win_amd64.whl", hash = "sha256:dde0070c40ea8bb3641e811c1cfbf18e265d024deff6de52c5950677a8fb1e0f"}, - {file = "coverage-7.5.1-pp38.pp39.pp310-none-any.whl", hash = "sha256:6537e7c10cc47c595828b8a8be04c72144725c383c4702703ff4e42e44577312"}, - {file = "coverage-7.5.1.tar.gz", hash = "sha256:54de9ef3a9da981f7af93eafde4ede199e0846cd819eb27c88e2b712aae9708c"}, + {file = "coverage-7.5.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6cfb5a4f556bb51aba274588200a46e4dd6b505fb1a5f8c5ae408222eb416f99"}, + {file = "coverage-7.5.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2174e7c23e0a454ffe12267a10732c273243b4f2d50d07544a91198f05c48f47"}, + {file = "coverage-7.5.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2214ee920787d85db1b6a0bd9da5f8503ccc8fcd5814d90796c2f2493a2f4d2e"}, + {file = "coverage-7.5.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1137f46adb28e3813dec8c01fefadcb8c614f33576f672962e323b5128d9a68d"}, + {file = "coverage-7.5.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b385d49609f8e9efc885790a5a0e89f2e3ae042cdf12958b6034cc442de428d3"}, + {file = "coverage-7.5.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b4a474f799456e0eb46d78ab07303286a84a3140e9700b9e154cfebc8f527016"}, + {file = "coverage-7.5.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5cd64adedf3be66f8ccee418473c2916492d53cbafbfcff851cbec5a8454b136"}, + {file = "coverage-7.5.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e564c2cf45d2f44a9da56f4e3a26b2236504a496eb4cb0ca7221cd4cc7a9aca9"}, + {file = "coverage-7.5.4-cp310-cp310-win32.whl", hash = "sha256:7076b4b3a5f6d2b5d7f1185fde25b1e54eb66e647a1dfef0e2c2bfaf9b4c88c8"}, + {file = "coverage-7.5.4-cp310-cp310-win_amd64.whl", hash = "sha256:018a12985185038a5b2bcafab04ab833a9a0f2c59995b3cec07e10074c78635f"}, + {file = "coverage-7.5.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:db14f552ac38f10758ad14dd7b983dbab424e731588d300c7db25b6f89e335b5"}, + {file = "coverage-7.5.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3257fdd8e574805f27bb5342b77bc65578e98cbc004a92232106344053f319ba"}, + {file = "coverage-7.5.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a6612c99081d8d6134005b1354191e103ec9705d7ba2754e848211ac8cacc6b"}, + {file = "coverage-7.5.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d45d3cbd94159c468b9b8c5a556e3f6b81a8d1af2a92b77320e887c3e7a5d080"}, + {file = "coverage-7.5.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ed550e7442f278af76d9d65af48069f1fb84c9f745ae249c1a183c1e9d1b025c"}, + {file = "coverage-7.5.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7a892be37ca35eb5019ec85402c3371b0f7cda5ab5056023a7f13da0961e60da"}, + {file = "coverage-7.5.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8192794d120167e2a64721d88dbd688584675e86e15d0569599257566dec9bf0"}, + {file = "coverage-7.5.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:820bc841faa502e727a48311948e0461132a9c8baa42f6b2b84a29ced24cc078"}, + {file = "coverage-7.5.4-cp311-cp311-win32.whl", hash = "sha256:6aae5cce399a0f065da65c7bb1e8abd5c7a3043da9dceb429ebe1b289bc07806"}, + {file = "coverage-7.5.4-cp311-cp311-win_amd64.whl", hash = "sha256:d2e344d6adc8ef81c5a233d3a57b3c7d5181f40e79e05e1c143da143ccb6377d"}, + {file = "coverage-7.5.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:54317c2b806354cbb2dc7ac27e2b93f97096912cc16b18289c5d4e44fc663233"}, + {file = "coverage-7.5.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:042183de01f8b6d531e10c197f7f0315a61e8d805ab29c5f7b51a01d62782747"}, + {file = "coverage-7.5.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a6bb74ed465d5fb204b2ec41d79bcd28afccf817de721e8a807d5141c3426638"}, + {file = "coverage-7.5.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3d45ff86efb129c599a3b287ae2e44c1e281ae0f9a9bad0edc202179bcc3a2e"}, + {file = "coverage-7.5.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5013ed890dc917cef2c9f765c4c6a8ae9df983cd60dbb635df8ed9f4ebc9f555"}, + {file = "coverage-7.5.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1014fbf665fef86cdfd6cb5b7371496ce35e4d2a00cda501cf9f5b9e6fced69f"}, + {file = "coverage-7.5.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3684bc2ff328f935981847082ba4fdc950d58906a40eafa93510d1b54c08a66c"}, + {file = "coverage-7.5.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:581ea96f92bf71a5ec0974001f900db495488434a6928a2ca7f01eee20c23805"}, + {file = "coverage-7.5.4-cp312-cp312-win32.whl", hash = "sha256:73ca8fbc5bc622e54627314c1a6f1dfdd8db69788f3443e752c215f29fa87a0b"}, + {file = "coverage-7.5.4-cp312-cp312-win_amd64.whl", hash = "sha256:cef4649ec906ea7ea5e9e796e68b987f83fa9a718514fe147f538cfeda76d7a7"}, + {file = "coverage-7.5.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cdd31315fc20868c194130de9ee6bfd99755cc9565edff98ecc12585b90be882"}, + {file = "coverage-7.5.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:02ff6e898197cc1e9fa375581382b72498eb2e6d5fc0b53f03e496cfee3fac6d"}, + {file = "coverage-7.5.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d05c16cf4b4c2fc880cb12ba4c9b526e9e5d5bb1d81313d4d732a5b9fe2b9d53"}, + {file = "coverage-7.5.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c5986ee7ea0795a4095ac4d113cbb3448601efca7f158ec7f7087a6c705304e4"}, + {file = "coverage-7.5.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5df54843b88901fdc2f598ac06737f03d71168fd1175728054c8f5a2739ac3e4"}, + {file = "coverage-7.5.4-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:ab73b35e8d109bffbda9a3e91c64e29fe26e03e49addf5b43d85fc426dde11f9"}, + {file = "coverage-7.5.4-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:aea072a941b033813f5e4814541fc265a5c12ed9720daef11ca516aeacd3bd7f"}, + {file = "coverage-7.5.4-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:16852febd96acd953b0d55fc842ce2dac1710f26729b31c80b940b9afcd9896f"}, + {file = "coverage-7.5.4-cp38-cp38-win32.whl", hash = "sha256:8f894208794b164e6bd4bba61fc98bf6b06be4d390cf2daacfa6eca0a6d2bb4f"}, + {file = "coverage-7.5.4-cp38-cp38-win_amd64.whl", hash = "sha256:e2afe743289273209c992075a5a4913e8d007d569a406ffed0bd080ea02b0633"}, + {file = "coverage-7.5.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b95c3a8cb0463ba9f77383d0fa8c9194cf91f64445a63fc26fb2327e1e1eb088"}, + {file = "coverage-7.5.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3d7564cc09dd91b5a6001754a5b3c6ecc4aba6323baf33a12bd751036c998be4"}, + {file = "coverage-7.5.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:44da56a2589b684813f86d07597fdf8a9c6ce77f58976727329272f5a01f99f7"}, + {file = "coverage-7.5.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e16f3d6b491c48c5ae726308e6ab1e18ee830b4cdd6913f2d7f77354b33f91c8"}, + {file = "coverage-7.5.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dbc5958cb471e5a5af41b0ddaea96a37e74ed289535e8deca404811f6cb0bc3d"}, + {file = "coverage-7.5.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:a04e990a2a41740b02d6182b498ee9796cf60eefe40cf859b016650147908029"}, + {file = "coverage-7.5.4-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:ddbd2f9713a79e8e7242d7c51f1929611e991d855f414ca9996c20e44a895f7c"}, + {file = "coverage-7.5.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b1ccf5e728ccf83acd313c89f07c22d70d6c375a9c6f339233dcf792094bcbf7"}, + {file = "coverage-7.5.4-cp39-cp39-win32.whl", hash = "sha256:56b4eafa21c6c175b3ede004ca12c653a88b6f922494b023aeb1e836df953ace"}, + {file = "coverage-7.5.4-cp39-cp39-win_amd64.whl", hash = "sha256:65e528e2e921ba8fd67d9055e6b9f9e34b21ebd6768ae1c1723f4ea6ace1234d"}, + {file = "coverage-7.5.4-pp38.pp39.pp310-none-any.whl", hash = "sha256:79b356f3dd5b26f3ad23b35c75dbdaf1f9e2450b6bcefc6d0825ea0aa3f86ca5"}, + {file = "coverage-7.5.4.tar.gz", hash = "sha256:a44963520b069e12789d0faea4e9fdb1e410cdc4aab89d94f7f55cbb7fef0353"}, ] [package.dependencies] @@ -820,43 +879,43 @@ toml = ["tomli"] [[package]] name = "cryptography" -version = "42.0.7" +version = "42.0.8" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." -optional = true +optional = false python-versions = ">=3.7" files = [ - {file = "cryptography-42.0.7-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:a987f840718078212fdf4504d0fd4c6effe34a7e4740378e59d47696e8dfb477"}, - {file = "cryptography-42.0.7-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:bd13b5e9b543532453de08bcdc3cc7cebec6f9883e886fd20a92f26940fd3e7a"}, - {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a79165431551042cc9d1d90e6145d5d0d3ab0f2d66326c201d9b0e7f5bf43604"}, - {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a47787a5e3649008a1102d3df55424e86606c9bae6fb77ac59afe06d234605f8"}, - {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:02c0eee2d7133bdbbc5e24441258d5d2244beb31da5ed19fbb80315f4bbbff55"}, - {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:5e44507bf8d14b36b8389b226665d597bc0f18ea035d75b4e53c7b1ea84583cc"}, - {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:7f8b25fa616d8b846aef64b15c606bb0828dbc35faf90566eb139aa9cff67af2"}, - {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:93a3209f6bb2b33e725ed08ee0991b92976dfdcf4e8b38646540674fc7508e13"}, - {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:e6b8f1881dac458c34778d0a424ae5769de30544fc678eac51c1c8bb2183e9da"}, - {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3de9a45d3b2b7d8088c3fbf1ed4395dfeff79d07842217b38df14ef09ce1d8d7"}, - {file = "cryptography-42.0.7-cp37-abi3-win32.whl", hash = "sha256:789caea816c6704f63f6241a519bfa347f72fbd67ba28d04636b7c6b7da94b0b"}, - {file = "cryptography-42.0.7-cp37-abi3-win_amd64.whl", hash = "sha256:8cb8ce7c3347fcf9446f201dc30e2d5a3c898d009126010cbd1f443f28b52678"}, - {file = "cryptography-42.0.7-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:a3a5ac8b56fe37f3125e5b72b61dcde43283e5370827f5233893d461b7360cd4"}, - {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:779245e13b9a6638df14641d029add5dc17edbef6ec915688f3acb9e720a5858"}, - {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d563795db98b4cd57742a78a288cdbdc9daedac29f2239793071fe114f13785"}, - {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:31adb7d06fe4383226c3e963471f6837742889b3c4caa55aac20ad951bc8ffda"}, - {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:efd0bf5205240182e0f13bcaea41be4fdf5c22c5129fc7ced4a0282ac86998c9"}, - {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a9bc127cdc4ecf87a5ea22a2556cab6c7eda2923f84e4f3cc588e8470ce4e42e"}, - {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:3577d029bc3f4827dd5bf8bf7710cac13527b470bbf1820a3f394adb38ed7d5f"}, - {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2e47577f9b18723fa294b0ea9a17d5e53a227867a0a4904a1a076d1646d45ca1"}, - {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1a58839984d9cb34c855197043eaae2c187d930ca6d644612843b4fe8513c886"}, - {file = "cryptography-42.0.7-cp39-abi3-win32.whl", hash = "sha256:e6b79d0adb01aae87e8a44c2b64bc3f3fe59515280e00fb6d57a7267a2583cda"}, - {file = "cryptography-42.0.7-cp39-abi3-win_amd64.whl", hash = "sha256:16268d46086bb8ad5bf0a2b5544d8a9ed87a0e33f5e77dd3c3301e63d941a83b"}, - {file = "cryptography-42.0.7-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2954fccea107026512b15afb4aa664a5640cd0af630e2ee3962f2602693f0c82"}, - {file = "cryptography-42.0.7-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:362e7197754c231797ec45ee081f3088a27a47c6c01eff2ac83f60f85a50fe60"}, - {file = "cryptography-42.0.7-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4f698edacf9c9e0371112792558d2f705b5645076cc0aaae02f816a0171770fd"}, - {file = "cryptography-42.0.7-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5482e789294854c28237bba77c4c83be698be740e31a3ae5e879ee5444166582"}, - {file = "cryptography-42.0.7-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e9b2a6309f14c0497f348d08a065d52f3020656f675819fc405fb63bbcd26562"}, - {file = "cryptography-42.0.7-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d8e3098721b84392ee45af2dd554c947c32cc52f862b6a3ae982dbb90f577f14"}, - {file = "cryptography-42.0.7-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c65f96dad14f8528a447414125e1fc8feb2ad5a272b8f68477abbcc1ea7d94b9"}, - {file = "cryptography-42.0.7-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:36017400817987670037fbb0324d71489b6ead6231c9604f8fc1f7d008087c68"}, - {file = "cryptography-42.0.7.tar.gz", hash = "sha256:ecbfbc00bf55888edda9868a4cf927205de8499e7fabe6c050322298382953f2"}, + {file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:81d8a521705787afe7a18d5bfb47ea9d9cc068206270aad0b96a725022e18d2e"}, + {file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:961e61cefdcb06e0c6d7e3a1b22ebe8b996eb2bf50614e89384be54c48c6b63d"}, + {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3ec3672626e1b9e55afd0df6d774ff0e953452886e06e0f1eb7eb0c832e8902"}, + {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e599b53fd95357d92304510fb7bda8523ed1f79ca98dce2f43c115950aa78801"}, + {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:5226d5d21ab681f432a9c1cf8b658c0cb02533eece706b155e5fbd8a0cdd3949"}, + {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:6b7c4f03ce01afd3b76cf69a5455caa9cfa3de8c8f493e0d3ab7d20611c8dae9"}, + {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:2346b911eb349ab547076f47f2e035fc8ff2c02380a7cbbf8d87114fa0f1c583"}, + {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:ad803773e9df0b92e0a817d22fd8a3675493f690b96130a5e24f1b8fabbea9c7"}, + {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2f66d9cd9147ee495a8374a45ca445819f8929a3efcd2e3df6428e46c3cbb10b"}, + {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:d45b940883a03e19e944456a558b67a41160e367a719833c53de6911cabba2b7"}, + {file = "cryptography-42.0.8-cp37-abi3-win32.whl", hash = "sha256:a0c5b2b0585b6af82d7e385f55a8bc568abff8923af147ee3c07bd8b42cda8b2"}, + {file = "cryptography-42.0.8-cp37-abi3-win_amd64.whl", hash = "sha256:57080dee41209e556a9a4ce60d229244f7a66ef52750f813bfbe18959770cfba"}, + {file = "cryptography-42.0.8-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:dea567d1b0e8bc5764b9443858b673b734100c2871dc93163f58c46a97a83d28"}, + {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4783183f7cb757b73b2ae9aed6599b96338eb957233c58ca8f49a49cc32fd5e"}, + {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0608251135d0e03111152e41f0cc2392d1e74e35703960d4190b2e0f4ca9c70"}, + {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:dc0fdf6787f37b1c6b08e6dfc892d9d068b5bdb671198c72072828b80bd5fe4c"}, + {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:9c0c1716c8447ee7dbf08d6db2e5c41c688544c61074b54fc4564196f55c25a7"}, + {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:fff12c88a672ab9c9c1cf7b0c80e3ad9e2ebd9d828d955c126be4fd3e5578c9e"}, + {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:cafb92b2bc622cd1aa6a1dce4b93307792633f4c5fe1f46c6b97cf67073ec961"}, + {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:31f721658a29331f895a5a54e7e82075554ccfb8b163a18719d342f5ffe5ecb1"}, + {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b297f90c5723d04bcc8265fc2a0f86d4ea2e0f7ab4b6994459548d3a6b992a14"}, + {file = "cryptography-42.0.8-cp39-abi3-win32.whl", hash = "sha256:2f88d197e66c65be5e42cd72e5c18afbfae3f741742070e3019ac8f4ac57262c"}, + {file = "cryptography-42.0.8-cp39-abi3-win_amd64.whl", hash = "sha256:fa76fbb7596cc5839320000cdd5d0955313696d9511debab7ee7278fc8b5c84a"}, + {file = "cryptography-42.0.8-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ba4f0a211697362e89ad822e667d8d340b4d8d55fae72cdd619389fb5912eefe"}, + {file = "cryptography-42.0.8-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:81884c4d096c272f00aeb1f11cf62ccd39763581645b0812e99a91505fa48e0c"}, + {file = "cryptography-42.0.8-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c9bb2ae11bfbab395bdd072985abde58ea9860ed84e59dbc0463a5d0159f5b71"}, + {file = "cryptography-42.0.8-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7016f837e15b0a1c119d27ecd89b3515f01f90a8615ed5e9427e30d9cdbfed3d"}, + {file = "cryptography-42.0.8-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5a94eccb2a81a309806027e1670a358b99b8fe8bfe9f8d329f27d72c094dde8c"}, + {file = "cryptography-42.0.8-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:dec9b018df185f08483f294cae6ccac29e7a6e0678996587363dc352dc65c842"}, + {file = "cryptography-42.0.8-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:343728aac38decfdeecf55ecab3264b015be68fc2816ca800db649607aeee648"}, + {file = "cryptography-42.0.8-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:013629ae70b40af70c9a7a5db40abe5d9054e6f4380e50ce769947b73bf3caad"}, + {file = "cryptography-42.0.8.tar.gz", hash = "sha256:8d09d05439ce7baa8e9e95b07ec5b6c886f548deb7e0f69ef25f64b3bce842f2"}, ] [package.dependencies] @@ -885,13 +944,13 @@ files = [ [[package]] name = "dask" -version = "2024.5.1" +version = "2024.6.2" description = "Parallel PyData with Task Scheduling" optional = false python-versions = ">=3.9" files = [ - {file = "dask-2024.5.1-py3-none-any.whl", hash = "sha256:af1cadd1fd1d1d44600ff5de43dd029e5668fdf87422131f4e3e3aa2a6a63555"}, - {file = "dask-2024.5.1.tar.gz", hash = "sha256:e071fda67031c314569e37ca70b3e88bb30f1d91ff8ee4122b541845847cc264"}, + {file = "dask-2024.6.2-py3-none-any.whl", hash = "sha256:81b80ee015b2e057b93bb2d1bf13a866136e762e2b24bf54b6b621e8b86b7708"}, + {file = "dask-2024.6.2.tar.gz", hash = "sha256:d429d6b19e85fd1306ac37c188aaf99d03bbe69a6fe59d2b42882b2ac188686f"}, ] [package.dependencies] @@ -909,7 +968,7 @@ array = ["numpy (>=1.21)"] complete = ["dask[array,dataframe,diagnostics,distributed]", "lz4 (>=4.3.2)", "pyarrow (>=7.0)", "pyarrow-hotfix"] dataframe = ["dask-expr (>=1.1,<1.2)", "dask[array]", "pandas (>=1.3)"] diagnostics = ["bokeh (>=2.4.2)", "jinja2 (>=2.10.3)"] -distributed = ["distributed (==2024.5.1)"] +distributed = ["distributed (==2024.6.2)"] test = ["pandas[test]", "pre-commit", "pytest", "pytest-cov", "pytest-rerunfailures", "pytest-timeout", "pytest-xdist"] [[package]] @@ -953,19 +1012,19 @@ files = [ [[package]] name = "distributed" -version = "2024.5.1" +version = "2024.6.2" description = "Distributed scheduler for Dask" optional = true python-versions = ">=3.9" files = [ - {file = "distributed-2024.5.1-py3-none-any.whl", hash = "sha256:cf77583ce67f6696aa716c30f1cba3403ac866241c00d6e9a0bc1500c6818b40"}, - {file = "distributed-2024.5.1.tar.gz", hash = "sha256:c4e641e5fc014de3b43c584c70f703a7d44557b51b1143db812b8bc861aa84e2"}, + {file = "distributed-2024.6.2-py3-none-any.whl", hash = "sha256:0c1f8ccb1da71273ad8c53c598147dc37e60bef17142fd466cb72618a521880f"}, + {file = "distributed-2024.6.2.tar.gz", hash = "sha256:bb43b766ada860b163956607c80f99871d823c645e326c2b5e35f020351adc55"}, ] [package.dependencies] click = ">=8.0" cloudpickle = ">=1.5.0" -dask = "2024.5.1" +dask = "2024.6.2" jinja2 = ">=2.10.3" locket = ">=1.0.0" msgpack = ">=1.0.0" @@ -981,24 +1040,24 @@ zict = ">=3.0.0" [[package]] name = "docutils" -version = "0.20.1" +version = "0.21.2" description = "Docutils -- Python Documentation Utilities" optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" files = [ - {file = "docutils-0.20.1-py3-none-any.whl", hash = "sha256:96f387a2c5562db4476f09f13bbab2192e764cac08ebbf3a34a95d9b1e4a59d6"}, - {file = "docutils-0.20.1.tar.gz", hash = "sha256:f08a4e276c3a1583a86dce3e34aba3fe04d02bba2dd51ed16106244e8a923e3b"}, + {file = "docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2"}, + {file = "docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f"}, ] [[package]] name = "dparse" -version = "0.6.3" +version = "0.6.4b0" description = "A parser for Python dependency files" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "dparse-0.6.3-py3-none-any.whl", hash = "sha256:0d8fe18714056ca632d98b24fbfc4e9791d4e47065285ab486182288813a5318"}, - {file = "dparse-0.6.3.tar.gz", hash = "sha256:27bb8b4bcaefec3997697ba3f6e06b2447200ba273c0b085c3d012a04571b528"}, + {file = "dparse-0.6.4b0-py3-none-any.whl", hash = "sha256:592ff183348b8a5ea0a18442a7965e29445d3a26063654ec2c7e8ef42cd5753c"}, + {file = "dparse-0.6.4b0.tar.gz", hash = "sha256:f8d49b41a527f3d16a269f854e6665245b325e50e41d2c213810cb984553e5c8"}, ] [package.dependencies] @@ -1006,8 +1065,24 @@ packaging = "*" tomli = {version = "*", markers = "python_version < \"3.11\""} [package.extras] +all = ["dparse[conda]", "dparse[pipenv]", "dparse[poetry]"] conda = ["pyyaml"] -pipenv = ["pipenv (<=2022.12.19)"] +pipenv = ["pipenv"] +poetry = ["poetry"] + +[[package]] +name = "eval-type-backport" +version = "0.1.3" +description = "Like `typing._eval_type`, but lets older Python versions use newer typing features." +optional = false +python-versions = ">=3.7" +files = [ + {file = "eval_type_backport-0.1.3-py3-none-any.whl", hash = "sha256:519d2a993b3da286df9f90e17f503f66435106ad870cf26620c5720e2158ddf2"}, + {file = "eval_type_backport-0.1.3.tar.gz", hash = "sha256:d83ee225331dfa009493cec1f3608a71550b515ee4749abe78da14e3c5e314f5"}, +] + +[package.extras] +tests = ["pytest"] [[package]] name = "exceptiongroup" @@ -1036,34 +1111,34 @@ files = [ [[package]] name = "filelock" -version = "3.14.0" +version = "3.15.4" description = "A platform independent file lock." optional = false python-versions = ">=3.8" files = [ - {file = "filelock-3.14.0-py3-none-any.whl", hash = "sha256:43339835842f110ca7ae60f1e1c160714c5a6afd15a2873419ab185334975c0f"}, - {file = "filelock-3.14.0.tar.gz", hash = "sha256:6ea72da3be9b8c82afd3edcf99f2fffbb5076335a5ae4d03248bb5b6c3eae78a"}, + {file = "filelock-3.15.4-py3-none-any.whl", hash = "sha256:6ca1fffae96225dab4c6eaf1c4f4f28cd2568d3ec2a44e15a08520504de468e7"}, + {file = "filelock-3.15.4.tar.gz", hash = "sha256:2207938cbc1844345cb01a5a95524dae30f0ce089eba5b00378295a17e3e90cb"}, ] [package.extras] docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-asyncio (>=0.21)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)", "virtualenv (>=20.26.2)"] typing = ["typing-extensions (>=4.8)"] [[package]] name = "flake8" -version = "7.0.0" +version = "7.1.0" description = "the modular source code checker: pep8 pyflakes and co" optional = false python-versions = ">=3.8.1" files = [ - {file = "flake8-7.0.0-py2.py3-none-any.whl", hash = "sha256:a6dfbb75e03252917f2473ea9653f7cd799c3064e54d4c8140044c5c065f53c3"}, - {file = "flake8-7.0.0.tar.gz", hash = "sha256:33f96621059e65eec474169085dc92bf26e7b2d47366b70be2f67ab80dc25132"}, + {file = "flake8-7.1.0-py2.py3-none-any.whl", hash = "sha256:2e416edcc62471a64cea09353f4e7bdba32aeb079b6e360554c659a122b1bc6a"}, + {file = "flake8-7.1.0.tar.gz", hash = "sha256:48a07b626b55236e0fb4784ee69a465fbf59d79eec1f5b4785c3d3bc57d17aa5"}, ] [package.dependencies] mccabe = ">=0.7.0,<0.8.0" -pycodestyle = ">=2.11.0,<2.12.0" +pycodestyle = ">=2.12.0,<2.13.0" pyflakes = ">=3.2.0,<3.3.0" [[package]] @@ -1083,13 +1158,13 @@ flake8 = ">=5.0.0" [[package]] name = "flake8-bugbear" -version = "23.12.2" +version = "24.4.26" description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." optional = false python-versions = ">=3.8.1" files = [ - {file = "flake8-bugbear-23.12.2.tar.gz", hash = "sha256:32b2903e22331ae04885dae25756a32a8c666c85142e933f43512a70f342052a"}, - {file = "flake8_bugbear-23.12.2-py3-none-any.whl", hash = "sha256:83324bad4d90fee4bf64dd69c61aff94debf8073fbd807c8b6a36eec7a2f0719"}, + {file = "flake8_bugbear-24.4.26-py3-none-any.whl", hash = "sha256:cb430dd86bc821d79ccc0b030789a9c87a47a369667f12ba06e80f11305e8258"}, + {file = "flake8_bugbear-24.4.26.tar.gz", hash = "sha256:ff8d4ba5719019ebf98e754624c30c05cef0dadcf18a65d91c7567300e52a130"}, ] [package.dependencies] @@ -1221,13 +1296,13 @@ files = [ [[package]] name = "fsspec" -version = "2024.5.0" +version = "2024.6.0" description = "File-system specification" optional = false python-versions = ">=3.8" files = [ - {file = "fsspec-2024.5.0-py3-none-any.whl", hash = "sha256:e0fdbc446d67e182f49a70b82cf7889028a63588fde6b222521f10937b2b670c"}, - {file = "fsspec-2024.5.0.tar.gz", hash = "sha256:1d021b0b0f933e3b3029ed808eb400c08ba101ca2de4b3483fbc9ca23fcee94a"}, + {file = "fsspec-2024.6.0-py3-none-any.whl", hash = "sha256:58d7122eb8a1a46f7f13453187bfea4972d66bf01618d37366521b1998034cee"}, + {file = "fsspec-2024.6.0.tar.gz", hash = "sha256:f579960a56e6d8038a9efc8f9c77279ec12e6299aa86b0769a7e9c46b94527c2"}, ] [package.extras] @@ -1236,6 +1311,7 @@ adl = ["adlfs"] arrow = ["pyarrow (>=1)"] dask = ["dask", "distributed"] dev = ["pre-commit", "ruff"] +doc = ["numpydoc", "sphinx", "sphinx-design", "sphinx-rtd-theme", "yarl"] dropbox = ["dropbox", "dropboxdrivefs", "requests"] full = ["adlfs", "aiohttp (!=4.0.0a0,!=4.0.0a1)", "dask", "distributed", "dropbox", "dropboxdrivefs", "fusepy", "gcsfs", "libarchive-c", "ocifs", "panel", "paramiko", "pyarrow (>=1)", "pygit2", "requests", "s3fs", "smbprotocol", "tqdm"] fuse = ["fusepy"] @@ -1276,19 +1352,19 @@ sphinx-basic-ng = ">=1.0.0.beta2" [[package]] name = "gcsfs" -version = "2024.5.0" +version = "2024.6.0" description = "Convenient Filesystem interface over GCS" optional = true python-versions = ">=3.8" files = [ - {file = "gcsfs-2024.5.0-py2.py3-none-any.whl", hash = "sha256:49978e7eb68800c2d074bb07b39050f8ae990899855abcdae6ef478a94528451"}, - {file = "gcsfs-2024.5.0.tar.gz", hash = "sha256:e54eaaffb82aaa369aea9b985e5db19a8446a325f796481303abe71a4e3427d6"}, + {file = "gcsfs-2024.6.0-py2.py3-none-any.whl", hash = "sha256:92c9239167bd1e209b662b6f4ab71974f276118779c55360215cce5e0098ca7f"}, + {file = "gcsfs-2024.6.0.tar.gz", hash = "sha256:27bd490d7a9dd641d5f6f4ea0b18fabdcfa6129b84ebdb22b23e3460ded1aa8c"}, ] [package.dependencies] aiohttp = "<4.0.0a0 || >4.0.0a0,<4.0.0a1 || >4.0.0a1" decorator = ">4.1.2" -fsspec = "2024.5.0" +fsspec = "2024.6.0" google-auth = ">=1.2" google-auth-oauthlib = "*" google-cloud-storage = "*" @@ -1300,20 +1376,20 @@ gcsfuse = ["fusepy"] [[package]] name = "google-api-core" -version = "2.19.0" +version = "2.19.1" description = "Google API client core library" optional = true python-versions = ">=3.7" files = [ - {file = "google-api-core-2.19.0.tar.gz", hash = "sha256:cf1b7c2694047886d2af1128a03ae99e391108a08804f87cfd35970e49c9cd10"}, - {file = "google_api_core-2.19.0-py3-none-any.whl", hash = "sha256:8661eec4078c35428fd3f69a2c7ee29e342896b70f01d1a1cbcb334372dd6251"}, + {file = "google-api-core-2.19.1.tar.gz", hash = "sha256:f4695f1e3650b316a795108a76a1c416e6afb036199d1c1f1f110916df479ffd"}, + {file = "google_api_core-2.19.1-py3-none-any.whl", hash = "sha256:f12a9b8309b5e21d92483bbd47ce2c445861ec7d269ef6784ecc0ea8c1fa6125"}, ] [package.dependencies] google-auth = ">=2.14.1,<3.0.dev0" googleapis-common-protos = ">=1.56.2,<2.0.dev0" proto-plus = ">=1.22.3,<2.0.0dev" -protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0.dev0" +protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0.dev0" requests = ">=2.18.0,<3.0.0.dev0" [package.extras] @@ -1323,13 +1399,13 @@ grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] [[package]] name = "google-auth" -version = "2.29.0" +version = "2.30.0" description = "Google Authentication Library" optional = true python-versions = ">=3.7" files = [ - {file = "google-auth-2.29.0.tar.gz", hash = "sha256:672dff332d073227550ffc7457868ac4218d6c500b155fe6cc17d2b13602c360"}, - {file = "google_auth-2.29.0-py2.py3-none-any.whl", hash = "sha256:d452ad095688cd52bae0ad6fafe027f6a6d6f560e810fec20914e17a09526415"}, + {file = "google-auth-2.30.0.tar.gz", hash = "sha256:ab630a1320f6720909ad76a7dbdb6841cdf5c66b328d690027e4867bdfb16688"}, + {file = "google_auth-2.30.0-py2.py3-none-any.whl", hash = "sha256:8df7da660f62757388b8a7f249df13549b3373f24388cb5d2f1dd91cc18180b5"}, ] [package.dependencies] @@ -1382,13 +1458,13 @@ grpc = ["grpcio (>=1.38.0,<2.0dev)", "grpcio-status (>=1.38.0,<2.0.dev0)"] [[package]] name = "google-cloud-storage" -version = "2.16.0" +version = "2.17.0" description = "Google Cloud Storage API client library" optional = true python-versions = ">=3.7" files = [ - {file = "google-cloud-storage-2.16.0.tar.gz", hash = "sha256:dda485fa503710a828d01246bd16ce9db0823dc51bbca742ce96a6817d58669f"}, - {file = "google_cloud_storage-2.16.0-py2.py3-none-any.whl", hash = "sha256:91a06b96fb79cf9cdfb4e759f178ce11ea885c79938f89590344d079305f5852"}, + {file = "google-cloud-storage-2.17.0.tar.gz", hash = "sha256:49378abff54ef656b52dca5ef0f2eba9aa83dc2b2c72c78714b03a1a95fe9388"}, + {file = "google_cloud_storage-2.17.0-py2.py3-none-any.whl", hash = "sha256:5b393bc766b7a3bc6f5407b9e665b2450d36282614b7945e570b3480a456d1e1"}, ] [package.dependencies] @@ -1484,13 +1560,13 @@ testing = ["pytest"] [[package]] name = "google-resumable-media" -version = "2.7.0" +version = "2.7.1" description = "Utilities for Google Media Downloads and Resumable Uploads" optional = true -python-versions = ">= 3.7" +python-versions = ">=3.7" files = [ - {file = "google-resumable-media-2.7.0.tar.gz", hash = "sha256:5f18f5fa9836f4b083162064a1c2c98c17239bfda9ca50ad970ccf905f3e625b"}, - {file = "google_resumable_media-2.7.0-py2.py3-none-any.whl", hash = "sha256:79543cfe433b63fd81c0844b7803aba1bb8950b47bedf7d980c38fa123937e08"}, + {file = "google-resumable-media-2.7.1.tar.gz", hash = "sha256:eae451a7b2e2cdbaaa0fd2eb00cc8a1ee5e95e16b55597359cbc3d27d7d90e33"}, + {file = "google_resumable_media-2.7.1-py2.py3-none-any.whl", hash = "sha256:103ebc4ba331ab1bfdac0250f8033627a2cd7cde09e7ccff9181e31ba4315b2c"}, ] [package.dependencies] @@ -1502,21 +1578,32 @@ requests = ["requests (>=2.18.0,<3.0.0dev)"] [[package]] name = "googleapis-common-protos" -version = "1.63.0" +version = "1.63.2" description = "Common protobufs used in Google APIs" optional = true python-versions = ">=3.7" files = [ - {file = "googleapis-common-protos-1.63.0.tar.gz", hash = "sha256:17ad01b11d5f1d0171c06d3ba5c04c54474e883b66b949722b4938ee2694ef4e"}, - {file = "googleapis_common_protos-1.63.0-py2.py3-none-any.whl", hash = "sha256:ae45f75702f7c08b541f750854a678bd8f534a1a6bace6afe975f1d0a82d6632"}, + {file = "googleapis-common-protos-1.63.2.tar.gz", hash = "sha256:27c5abdffc4911f28101e635de1533fb4cfd2c37fbaa9174587c799fac90aa87"}, + {file = "googleapis_common_protos-1.63.2-py2.py3-none-any.whl", hash = "sha256:27a2499c7e8aff199665b22741997e485eccc8645aa9176c7c988e6fae507945"}, ] [package.dependencies] -protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0.dev0" +protobuf = ">=3.20.2,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0.dev0" [package.extras] grpc = ["grpcio (>=1.44.0,<2.0.0.dev0)"] +[[package]] +name = "h11" +version = "0.14.0" +description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +optional = false +python-versions = ">=3.7" +files = [ + {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, + {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, +] + [[package]] name = "identify" version = "2.5.36" @@ -1555,22 +1642,22 @@ files = [ [[package]] name = "importlib-metadata" -version = "7.1.0" +version = "7.2.1" description = "Read metadata from Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "importlib_metadata-7.1.0-py3-none-any.whl", hash = "sha256:30962b96c0c223483ed6cc7280e7f0199feb01a0e40cfae4d4450fc6fab1f570"}, - {file = "importlib_metadata-7.1.0.tar.gz", hash = "sha256:b78938b926ee8d5f020fc4772d487045805a55ddbad2ecf21c6d60938dc7fcd2"}, + {file = "importlib_metadata-7.2.1-py3-none-any.whl", hash = "sha256:ffef94b0b66046dd8ea2d619b701fe978d9264d38f3998bc4c27ec3b146a87c8"}, + {file = "importlib_metadata-7.2.1.tar.gz", hash = "sha256:509ecb2ab77071db5137c655e24ceb3eee66e7bbc6574165d0d114d9fc4bbe68"}, ] [package.dependencies] zipp = ">=0.5" [package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] perf = ["ipython"] -testing = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-perf (>=0.9.2)", "pytest-ruff (>=0.2.1)"] +test = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-perf (>=0.9.2)", "pytest-ruff (>=0.2.1)"] [[package]] name = "iniconfig" @@ -1639,49 +1726,34 @@ files = [ {file = "jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"}, ] -[[package]] -name = "livereload" -version = "2.6.3" -description = "Python LiveReload is an awesome tool for web developers" -optional = false -python-versions = "*" -files = [ - {file = "livereload-2.6.3-py2.py3-none-any.whl", hash = "sha256:ad4ac6f53b2d62bb6ce1a5e6e96f1f00976a32348afedcb4b6d68df2a1d346e4"}, - {file = "livereload-2.6.3.tar.gz", hash = "sha256:776f2f865e59fde56490a56bcc6773b6917366bce0c267c60ee8aaf1a0959869"}, -] - -[package.dependencies] -six = "*" -tornado = {version = "*", markers = "python_version > \"2.7\""} - [[package]] name = "llvmlite" -version = "0.42.0" +version = "0.43.0" description = "lightweight wrapper around basic LLVM functionality" optional = false python-versions = ">=3.9" files = [ - {file = "llvmlite-0.42.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3366938e1bf63d26c34fbfb4c8e8d2ded57d11e0567d5bb243d89aab1eb56098"}, - {file = "llvmlite-0.42.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c35da49666a21185d21b551fc3caf46a935d54d66969d32d72af109b5e7d2b6f"}, - {file = "llvmlite-0.42.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70f44ccc3c6220bd23e0ba698a63ec2a7d3205da0d848804807f37fc243e3f77"}, - {file = "llvmlite-0.42.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:763f8d8717a9073b9e0246998de89929071d15b47f254c10eef2310b9aac033d"}, - {file = "llvmlite-0.42.0-cp310-cp310-win_amd64.whl", hash = "sha256:8d90edf400b4ceb3a0e776b6c6e4656d05c7187c439587e06f86afceb66d2be5"}, - {file = "llvmlite-0.42.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ae511caed28beaf1252dbaf5f40e663f533b79ceb408c874c01754cafabb9cbf"}, - {file = "llvmlite-0.42.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81e674c2fe85576e6c4474e8c7e7aba7901ac0196e864fe7985492b737dbab65"}, - {file = "llvmlite-0.42.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb3975787f13eb97629052edb5017f6c170eebc1c14a0433e8089e5db43bcce6"}, - {file = "llvmlite-0.42.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c5bece0cdf77f22379f19b1959ccd7aee518afa4afbd3656c6365865f84903f9"}, - {file = "llvmlite-0.42.0-cp311-cp311-win_amd64.whl", hash = "sha256:7e0c4c11c8c2aa9b0701f91b799cb9134a6a6de51444eff5a9087fc7c1384275"}, - {file = "llvmlite-0.42.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:08fa9ab02b0d0179c688a4216b8939138266519aaa0aa94f1195a8542faedb56"}, - {file = "llvmlite-0.42.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b2fce7d355068494d1e42202c7aff25d50c462584233013eb4470c33b995e3ee"}, - {file = "llvmlite-0.42.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebe66a86dc44634b59a3bc860c7b20d26d9aaffcd30364ebe8ba79161a9121f4"}, - {file = "llvmlite-0.42.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d47494552559e00d81bfb836cf1c4d5a5062e54102cc5767d5aa1e77ccd2505c"}, - {file = "llvmlite-0.42.0-cp312-cp312-win_amd64.whl", hash = "sha256:05cb7e9b6ce69165ce4d1b994fbdedca0c62492e537b0cc86141b6e2c78d5888"}, - {file = "llvmlite-0.42.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bdd3888544538a94d7ec99e7c62a0cdd8833609c85f0c23fcb6c5c591aec60ad"}, - {file = "llvmlite-0.42.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d0936c2067a67fb8816c908d5457d63eba3e2b17e515c5fe00e5ee2bace06040"}, - {file = "llvmlite-0.42.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a78ab89f1924fc11482209f6799a7a3fc74ddc80425a7a3e0e8174af0e9e2301"}, - {file = "llvmlite-0.42.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7599b65c7af7abbc978dbf345712c60fd596aa5670496561cc10e8a71cebfb2"}, - {file = "llvmlite-0.42.0-cp39-cp39-win_amd64.whl", hash = "sha256:43d65cc4e206c2e902c1004dd5418417c4efa6c1d04df05c6c5675a27e8ca90e"}, - {file = "llvmlite-0.42.0.tar.gz", hash = "sha256:f92b09243c0cc3f457da8b983f67bd8e1295d0f5b3746c7a1861d7a99403854a"}, + {file = "llvmlite-0.43.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a289af9a1687c6cf463478f0fa8e8aa3b6fb813317b0d70bf1ed0759eab6f761"}, + {file = "llvmlite-0.43.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6d4fd101f571a31acb1559ae1af30f30b1dc4b3186669f92ad780e17c81e91bc"}, + {file = "llvmlite-0.43.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7d434ec7e2ce3cc8f452d1cd9a28591745de022f931d67be688a737320dfcead"}, + {file = "llvmlite-0.43.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6912a87782acdff6eb8bf01675ed01d60ca1f2551f8176a300a886f09e836a6a"}, + {file = "llvmlite-0.43.0-cp310-cp310-win_amd64.whl", hash = "sha256:14f0e4bf2fd2d9a75a3534111e8ebeb08eda2f33e9bdd6dfa13282afacdde0ed"}, + {file = "llvmlite-0.43.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3e8d0618cb9bfe40ac38a9633f2493d4d4e9fcc2f438d39a4e854f39cc0f5f98"}, + {file = "llvmlite-0.43.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e0a9a1a39d4bf3517f2af9d23d479b4175ead205c592ceeb8b89af48a327ea57"}, + {file = "llvmlite-0.43.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1da416ab53e4f7f3bc8d4eeba36d801cc1894b9fbfbf2022b29b6bad34a7df2"}, + {file = "llvmlite-0.43.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:977525a1e5f4059316b183fb4fd34fa858c9eade31f165427a3977c95e3ee749"}, + {file = "llvmlite-0.43.0-cp311-cp311-win_amd64.whl", hash = "sha256:d5bd550001d26450bd90777736c69d68c487d17bf371438f975229b2b8241a91"}, + {file = "llvmlite-0.43.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f99b600aa7f65235a5a05d0b9a9f31150c390f31261f2a0ba678e26823ec38f7"}, + {file = "llvmlite-0.43.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:35d80d61d0cda2d767f72de99450766250560399edc309da16937b93d3b676e7"}, + {file = "llvmlite-0.43.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eccce86bba940bae0d8d48ed925f21dbb813519169246e2ab292b5092aba121f"}, + {file = "llvmlite-0.43.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df6509e1507ca0760787a199d19439cc887bfd82226f5af746d6977bd9f66844"}, + {file = "llvmlite-0.43.0-cp312-cp312-win_amd64.whl", hash = "sha256:7a2872ee80dcf6b5dbdc838763d26554c2a18aa833d31a2635bff16aafefb9c9"}, + {file = "llvmlite-0.43.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9cd2a7376f7b3367019b664c21f0c61766219faa3b03731113ead75107f3b66c"}, + {file = "llvmlite-0.43.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:18e9953c748b105668487b7c81a3e97b046d8abf95c4ddc0cd3c94f4e4651ae8"}, + {file = "llvmlite-0.43.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74937acd22dc11b33946b67dca7680e6d103d6e90eeaaaf932603bec6fe7b03a"}, + {file = "llvmlite-0.43.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc9efc739cc6ed760f795806f67889923f7274276f0eb45092a1473e40d9b867"}, + {file = "llvmlite-0.43.0-cp39-cp39-win_amd64.whl", hash = "sha256:47e147cdda9037f94b399bf03bfd8a6b6b1f2f90be94a454e3386f006455a9b4"}, + {file = "llvmlite-0.43.0.tar.gz", hash = "sha256:ae2b5b5c3ef67354824fb75517c8db5fbe93bc02cd9671f3c62271626bc041d5"}, ] [[package]] @@ -1790,13 +1862,13 @@ files = [ [[package]] name = "marshmallow" -version = "3.21.2" +version = "3.21.3" description = "A lightweight library for converting complex datatypes to and from native Python datatypes." optional = false python-versions = ">=3.8" files = [ - {file = "marshmallow-3.21.2-py3-none-any.whl", hash = "sha256:70b54a6282f4704d12c0a41599682c5c5450e843b9ec406308653b47c59648a1"}, - {file = "marshmallow-3.21.2.tar.gz", hash = "sha256:82408deadd8b33d56338d2182d455db632c6313aa2af61916672146bb32edc56"}, + {file = "marshmallow-3.21.3-py3-none-any.whl", hash = "sha256:86ce7fb914aa865001a4b2092c4c2872d13bc347f3d42673272cabfdbad386f1"}, + {file = "marshmallow-3.21.3.tar.gz", hash = "sha256:4f57c5e050a54d66361e826f94fba213eb10b67b2fdb02c3e0343ce207ba1662"}, ] [package.dependencies] @@ -1850,41 +1922,37 @@ files = [ [[package]] name = "msal" -version = "1.28.0" +version = "1.29.0" description = "The Microsoft Authentication Library (MSAL) for Python library enables your app to access the Microsoft Cloud by supporting authentication of users with Microsoft Azure Active Directory accounts (AAD) and Microsoft Accounts (MSA) using industry standard OAuth2 and OpenID Connect." optional = true python-versions = ">=3.7" files = [ - {file = "msal-1.28.0-py3-none-any.whl", hash = "sha256:3064f80221a21cd535ad8c3fafbb3a3582cd9c7e9af0bb789ae14f726a0ca99b"}, - {file = "msal-1.28.0.tar.gz", hash = "sha256:80bbabe34567cb734efd2ec1869b2d98195c927455369d8077b3c542088c5c9d"}, + {file = "msal-1.29.0-py3-none-any.whl", hash = "sha256:6b301e63f967481f0cc1a3a3bac0cf322b276855bc1b0955468d9deb3f33d511"}, + {file = "msal-1.29.0.tar.gz", hash = "sha256:8f6725f099752553f9b2fe84125e2a5ebe47b49f92eacca33ebedd3a9ebaae25"}, ] [package.dependencies] -cryptography = ">=0.6,<45" +cryptography = ">=2.5,<45" PyJWT = {version = ">=1.0.0,<3", extras = ["crypto"]} requests = ">=2.0.0,<3" [package.extras] -broker = ["pymsalruntime (>=0.13.2,<0.15)"] +broker = ["pymsalruntime (>=0.13.2,<0.17)"] [[package]] name = "msal-extensions" -version = "1.1.0" +version = "1.2.0" description = "Microsoft Authentication Library extensions (MSAL EX) provides a persistence API that can save your data on disk, encrypted on Windows, macOS and Linux. Concurrent data access will be coordinated by a file lock mechanism." optional = true python-versions = ">=3.7" files = [ - {file = "msal-extensions-1.1.0.tar.gz", hash = "sha256:6ab357867062db7b253d0bd2df6d411c7891a0ee7308d54d1e4317c1d1c54252"}, - {file = "msal_extensions-1.1.0-py3-none-any.whl", hash = "sha256:01be9711b4c0b1a151450068eeb2c4f0997df3bba085ac299de3a66f585e382f"}, + {file = "msal_extensions-1.2.0-py3-none-any.whl", hash = "sha256:cf5ba83a2113fa6dc011a254a72f1c223c88d7dfad74cc30617c4679a417704d"}, + {file = "msal_extensions-1.2.0.tar.gz", hash = "sha256:6f41b320bfd2933d631a215c91ca0dd3e67d84bd1a2f50ce917d5874ec646bef"}, ] [package.dependencies] -msal = ">=0.4.1,<2.0.0" -packaging = "*" -portalocker = [ - {version = ">=1.0,<3", markers = "platform_system != \"Windows\""}, - {version = ">=1.6,<3", markers = "platform_system == \"Windows\""}, -] +msal = ">=1.29,<2" +portalocker = ">=1.4,<3" [[package]] name = "msgpack" @@ -2053,38 +2121,38 @@ files = [ [[package]] name = "mypy" -version = "1.10.0" +version = "1.10.1" description = "Optional static typing for Python" optional = false python-versions = ">=3.8" files = [ - {file = "mypy-1.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:da1cbf08fb3b851ab3b9523a884c232774008267b1f83371ace57f412fe308c2"}, - {file = "mypy-1.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:12b6bfc1b1a66095ab413160a6e520e1dc076a28f3e22f7fb25ba3b000b4ef99"}, - {file = "mypy-1.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e36fb078cce9904c7989b9693e41cb9711e0600139ce3970c6ef814b6ebc2b2"}, - {file = "mypy-1.10.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2b0695d605ddcd3eb2f736cd8b4e388288c21e7de85001e9f85df9187f2b50f9"}, - {file = "mypy-1.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:cd777b780312ddb135bceb9bc8722a73ec95e042f911cc279e2ec3c667076051"}, - {file = "mypy-1.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3be66771aa5c97602f382230165b856c231d1277c511c9a8dd058be4784472e1"}, - {file = "mypy-1.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8b2cbaca148d0754a54d44121b5825ae71868c7592a53b7292eeb0f3fdae95ee"}, - {file = "mypy-1.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ec404a7cbe9fc0e92cb0e67f55ce0c025014e26d33e54d9e506a0f2d07fe5de"}, - {file = "mypy-1.10.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e22e1527dc3d4aa94311d246b59e47f6455b8729f4968765ac1eacf9a4760bc7"}, - {file = "mypy-1.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:a87dbfa85971e8d59c9cc1fcf534efe664d8949e4c0b6b44e8ca548e746a8d53"}, - {file = "mypy-1.10.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a781f6ad4bab20eef8b65174a57e5203f4be627b46291f4589879bf4e257b97b"}, - {file = "mypy-1.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b808e12113505b97d9023b0b5e0c0705a90571c6feefc6f215c1df9381256e30"}, - {file = "mypy-1.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f55583b12156c399dce2df7d16f8a5095291354f1e839c252ec6c0611e86e2e"}, - {file = "mypy-1.10.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4cf18f9d0efa1b16478c4c129eabec36148032575391095f73cae2e722fcf9d5"}, - {file = "mypy-1.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:bc6ac273b23c6b82da3bb25f4136c4fd42665f17f2cd850771cb600bdd2ebeda"}, - {file = "mypy-1.10.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9fd50226364cd2737351c79807775136b0abe084433b55b2e29181a4c3c878c0"}, - {file = "mypy-1.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f90cff89eea89273727d8783fef5d4a934be2fdca11b47def50cf5d311aff727"}, - {file = "mypy-1.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fcfc70599efde5c67862a07a1aaf50e55bce629ace26bb19dc17cece5dd31ca4"}, - {file = "mypy-1.10.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:075cbf81f3e134eadaf247de187bd604748171d6b79736fa9b6c9685b4083061"}, - {file = "mypy-1.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:3f298531bca95ff615b6e9f2fc0333aae27fa48052903a0ac90215021cdcfa4f"}, - {file = "mypy-1.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fa7ef5244615a2523b56c034becde4e9e3f9b034854c93639adb667ec9ec2976"}, - {file = "mypy-1.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3236a4c8f535a0631f85f5fcdffba71c7feeef76a6002fcba7c1a8e57c8be1ec"}, - {file = "mypy-1.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a2b5cdbb5dd35aa08ea9114436e0d79aceb2f38e32c21684dcf8e24e1e92821"}, - {file = "mypy-1.10.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:92f93b21c0fe73dc00abf91022234c79d793318b8a96faac147cd579c1671746"}, - {file = "mypy-1.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:28d0e038361b45f099cc086d9dd99c15ff14d0188f44ac883010e172ce86c38a"}, - {file = "mypy-1.10.0-py3-none-any.whl", hash = "sha256:f8c083976eb530019175aabadb60921e73b4f45736760826aa1689dda8208aee"}, - {file = "mypy-1.10.0.tar.gz", hash = "sha256:3d087fcbec056c4ee34974da493a826ce316947485cef3901f511848e687c131"}, + {file = "mypy-1.10.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e36f229acfe250dc660790840916eb49726c928e8ce10fbdf90715090fe4ae02"}, + {file = "mypy-1.10.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:51a46974340baaa4145363b9e051812a2446cf583dfaeba124af966fa44593f7"}, + {file = "mypy-1.10.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:901c89c2d67bba57aaaca91ccdb659aa3a312de67f23b9dfb059727cce2e2e0a"}, + {file = "mypy-1.10.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0cd62192a4a32b77ceb31272d9e74d23cd88c8060c34d1d3622db3267679a5d9"}, + {file = "mypy-1.10.1-cp310-cp310-win_amd64.whl", hash = "sha256:a2cbc68cb9e943ac0814c13e2452d2046c2f2b23ff0278e26599224cf164e78d"}, + {file = "mypy-1.10.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:bd6f629b67bb43dc0d9211ee98b96d8dabc97b1ad38b9b25f5e4c4d7569a0c6a"}, + {file = "mypy-1.10.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a1bbb3a6f5ff319d2b9d40b4080d46cd639abe3516d5a62c070cf0114a457d84"}, + {file = "mypy-1.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8edd4e9bbbc9d7b79502eb9592cab808585516ae1bcc1446eb9122656c6066f"}, + {file = "mypy-1.10.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6166a88b15f1759f94a46fa474c7b1b05d134b1b61fca627dd7335454cc9aa6b"}, + {file = "mypy-1.10.1-cp311-cp311-win_amd64.whl", hash = "sha256:5bb9cd11c01c8606a9d0b83ffa91d0b236a0e91bc4126d9ba9ce62906ada868e"}, + {file = "mypy-1.10.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d8681909f7b44d0b7b86e653ca152d6dff0eb5eb41694e163c6092124f8246d7"}, + {file = "mypy-1.10.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:378c03f53f10bbdd55ca94e46ec3ba255279706a6aacaecac52ad248f98205d3"}, + {file = "mypy-1.10.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bacf8f3a3d7d849f40ca6caea5c055122efe70e81480c8328ad29c55c69e93e"}, + {file = "mypy-1.10.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:701b5f71413f1e9855566a34d6e9d12624e9e0a8818a5704d74d6b0402e66c04"}, + {file = "mypy-1.10.1-cp312-cp312-win_amd64.whl", hash = "sha256:3c4c2992f6ea46ff7fce0072642cfb62af7a2484efe69017ed8b095f7b39ef31"}, + {file = "mypy-1.10.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:604282c886497645ffb87b8f35a57ec773a4a2721161e709a4422c1636ddde5c"}, + {file = "mypy-1.10.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37fd87cab83f09842653f08de066ee68f1182b9b5282e4634cdb4b407266bade"}, + {file = "mypy-1.10.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8addf6313777dbb92e9564c5d32ec122bf2c6c39d683ea64de6a1fd98b90fe37"}, + {file = "mypy-1.10.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5cc3ca0a244eb9a5249c7c583ad9a7e881aa5d7b73c35652296ddcdb33b2b9c7"}, + {file = "mypy-1.10.1-cp38-cp38-win_amd64.whl", hash = "sha256:1b3a2ffce52cc4dbaeee4df762f20a2905aa171ef157b82192f2e2f368eec05d"}, + {file = "mypy-1.10.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fe85ed6836165d52ae8b88f99527d3d1b2362e0cb90b005409b8bed90e9059b3"}, + {file = "mypy-1.10.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c2ae450d60d7d020d67ab440c6e3fae375809988119817214440033f26ddf7bf"}, + {file = "mypy-1.10.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6be84c06e6abd72f960ba9a71561c14137a583093ffcf9bbfaf5e613d63fa531"}, + {file = "mypy-1.10.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2189ff1e39db399f08205e22a797383613ce1cb0cb3b13d8bcf0170e45b96cc3"}, + {file = "mypy-1.10.1-cp39-cp39-win_amd64.whl", hash = "sha256:97a131ee36ac37ce9581f4220311247ab6cba896b4395b9c87af0675a13a755f"}, + {file = "mypy-1.10.1-py3-none-any.whl", hash = "sha256:71d8ac0b906354ebda8ef1673e5fde785936ac1f29ff6987c7483cfbd5a4235a"}, + {file = "mypy-1.10.1.tar.gz", hash = "sha256:1f8f492d7db9e3593ef42d4f115f04e556130f2819ad33ab84551403e97dd4c0"}, ] [package.dependencies] @@ -2111,17 +2179,17 @@ files = [ [[package]] name = "myst-parser" -version = "2.0.0" +version = "3.0.1" description = "An extended [CommonMark](https://spec.commonmark.org/) compliant parser," optional = false python-versions = ">=3.8" files = [ - {file = "myst_parser-2.0.0-py3-none-any.whl", hash = "sha256:7c36344ae39c8e740dad7fdabf5aa6fc4897a813083c6cc9990044eb93656b14"}, - {file = "myst_parser-2.0.0.tar.gz", hash = "sha256:ea929a67a6a0b1683cdbe19b8d2e724cd7643f8aa3e7bb18dd65beac3483bead"}, + {file = "myst_parser-3.0.1-py3-none-any.whl", hash = "sha256:6457aaa33a5d474aca678b8ead9b3dc298e89c68e67012e73146ea6fd54babf1"}, + {file = "myst_parser-3.0.1.tar.gz", hash = "sha256:88f0cb406cb363b077d176b51c476f62d60604d68a8dcdf4832e080441301a87"}, ] [package.dependencies] -docutils = ">=0.16,<0.21" +docutils = ">=0.18,<0.22" jinja2 = "*" markdown-it-py = ">=3.0,<4.0" mdit-py-plugins = ">=0.4,<1.0" @@ -2131,57 +2199,54 @@ sphinx = ">=6,<8" [package.extras] code-style = ["pre-commit (>=3.0,<4.0)"] linkify = ["linkify-it-py (>=2.0,<3.0)"] -rtd = ["ipython", "pydata-sphinx-theme (==v0.13.0rc4)", "sphinx-autodoc2 (>=0.4.2,<0.5.0)", "sphinx-book-theme (==1.0.0rc2)", "sphinx-copybutton", "sphinx-design2", "sphinx-pyscript", "sphinx-tippy (>=0.3.1)", "sphinx-togglebutton", "sphinxext-opengraph (>=0.8.2,<0.9.0)", "sphinxext-rediraffe (>=0.2.7,<0.3.0)"] -testing = ["beautifulsoup4", "coverage[toml]", "pytest (>=7,<8)", "pytest-cov", "pytest-param-files (>=0.3.4,<0.4.0)", "pytest-regressions", "sphinx-pytest"] -testing-docutils = ["pygments", "pytest (>=7,<8)", "pytest-param-files (>=0.3.4,<0.4.0)"] +rtd = ["ipython", "sphinx (>=7)", "sphinx-autodoc2 (>=0.5.0,<0.6.0)", "sphinx-book-theme (>=1.1,<2.0)", "sphinx-copybutton", "sphinx-design", "sphinx-pyscript", "sphinx-tippy (>=0.4.3)", "sphinx-togglebutton", "sphinxext-opengraph (>=0.9.0,<0.10.0)", "sphinxext-rediraffe (>=0.2.7,<0.3.0)"] +testing = ["beautifulsoup4", "coverage[toml]", "defusedxml", "pytest (>=8,<9)", "pytest-cov", "pytest-param-files (>=0.6.0,<0.7.0)", "pytest-regressions", "sphinx-pytest"] +testing-docutils = ["pygments", "pytest (>=8,<9)", "pytest-param-files (>=0.6.0,<0.7.0)"] [[package]] name = "nodeenv" -version = "1.8.0" +version = "1.9.1" description = "Node.js virtual environment builder" optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ - {file = "nodeenv-1.8.0-py2.py3-none-any.whl", hash = "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec"}, - {file = "nodeenv-1.8.0.tar.gz", hash = "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2"}, + {file = "nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9"}, + {file = "nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f"}, ] -[package.dependencies] -setuptools = "*" - [[package]] name = "numba" -version = "0.59.1" +version = "0.60.0" description = "compiling Python code using LLVM" optional = false python-versions = ">=3.9" files = [ - {file = "numba-0.59.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:97385a7f12212c4f4bc28f648720a92514bee79d7063e40ef66c2d30600fd18e"}, - {file = "numba-0.59.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0b77aecf52040de2a1eb1d7e314497b9e56fba17466c80b457b971a25bb1576d"}, - {file = "numba-0.59.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3476a4f641bfd58f35ead42f4dcaf5f132569c4647c6f1360ccf18ee4cda3990"}, - {file = "numba-0.59.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:525ef3f820931bdae95ee5379c670d5c97289c6520726bc6937a4a7d4230ba24"}, - {file = "numba-0.59.1-cp310-cp310-win_amd64.whl", hash = "sha256:990e395e44d192a12105eca3083b61307db7da10e093972ca285c85bef0963d6"}, - {file = "numba-0.59.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:43727e7ad20b3ec23ee4fc642f5b61845c71f75dd2825b3c234390c6d8d64051"}, - {file = "numba-0.59.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:411df625372c77959570050e861981e9d196cc1da9aa62c3d6a836b5cc338966"}, - {file = "numba-0.59.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2801003caa263d1e8497fb84829a7ecfb61738a95f62bc05693fcf1733e978e4"}, - {file = "numba-0.59.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:dd2842fac03be4e5324ebbbd4d2d0c8c0fc6e0df75c09477dd45b288a0777389"}, - {file = "numba-0.59.1-cp311-cp311-win_amd64.whl", hash = "sha256:0594b3dfb369fada1f8bb2e3045cd6c61a564c62e50cf1f86b4666bc721b3450"}, - {file = "numba-0.59.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:1cce206a3b92836cdf26ef39d3a3242fec25e07f020cc4feec4c4a865e340569"}, - {file = "numba-0.59.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8c8b4477763cb1fbd86a3be7050500229417bf60867c93e131fd2626edb02238"}, - {file = "numba-0.59.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7d80bce4ef7e65bf895c29e3889ca75a29ee01da80266a01d34815918e365835"}, - {file = "numba-0.59.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f7ad1d217773e89a9845886401eaaab0a156a90aa2f179fdc125261fd1105096"}, - {file = "numba-0.59.1-cp312-cp312-win_amd64.whl", hash = "sha256:5bf68f4d69dd3a9f26a9b23548fa23e3bcb9042e2935257b471d2a8d3c424b7f"}, - {file = "numba-0.59.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4e0318ae729de6e5dbe64c75ead1a95eb01fabfe0e2ebed81ebf0344d32db0ae"}, - {file = "numba-0.59.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0f68589740a8c38bb7dc1b938b55d1145244c8353078eea23895d4f82c8b9ec1"}, - {file = "numba-0.59.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:649913a3758891c77c32e2d2a3bcbedf4a69f5fea276d11f9119677c45a422e8"}, - {file = "numba-0.59.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:9712808e4545270291d76b9a264839ac878c5eb7d8b6e02c970dc0ac29bc8187"}, - {file = "numba-0.59.1-cp39-cp39-win_amd64.whl", hash = "sha256:8d51ccd7008a83105ad6a0082b6a2b70f1142dc7cfd76deb8c5a862367eb8c86"}, - {file = "numba-0.59.1.tar.gz", hash = "sha256:76f69132b96028d2774ed20415e8c528a34e3299a40581bae178f0994a2f370b"}, -] - -[package.dependencies] -llvmlite = "==0.42.*" -numpy = ">=1.22,<1.27" + {file = "numba-0.60.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5d761de835cd38fb400d2c26bb103a2726f548dc30368853121d66201672e651"}, + {file = "numba-0.60.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:159e618ef213fba758837f9837fb402bbe65326e60ba0633dbe6c7f274d42c1b"}, + {file = "numba-0.60.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1527dc578b95c7c4ff248792ec33d097ba6bef9eda466c948b68dfc995c25781"}, + {file = "numba-0.60.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fe0b28abb8d70f8160798f4de9d486143200f34458d34c4a214114e445d7124e"}, + {file = "numba-0.60.0-cp310-cp310-win_amd64.whl", hash = "sha256:19407ced081d7e2e4b8d8c36aa57b7452e0283871c296e12d798852bc7d7f198"}, + {file = "numba-0.60.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a17b70fc9e380ee29c42717e8cc0bfaa5556c416d94f9aa96ba13acb41bdece8"}, + {file = "numba-0.60.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3fb02b344a2a80efa6f677aa5c40cd5dd452e1b35f8d1c2af0dfd9ada9978e4b"}, + {file = "numba-0.60.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5f4fde652ea604ea3c86508a3fb31556a6157b2c76c8b51b1d45eb40c8598703"}, + {file = "numba-0.60.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4142d7ac0210cc86432b818338a2bc368dc773a2f5cf1e32ff7c5b378bd63ee8"}, + {file = "numba-0.60.0-cp311-cp311-win_amd64.whl", hash = "sha256:cac02c041e9b5bc8cf8f2034ff6f0dbafccd1ae9590dc146b3a02a45e53af4e2"}, + {file = "numba-0.60.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d7da4098db31182fc5ffe4bc42c6f24cd7d1cb8a14b59fd755bfee32e34b8404"}, + {file = "numba-0.60.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:38d6ea4c1f56417076ecf8fc327c831ae793282e0ff51080c5094cb726507b1c"}, + {file = "numba-0.60.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:62908d29fb6a3229c242e981ca27e32a6e606cc253fc9e8faeb0e48760de241e"}, + {file = "numba-0.60.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0ebaa91538e996f708f1ab30ef4d3ddc344b64b5227b67a57aa74f401bb68b9d"}, + {file = "numba-0.60.0-cp312-cp312-win_amd64.whl", hash = "sha256:f75262e8fe7fa96db1dca93d53a194a38c46da28b112b8a4aca168f0df860347"}, + {file = "numba-0.60.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:01ef4cd7d83abe087d644eaa3d95831b777aa21d441a23703d649e06b8e06b74"}, + {file = "numba-0.60.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:819a3dfd4630d95fd574036f99e47212a1af41cbcb019bf8afac63ff56834449"}, + {file = "numba-0.60.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0b983bd6ad82fe868493012487f34eae8bf7dd94654951404114f23c3466d34b"}, + {file = "numba-0.60.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c151748cd269ddeab66334bd754817ffc0cabd9433acb0f551697e5151917d25"}, + {file = "numba-0.60.0-cp39-cp39-win_amd64.whl", hash = "sha256:3031547a015710140e8c87226b4cfe927cac199835e5bf7d4fe5cb64e814e3ab"}, + {file = "numba-0.60.0.tar.gz", hash = "sha256:5df6158e5584eece5fc83294b949fd30b9f1125df7708862205217e068aabf16"}, +] + +[package.dependencies] +llvmlite = "==0.43.*" +numpy = ">=1.22,<2.1" [[package]] name = "numcodecs" @@ -2286,20 +2351,20 @@ signedtoken = ["cryptography (>=3.0.0)", "pyjwt (>=2.0.0,<3)"] [[package]] name = "packaging" -version = "24.0" +version = "24.1" description = "Core utilities for Python packages" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5"}, - {file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"}, + {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, + {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, ] [[package]] name = "pandas" version = "2.2.2" description = "Powerful data structures for data analysis, time series, and statistics" -optional = true +optional = false python-versions = ">=3.9" files = [ {file = "pandas-2.2.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:90c6fca2acf139569e74e8781709dccb6fe25940488755716d1d354d6bc58bce"}, @@ -2408,13 +2473,13 @@ files = [ [[package]] name = "pep8-naming" -version = "0.13.3" +version = "0.14.1" description = "Check PEP-8 naming conventions, plugin for flake8" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pep8-naming-0.13.3.tar.gz", hash = "sha256:1705f046dfcd851378aac3be1cd1551c7c1e5ff363bacad707d43007877fa971"}, - {file = "pep8_naming-0.13.3-py3-none-any.whl", hash = "sha256:1a86b8c71a03337c97181917e2b472f0f5e4ccb06844a0d6f0a33522549e7a80"}, + {file = "pep8-naming-0.14.1.tar.gz", hash = "sha256:1ef228ae80875557eb6c1549deafed4dabbf3261cfcafa12f773fe0db9be8a36"}, + {file = "pep8_naming-0.14.1-py3-none-any.whl", hash = "sha256:63f514fc777d715f935faf185dedd679ab99526a7f2f503abb61587877f7b1c5"}, ] [package.dependencies] @@ -2539,13 +2604,13 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "portalocker" -version = "2.8.2" +version = "2.10.0" description = "Wraps the portalocker recipe for easy usage" optional = true python-versions = ">=3.8" files = [ - {file = "portalocker-2.8.2-py3-none-any.whl", hash = "sha256:cfb86acc09b9aa7c3b43594e19be1345b9d16af3feb08bf92f23d4dce513a28e"}, - {file = "portalocker-2.8.2.tar.gz", hash = "sha256:2b035aa7828e46c58e9b31390ee1f169b98e1066ab10b9a6a861fe7e25ee4f33"}, + {file = "portalocker-2.10.0-py3-none-any.whl", hash = "sha256:48944147b2cd42520549bc1bb8fe44e220296e56f7c3d551bc6ecce69d9b0de1"}, + {file = "portalocker-2.10.0.tar.gz", hash = "sha256:49de8bc0a2f68ca98bf9e219c81a3e6b27097c7bf505a87c5a112ce1aaeb9b81"}, ] [package.dependencies] @@ -2591,64 +2656,65 @@ tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} [[package]] name = "proto-plus" -version = "1.23.0" +version = "1.24.0" description = "Beautiful, Pythonic protocol buffers." optional = true -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "proto-plus-1.23.0.tar.gz", hash = "sha256:89075171ef11988b3fa157f5dbd8b9cf09d65fffee97e29ce403cd8defba19d2"}, - {file = "proto_plus-1.23.0-py3-none-any.whl", hash = "sha256:a829c79e619e1cf632de091013a4173deed13a55f326ef84f05af6f50ff4c82c"}, + {file = "proto-plus-1.24.0.tar.gz", hash = "sha256:30b72a5ecafe4406b0d339db35b56c4059064e69227b8c3bda7462397f966445"}, + {file = "proto_plus-1.24.0-py3-none-any.whl", hash = "sha256:402576830425e5f6ce4c2a6702400ac79897dab0b4343821aa5188b0fab81a12"}, ] [package.dependencies] -protobuf = ">=3.19.0,<5.0.0dev" +protobuf = ">=3.19.0,<6.0.0dev" [package.extras] -testing = ["google-api-core[grpc] (>=1.31.5)"] +testing = ["google-api-core (>=1.31.5)"] [[package]] name = "protobuf" -version = "4.25.3" +version = "5.27.1" description = "" optional = true python-versions = ">=3.8" files = [ - {file = "protobuf-4.25.3-cp310-abi3-win32.whl", hash = "sha256:d4198877797a83cbfe9bffa3803602bbe1625dc30d8a097365dbc762e5790faa"}, - {file = "protobuf-4.25.3-cp310-abi3-win_amd64.whl", hash = "sha256:209ba4cc916bab46f64e56b85b090607a676f66b473e6b762e6f1d9d591eb2e8"}, - {file = "protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:f1279ab38ecbfae7e456a108c5c0681e4956d5b1090027c1de0f934dfdb4b35c"}, - {file = "protobuf-4.25.3-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:e7cb0ae90dd83727f0c0718634ed56837bfeeee29a5f82a7514c03ee1364c019"}, - {file = "protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:7c8daa26095f82482307bc717364e7c13f4f1c99659be82890dcfc215194554d"}, - {file = "protobuf-4.25.3-cp38-cp38-win32.whl", hash = "sha256:f4f118245c4a087776e0a8408be33cf09f6c547442c00395fbfb116fac2f8ac2"}, - {file = "protobuf-4.25.3-cp38-cp38-win_amd64.whl", hash = "sha256:c053062984e61144385022e53678fbded7aea14ebb3e0305ae3592fb219ccfa4"}, - {file = "protobuf-4.25.3-cp39-cp39-win32.whl", hash = "sha256:19b270aeaa0099f16d3ca02628546b8baefe2955bbe23224aaf856134eccf1e4"}, - {file = "protobuf-4.25.3-cp39-cp39-win_amd64.whl", hash = "sha256:e3c97a1555fd6388f857770ff8b9703083de6bf1f9274a002a332d65fbb56c8c"}, - {file = "protobuf-4.25.3-py3-none-any.whl", hash = "sha256:f0700d54bcf45424477e46a9f0944155b46fb0639d69728739c0e47bab83f2b9"}, - {file = "protobuf-4.25.3.tar.gz", hash = "sha256:25b5d0b42fd000320bd7830b349e3b696435f3b329810427a6bcce6a5492cc5c"}, + {file = "protobuf-5.27.1-cp310-abi3-win32.whl", hash = "sha256:3adc15ec0ff35c5b2d0992f9345b04a540c1e73bfee3ff1643db43cc1d734333"}, + {file = "protobuf-5.27.1-cp310-abi3-win_amd64.whl", hash = "sha256:25236b69ab4ce1bec413fd4b68a15ef8141794427e0b4dc173e9d5d9dffc3bcd"}, + {file = "protobuf-5.27.1-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:4e38fc29d7df32e01a41cf118b5a968b1efd46b9c41ff515234e794011c78b17"}, + {file = "protobuf-5.27.1-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:917ed03c3eb8a2d51c3496359f5b53b4e4b7e40edfbdd3d3f34336e0eef6825a"}, + {file = "protobuf-5.27.1-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:ee52874a9e69a30271649be88ecbe69d374232e8fd0b4e4b0aaaa87f429f1631"}, + {file = "protobuf-5.27.1-cp38-cp38-win32.whl", hash = "sha256:7a97b9c5aed86b9ca289eb5148df6c208ab5bb6906930590961e08f097258107"}, + {file = "protobuf-5.27.1-cp38-cp38-win_amd64.whl", hash = "sha256:f6abd0f69968792da7460d3c2cfa7d94fd74e1c21df321eb6345b963f9ec3d8d"}, + {file = "protobuf-5.27.1-cp39-cp39-win32.whl", hash = "sha256:dfddb7537f789002cc4eb00752c92e67885badcc7005566f2c5de9d969d3282d"}, + {file = "protobuf-5.27.1-cp39-cp39-win_amd64.whl", hash = "sha256:39309898b912ca6febb0084ea912e976482834f401be35840a008da12d189340"}, + {file = "protobuf-5.27.1-py3-none-any.whl", hash = "sha256:4ac7249a1530a2ed50e24201d6630125ced04b30619262f06224616e0030b6cf"}, + {file = "protobuf-5.27.1.tar.gz", hash = "sha256:df5e5b8e39b7d1c25b186ffdf9f44f40f810bbcc9d2b71d9d3156fee5a9adf15"}, ] [[package]] name = "psutil" -version = "5.9.8" +version = "6.0.0" description = "Cross-platform lib for process and system monitoring in Python." optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" -files = [ - {file = "psutil-5.9.8-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:26bd09967ae00920df88e0352a91cff1a78f8d69b3ecabbfe733610c0af486c8"}, - {file = "psutil-5.9.8-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:05806de88103b25903dff19bb6692bd2e714ccf9e668d050d144012055cbca73"}, - {file = "psutil-5.9.8-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:611052c4bc70432ec770d5d54f64206aa7203a101ec273a0cd82418c86503bb7"}, - {file = "psutil-5.9.8-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:50187900d73c1381ba1454cf40308c2bf6f34268518b3f36a9b663ca87e65e36"}, - {file = "psutil-5.9.8-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:02615ed8c5ea222323408ceba16c60e99c3f91639b07da6373fb7e6539abc56d"}, - {file = "psutil-5.9.8-cp27-none-win32.whl", hash = "sha256:36f435891adb138ed3c9e58c6af3e2e6ca9ac2f365efe1f9cfef2794e6c93b4e"}, - {file = "psutil-5.9.8-cp27-none-win_amd64.whl", hash = "sha256:bd1184ceb3f87651a67b2708d4c3338e9b10c5df903f2e3776b62303b26cb631"}, - {file = "psutil-5.9.8-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:aee678c8720623dc456fa20659af736241f575d79429a0e5e9cf88ae0605cc81"}, - {file = "psutil-5.9.8-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8cb6403ce6d8e047495a701dc7c5bd788add903f8986d523e3e20b98b733e421"}, - {file = "psutil-5.9.8-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d06016f7f8625a1825ba3732081d77c94589dca78b7a3fc072194851e88461a4"}, - {file = "psutil-5.9.8-cp36-cp36m-win32.whl", hash = "sha256:7d79560ad97af658a0f6adfef8b834b53f64746d45b403f225b85c5c2c140eee"}, - {file = "psutil-5.9.8-cp36-cp36m-win_amd64.whl", hash = "sha256:27cc40c3493bb10de1be4b3f07cae4c010ce715290a5be22b98493509c6299e2"}, - {file = "psutil-5.9.8-cp37-abi3-win32.whl", hash = "sha256:bc56c2a1b0d15aa3eaa5a60c9f3f8e3e565303b465dbf57a1b730e7a2b9844e0"}, - {file = "psutil-5.9.8-cp37-abi3-win_amd64.whl", hash = "sha256:8db4c1b57507eef143a15a6884ca10f7c73876cdf5d51e713151c1236a0e68cf"}, - {file = "psutil-5.9.8-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:d16bbddf0693323b8c6123dd804100241da461e41d6e332fb0ba6058f630f8c8"}, - {file = "psutil-5.9.8.tar.gz", hash = "sha256:6be126e3225486dff286a8fb9a06246a5253f4c7c53b475ea5f5ac934e64194c"}, +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" +files = [ + {file = "psutil-6.0.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a021da3e881cd935e64a3d0a20983bda0bb4cf80e4f74fa9bfcb1bc5785360c6"}, + {file = "psutil-6.0.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:1287c2b95f1c0a364d23bc6f2ea2365a8d4d9b726a3be7294296ff7ba97c17f0"}, + {file = "psutil-6.0.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:a9a3dbfb4de4f18174528d87cc352d1f788b7496991cca33c6996f40c9e3c92c"}, + {file = "psutil-6.0.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:6ec7588fb3ddaec7344a825afe298db83fe01bfaaab39155fa84cf1c0d6b13c3"}, + {file = "psutil-6.0.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:1e7c870afcb7d91fdea2b37c24aeb08f98b6d67257a5cb0a8bc3ac68d0f1a68c"}, + {file = "psutil-6.0.0-cp27-none-win32.whl", hash = "sha256:02b69001f44cc73c1c5279d02b30a817e339ceb258ad75997325e0e6169d8b35"}, + {file = "psutil-6.0.0-cp27-none-win_amd64.whl", hash = "sha256:21f1fb635deccd510f69f485b87433460a603919b45e2a324ad65b0cc74f8fb1"}, + {file = "psutil-6.0.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c588a7e9b1173b6e866756dde596fd4cad94f9399daf99ad8c3258b3cb2b47a0"}, + {file = "psutil-6.0.0-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ed2440ada7ef7d0d608f20ad89a04ec47d2d3ab7190896cd62ca5fc4fe08bf0"}, + {file = "psutil-6.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fd9a97c8e94059b0ef54a7d4baf13b405011176c3b6ff257c247cae0d560ecd"}, + {file = "psutil-6.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2e8d0054fc88153ca0544f5c4d554d42e33df2e009c4ff42284ac9ebdef4132"}, + {file = "psutil-6.0.0-cp36-cp36m-win32.whl", hash = "sha256:fc8c9510cde0146432bbdb433322861ee8c3efbf8589865c8bf8d21cb30c4d14"}, + {file = "psutil-6.0.0-cp36-cp36m-win_amd64.whl", hash = "sha256:34859b8d8f423b86e4385ff3665d3f4d94be3cdf48221fbe476e883514fdb71c"}, + {file = "psutil-6.0.0-cp37-abi3-win32.whl", hash = "sha256:a495580d6bae27291324fe60cea0b5a7c23fa36a7cd35035a16d93bdcf076b9d"}, + {file = "psutil-6.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:33ea5e1c975250a720b3a6609c490db40dae5d83a4eb315170c4fe0d8b1f34b3"}, + {file = "psutil-6.0.0-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:ffe7fc9b6b36beadc8c322f84e1caff51e8703b88eee1da46d1e3a6ae11b4fd0"}, + {file = "psutil-6.0.0.tar.gz", hash = "sha256:8faae4f310b6d969fa26ca0545338b21f73c6b15db7c4a8d934a5482faa818f2"}, ] [package.extras] @@ -2681,26 +2747,155 @@ pyasn1 = ">=0.4.6,<0.7.0" [[package]] name = "pycodestyle" -version = "2.11.1" +version = "2.12.0" description = "Python style guide checker" optional = false python-versions = ">=3.8" files = [ - {file = "pycodestyle-2.11.1-py2.py3-none-any.whl", hash = "sha256:44fe31000b2d866f2e41841b18528a505fbd7fef9017b04eff4e2648a0fadc67"}, - {file = "pycodestyle-2.11.1.tar.gz", hash = "sha256:41ba0e7afc9752dfb53ced5489e89f8186be00e599e712660695b7a75ff2663f"}, + {file = "pycodestyle-2.12.0-py2.py3-none-any.whl", hash = "sha256:949a39f6b86c3e1515ba1787c2022131d165a8ad271b11370a8819aa070269e4"}, + {file = "pycodestyle-2.12.0.tar.gz", hash = "sha256:442f950141b4f43df752dd303511ffded3a04c2b6fb7f65980574f0c31e6e79c"}, ] [[package]] name = "pycparser" version = "2.22" description = "C parser in Python" -optional = true +optional = false python-versions = ">=3.8" files = [ {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, ] +[[package]] +name = "pydantic" +version = "2.7.4" +description = "Data validation using Python type hints" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pydantic-2.7.4-py3-none-any.whl", hash = "sha256:ee8538d41ccb9c0a9ad3e0e5f07bf15ed8015b481ced539a1759d8cc89ae90d0"}, + {file = "pydantic-2.7.4.tar.gz", hash = "sha256:0c84efd9548d545f63ac0060c1e4d39bb9b14db8b3c0652338aecc07b5adec52"}, +] + +[package.dependencies] +annotated-types = ">=0.4.0" +pydantic-core = "2.18.4" +typing-extensions = ">=4.6.1" + +[package.extras] +email = ["email-validator (>=2.0.0)"] + +[[package]] +name = "pydantic-core" +version = "2.18.4" +description = "Core functionality for Pydantic validation and serialization" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pydantic_core-2.18.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:f76d0ad001edd426b92233d45c746fd08f467d56100fd8f30e9ace4b005266e4"}, + {file = "pydantic_core-2.18.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:59ff3e89f4eaf14050c8022011862df275b552caef8082e37b542b066ce1ff26"}, + {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a55b5b16c839df1070bc113c1f7f94a0af4433fcfa1b41799ce7606e5c79ce0a"}, + {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4d0dcc59664fcb8974b356fe0a18a672d6d7cf9f54746c05f43275fc48636851"}, + {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8951eee36c57cd128f779e641e21eb40bc5073eb28b2d23f33eb0ef14ffb3f5d"}, + {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4701b19f7e3a06ea655513f7938de6f108123bf7c86bbebb1196eb9bd35cf724"}, + {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e00a3f196329e08e43d99b79b286d60ce46bed10f2280d25a1718399457e06be"}, + {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:97736815b9cc893b2b7f663628e63f436018b75f44854c8027040e05230eeddb"}, + {file = "pydantic_core-2.18.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6891a2ae0e8692679c07728819b6e2b822fb30ca7445f67bbf6509b25a96332c"}, + {file = "pydantic_core-2.18.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bc4ff9805858bd54d1a20efff925ccd89c9d2e7cf4986144b30802bf78091c3e"}, + {file = "pydantic_core-2.18.4-cp310-none-win32.whl", hash = "sha256:1b4de2e51bbcb61fdebd0ab86ef28062704f62c82bbf4addc4e37fa4b00b7cbc"}, + {file = "pydantic_core-2.18.4-cp310-none-win_amd64.whl", hash = "sha256:6a750aec7bf431517a9fd78cb93c97b9b0c496090fee84a47a0d23668976b4b0"}, + {file = "pydantic_core-2.18.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:942ba11e7dfb66dc70f9ae66b33452f51ac7bb90676da39a7345e99ffb55402d"}, + {file = "pydantic_core-2.18.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b2ebef0e0b4454320274f5e83a41844c63438fdc874ea40a8b5b4ecb7693f1c4"}, + {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a642295cd0c8df1b86fc3dced1d067874c353a188dc8e0f744626d49e9aa51c4"}, + {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f09baa656c904807e832cf9cce799c6460c450c4ad80803517032da0cd062e2"}, + {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:98906207f29bc2c459ff64fa007afd10a8c8ac080f7e4d5beff4c97086a3dabd"}, + {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:19894b95aacfa98e7cb093cd7881a0c76f55731efad31073db4521e2b6ff5b7d"}, + {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0fbbdc827fe5e42e4d196c746b890b3d72876bdbf160b0eafe9f0334525119c8"}, + {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f85d05aa0918283cf29a30b547b4df2fbb56b45b135f9e35b6807cb28bc47951"}, + {file = "pydantic_core-2.18.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e85637bc8fe81ddb73fda9e56bab24560bdddfa98aa64f87aaa4e4b6730c23d2"}, + {file = "pydantic_core-2.18.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2f5966897e5461f818e136b8451d0551a2e77259eb0f73a837027b47dc95dab9"}, + {file = "pydantic_core-2.18.4-cp311-none-win32.whl", hash = "sha256:44c7486a4228413c317952e9d89598bcdfb06399735e49e0f8df643e1ccd0558"}, + {file = "pydantic_core-2.18.4-cp311-none-win_amd64.whl", hash = "sha256:8a7164fe2005d03c64fd3b85649891cd4953a8de53107940bf272500ba8a788b"}, + {file = "pydantic_core-2.18.4-cp311-none-win_arm64.whl", hash = "sha256:4e99bc050fe65c450344421017f98298a97cefc18c53bb2f7b3531eb39bc7805"}, + {file = "pydantic_core-2.18.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:6f5c4d41b2771c730ea1c34e458e781b18cc668d194958e0112455fff4e402b2"}, + {file = "pydantic_core-2.18.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2fdf2156aa3d017fddf8aea5adfba9f777db1d6022d392b682d2a8329e087cef"}, + {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4748321b5078216070b151d5271ef3e7cc905ab170bbfd27d5c83ee3ec436695"}, + {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:847a35c4d58721c5dc3dba599878ebbdfd96784f3fb8bb2c356e123bdcd73f34"}, + {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3c40d4eaad41f78e3bbda31b89edc46a3f3dc6e171bf0ecf097ff7a0ffff7cb1"}, + {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:21a5e440dbe315ab9825fcd459b8814bb92b27c974cbc23c3e8baa2b76890077"}, + {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01dd777215e2aa86dfd664daed5957704b769e726626393438f9c87690ce78c3"}, + {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4b06beb3b3f1479d32befd1f3079cc47b34fa2da62457cdf6c963393340b56e9"}, + {file = "pydantic_core-2.18.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:564d7922e4b13a16b98772441879fcdcbe82ff50daa622d681dd682175ea918c"}, + {file = "pydantic_core-2.18.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:0eb2a4f660fcd8e2b1c90ad566db2b98d7f3f4717c64fe0a83e0adb39766d5b8"}, + {file = "pydantic_core-2.18.4-cp312-none-win32.whl", hash = "sha256:8b8bab4c97248095ae0c4455b5a1cd1cdd96e4e4769306ab19dda135ea4cdb07"}, + {file = "pydantic_core-2.18.4-cp312-none-win_amd64.whl", hash = "sha256:14601cdb733d741b8958224030e2bfe21a4a881fb3dd6fbb21f071cabd48fa0a"}, + {file = "pydantic_core-2.18.4-cp312-none-win_arm64.whl", hash = "sha256:c1322d7dd74713dcc157a2b7898a564ab091ca6c58302d5c7b4c07296e3fd00f"}, + {file = "pydantic_core-2.18.4-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:823be1deb01793da05ecb0484d6c9e20baebb39bd42b5d72636ae9cf8350dbd2"}, + {file = "pydantic_core-2.18.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ebef0dd9bf9b812bf75bda96743f2a6c5734a02092ae7f721c048d156d5fabae"}, + {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ae1d6df168efb88d7d522664693607b80b4080be6750c913eefb77e34c12c71a"}, + {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f9899c94762343f2cc2fc64c13e7cae4c3cc65cdfc87dd810a31654c9b7358cc"}, + {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99457f184ad90235cfe8461c4d70ab7dd2680e28821c29eca00252ba90308c78"}, + {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18f469a3d2a2fdafe99296a87e8a4c37748b5080a26b806a707f25a902c040a8"}, + {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b7cdf28938ac6b8b49ae5e92f2735056a7ba99c9b110a474473fd71185c1af5d"}, + {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:938cb21650855054dc54dfd9120a851c974f95450f00683399006aa6e8abb057"}, + {file = "pydantic_core-2.18.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:44cd83ab6a51da80fb5adbd9560e26018e2ac7826f9626bc06ca3dc074cd198b"}, + {file = "pydantic_core-2.18.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:972658f4a72d02b8abfa2581d92d59f59897d2e9f7e708fdabe922f9087773af"}, + {file = "pydantic_core-2.18.4-cp38-none-win32.whl", hash = "sha256:1d886dc848e60cb7666f771e406acae54ab279b9f1e4143babc9c2258213daa2"}, + {file = "pydantic_core-2.18.4-cp38-none-win_amd64.whl", hash = "sha256:bb4462bd43c2460774914b8525f79b00f8f407c945d50881568f294c1d9b4443"}, + {file = "pydantic_core-2.18.4-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:44a688331d4a4e2129140a8118479443bd6f1905231138971372fcde37e43528"}, + {file = "pydantic_core-2.18.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a2fdd81edd64342c85ac7cf2753ccae0b79bf2dfa063785503cb85a7d3593223"}, + {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:86110d7e1907ab36691f80b33eb2da87d780f4739ae773e5fc83fb272f88825f"}, + {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:46387e38bd641b3ee5ce247563b60c5ca098da9c56c75c157a05eaa0933ed154"}, + {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:123c3cec203e3f5ac7b000bd82235f1a3eced8665b63d18be751f115588fea30"}, + {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dc1803ac5c32ec324c5261c7209e8f8ce88e83254c4e1aebdc8b0a39f9ddb443"}, + {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53db086f9f6ab2b4061958d9c276d1dbe3690e8dd727d6abf2321d6cce37fa94"}, + {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:abc267fa9837245cc28ea6929f19fa335f3dc330a35d2e45509b6566dc18be23"}, + {file = "pydantic_core-2.18.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a0d829524aaefdebccb869eed855e2d04c21d2d7479b6cada7ace5448416597b"}, + {file = "pydantic_core-2.18.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:509daade3b8649f80d4e5ff21aa5673e4ebe58590b25fe42fac5f0f52c6f034a"}, + {file = "pydantic_core-2.18.4-cp39-none-win32.whl", hash = "sha256:ca26a1e73c48cfc54c4a76ff78df3727b9d9f4ccc8dbee4ae3f73306a591676d"}, + {file = "pydantic_core-2.18.4-cp39-none-win_amd64.whl", hash = "sha256:c67598100338d5d985db1b3d21f3619ef392e185e71b8d52bceacc4a7771ea7e"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:574d92eac874f7f4db0ca653514d823a0d22e2354359d0759e3f6a406db5d55d"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:1f4d26ceb5eb9eed4af91bebeae4b06c3fb28966ca3a8fb765208cf6b51102ab"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77450e6d20016ec41f43ca4a6c63e9fdde03f0ae3fe90e7c27bdbeaece8b1ed4"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d323a01da91851a4f17bf592faf46149c9169d68430b3146dcba2bb5e5719abc"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:43d447dd2ae072a0065389092a231283f62d960030ecd27565672bd40746c507"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:578e24f761f3b425834f297b9935e1ce2e30f51400964ce4801002435a1b41ef"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:81b5efb2f126454586d0f40c4d834010979cb80785173d1586df845a632e4e6d"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ab86ce7c8f9bea87b9d12c7f0af71102acbf5ecbc66c17796cff45dae54ef9a5"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:90afc12421df2b1b4dcc975f814e21bc1754640d502a2fbcc6d41e77af5ec312"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:51991a89639a912c17bef4b45c87bd83593aee0437d8102556af4885811d59f5"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:293afe532740370aba8c060882f7d26cfd00c94cae32fd2e212a3a6e3b7bc15e"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b48ece5bde2e768197a2d0f6e925f9d7e3e826f0ad2271120f8144a9db18d5c8"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:eae237477a873ab46e8dd748e515c72c0c804fb380fbe6c85533c7de51f23a8f"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:834b5230b5dfc0c1ec37b2fda433b271cbbc0e507560b5d1588e2cc1148cf1ce"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e858ac0a25074ba4bce653f9b5d0a85b7456eaddadc0ce82d3878c22489fa4ee"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2fd41f6eff4c20778d717af1cc50eca52f5afe7805ee530a4fbd0bae284f16e9"}, + {file = "pydantic_core-2.18.4.tar.gz", hash = "sha256:ec3beeada09ff865c344ff3bc2f427f5e6c26401cc6113d77e372c3fdac73864"}, +] + +[package.dependencies] +typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" + +[[package]] +name = "pydantic-settings" +version = "2.3.4" +description = "Settings management using Pydantic" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pydantic_settings-2.3.4-py3-none-any.whl", hash = "sha256:11ad8bacb68a045f00e4f862c7a718c8a9ec766aa8fd4c32e39a0594b207b53a"}, + {file = "pydantic_settings-2.3.4.tar.gz", hash = "sha256:c5802e3d62b78e82522319bbc9b8f8ffb28ad1c988a99311d04f2a6051fca0a7"}, +] + +[package.dependencies] +pydantic = ">=2.7.0" +python-dotenv = ">=0.21.0" + +[package.extras] +toml = ["tomli (>=2.0.1)"] +yaml = ["pyyaml (>=6.0.1)"] + [[package]] name = "pydocstyle" version = "6.3.0" @@ -2765,13 +2960,13 @@ tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] [[package]] name = "pytest" -version = "7.4.4" +version = "8.2.2" description = "pytest: simple powerful testing with Python" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, - {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, + {file = "pytest-8.2.2-py3-none-any.whl", hash = "sha256:c434598117762e2bd304e526244f67bf66bbd7b5d6cf22138be51ff661980343"}, + {file = "pytest-8.2.2.tar.gz", hash = "sha256:de4bb8104e201939ccdc688b27a89a7be2079b22e2bd2b07f806b6ba71117977"}, ] [package.dependencies] @@ -2779,17 +2974,31 @@ colorama = {version = "*", markers = "sys_platform == \"win32\""} exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} iniconfig = "*" packaging = "*" -pluggy = ">=0.12,<2.0" -tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} +pluggy = ">=1.5,<2.0" +tomli = {version = ">=1", markers = "python_version < \"3.11\""} [package.extras] -testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] +dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] + +[[package]] +name = "pytest-dependency" +version = "0.6.0" +description = "Manage dependencies of tests" +optional = false +python-versions = ">=3.4" +files = [ + {file = "pytest-dependency-0.6.0.tar.gz", hash = "sha256:934b0e6a39d95995062c193f7eaeed8a8ffa06ff1bcef4b62b0dc74a708bacc1"}, +] + +[package.dependencies] +pytest = ">=3.7.0" +setuptools = "*" [[package]] name = "python-dateutil" version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" -optional = true +optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" files = [ {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, @@ -2799,11 +3008,25 @@ files = [ [package.dependencies] six = ">=1.5" +[[package]] +name = "python-dotenv" +version = "1.0.1" +description = "Read key-value pairs from a .env file and set them as environment variables" +optional = false +python-versions = ">=3.8" +files = [ + {file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"}, + {file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"}, +] + +[package.extras] +cli = ["click (>=5.0)"] + [[package]] name = "pytz" version = "2024.1" description = "World timezone definitions, modern and historical" -optional = true +optional = false python-versions = "*" files = [ {file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"}, @@ -2812,13 +3035,13 @@ files = [ [[package]] name = "pyupgrade" -version = "3.15.2" +version = "3.16.0" description = "A tool to automatically upgrade syntax for newer versions." optional = false python-versions = ">=3.8.1" files = [ - {file = "pyupgrade-3.15.2-py2.py3-none-any.whl", hash = "sha256:ce309e0ff8ecb73f56a45f12570be84bbbde9540d13697cacb261a7f595fb1f5"}, - {file = "pyupgrade-3.15.2.tar.gz", hash = "sha256:c488d6896c546d25845712ef6402657123008d56c1063174e27aabe15bd6b4e5"}, + {file = "pyupgrade-3.16.0-py2.py3-none-any.whl", hash = "sha256:7a54ee28f3024d027048d49d101e5c702e88c85edc3a1d08b636c50ebef2a97d"}, + {file = "pyupgrade-3.16.0.tar.gz", hash = "sha256:237893a05d5b117259b31b423f23cbae4bce0b7eae57ba9a52c06098c2ddd76f"}, ] [package.dependencies] @@ -2906,15 +3129,120 @@ files = [ {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, ] +[[package]] +name = "rapidfuzz" +version = "3.9.3" +description = "rapid fuzzy string matching" +optional = false +python-versions = ">=3.8" +files = [ + {file = "rapidfuzz-3.9.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bdb8c5b8e29238ec80727c2ba3b301efd45aa30c6a7001123a6647b8e6f77ea4"}, + {file = "rapidfuzz-3.9.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b3bd0d9632088c63a241f217742b1cf86e2e8ae573e01354775bd5016d12138c"}, + {file = "rapidfuzz-3.9.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:153f23c03d4917f6a1fc2fb56d279cc6537d1929237ff08ee7429d0e40464a18"}, + {file = "rapidfuzz-3.9.3-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a96c5225e840f1587f1bac8fa6f67562b38e095341576e82b728a82021f26d62"}, + {file = "rapidfuzz-3.9.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b777cd910ceecd738adc58593d6ed42e73f60ad04ecdb4a841ae410b51c92e0e"}, + {file = "rapidfuzz-3.9.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:53e06e4b81f552da04940aa41fc556ba39dee5513d1861144300c36c33265b76"}, + {file = "rapidfuzz-3.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c7ca5b6050f18fdcacdada2dc5fb7619ff998cd9aba82aed2414eee74ebe6cd"}, + {file = "rapidfuzz-3.9.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:87bb8d84cb41446a808c4b5f746e29d8a53499381ed72f6c4e456fe0f81c80a8"}, + {file = "rapidfuzz-3.9.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:959a15186d18425d19811bea86a8ffbe19fd48644004d29008e636631420a9b7"}, + {file = "rapidfuzz-3.9.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:a24603dd05fb4e3c09d636b881ce347e5f55f925a6b1b4115527308a323b9f8e"}, + {file = "rapidfuzz-3.9.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:0d055da0e801c71dd74ba81d72d41b2fa32afa182b9fea6b4b199d2ce937450d"}, + {file = "rapidfuzz-3.9.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:875b581afb29a7213cf9d98cb0f98df862f1020bce9d9b2e6199b60e78a41d14"}, + {file = "rapidfuzz-3.9.3-cp310-cp310-win32.whl", hash = "sha256:6073a46f61479a89802e3f04655267caa6c14eb8ac9d81a635a13805f735ebc1"}, + {file = "rapidfuzz-3.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:119c010e20e561249b99ca2627f769fdc8305b07193f63dbc07bca0a6c27e892"}, + {file = "rapidfuzz-3.9.3-cp310-cp310-win_arm64.whl", hash = "sha256:790b0b244f3213581d42baa2fed8875f9ee2b2f9b91f94f100ec80d15b140ba9"}, + {file = "rapidfuzz-3.9.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f57e8305c281e8c8bc720515540e0580355100c0a7a541105c6cafc5de71daae"}, + {file = "rapidfuzz-3.9.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a4fc7b784cf987dbddc300cef70e09a92ed1bce136f7bb723ea79d7e297fe76d"}, + {file = "rapidfuzz-3.9.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b422c0a6fe139d5447a0766268e68e6a2a8c2611519f894b1f31f0a392b9167"}, + {file = "rapidfuzz-3.9.3-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f50fed4a9b0c9825ff37cf0bccafd51ff5792090618f7846a7650f21f85579c9"}, + {file = "rapidfuzz-3.9.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b80eb7cbe62348c61d3e67e17057cddfd6defab168863028146e07d5a8b24a89"}, + {file = "rapidfuzz-3.9.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f45be77ec82da32ce5709a362e236ccf801615cc7163b136d1778cf9e31b14"}, + {file = "rapidfuzz-3.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd84b7f652a5610733400307dc732f57c4a907080bef9520412e6d9b55bc9adc"}, + {file = "rapidfuzz-3.9.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3e6d27dad8c990218b8cd4a5c99cbc8834f82bb46ab965a7265d5aa69fc7ced7"}, + {file = "rapidfuzz-3.9.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:05ee0696ebf0dfe8f7c17f364d70617616afc7dafe366532730ca34056065b8a"}, + {file = "rapidfuzz-3.9.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:2bc8391749e5022cd9e514ede5316f86e332ffd3cfceeabdc0b17b7e45198a8c"}, + {file = "rapidfuzz-3.9.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:93981895602cf5944d89d317ae3b1b4cc684d175a8ae2a80ce5b65615e72ddd0"}, + {file = "rapidfuzz-3.9.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:754b719a4990735f66653c9e9261dcf52fd4d925597e43d6b9069afcae700d21"}, + {file = "rapidfuzz-3.9.3-cp311-cp311-win32.whl", hash = "sha256:14c9f268ade4c88cf77ab007ad0fdf63699af071ee69378de89fff7aa3cae134"}, + {file = "rapidfuzz-3.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:bc1991b4cde6c9d3c0bbcb83d5581dc7621bec8c666c095c65b4277233265a82"}, + {file = "rapidfuzz-3.9.3-cp311-cp311-win_arm64.whl", hash = "sha256:0c34139df09a61b1b557ab65782ada971b4a3bce7081d1b2bee45b0a52231adb"}, + {file = "rapidfuzz-3.9.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5d6a210347d6e71234af5c76d55eeb0348b026c9bb98fe7c1cca89bac50fb734"}, + {file = "rapidfuzz-3.9.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b300708c917ce52f6075bdc6e05b07c51a085733650f14b732c087dc26e0aaad"}, + {file = "rapidfuzz-3.9.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83ea7ca577d76778250421de61fb55a719e45b841deb769351fc2b1740763050"}, + {file = "rapidfuzz-3.9.3-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8319838fb5b7b5f088d12187d91d152b9386ce3979ed7660daa0ed1bff953791"}, + {file = "rapidfuzz-3.9.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:505d99131afd21529293a9a7b91dfc661b7e889680b95534756134dc1cc2cd86"}, + {file = "rapidfuzz-3.9.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c52970f7784518d7c82b07a62a26e345d2de8c2bd8ed4774e13342e4b3ff4200"}, + {file = "rapidfuzz-3.9.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:143caf7247449055ecc3c1e874b69e42f403dfc049fc2f3d5f70e1daf21c1318"}, + {file = "rapidfuzz-3.9.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b8ab0fa653d9225195a8ff924f992f4249c1e6fa0aea563f685e71b81b9fcccf"}, + {file = "rapidfuzz-3.9.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:57e7c5bf7b61c7320cfa5dde1e60e678d954ede9bb7da8e763959b2138391401"}, + {file = "rapidfuzz-3.9.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:51fa1ba84653ab480a2e2044e2277bd7f0123d6693051729755addc0d015c44f"}, + {file = "rapidfuzz-3.9.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:17ff7f7eecdb169f9236e3b872c96dbbaf116f7787f4d490abd34b0116e3e9c8"}, + {file = "rapidfuzz-3.9.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:afe7c72d3f917b066257f7ff48562e5d462d865a25fbcabf40fca303a9fa8d35"}, + {file = "rapidfuzz-3.9.3-cp312-cp312-win32.whl", hash = "sha256:e53ed2e9b32674ce96eed80b3b572db9fd87aae6742941fb8e4705e541d861ce"}, + {file = "rapidfuzz-3.9.3-cp312-cp312-win_amd64.whl", hash = "sha256:35b7286f177e4d8ba1e48b03612f928a3c4bdac78e5651379cec59f95d8651e6"}, + {file = "rapidfuzz-3.9.3-cp312-cp312-win_arm64.whl", hash = "sha256:e6e4b9380ed4758d0cb578b0d1970c3f32dd9e87119378729a5340cb3169f879"}, + {file = "rapidfuzz-3.9.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a39890013f6d5b056cc4bfdedc093e322462ece1027a57ef0c636537bdde7531"}, + {file = "rapidfuzz-3.9.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b5bc0fdbf419493163c5c9cb147c5fbe95b8e25844a74a8807dcb1a125e630cf"}, + {file = "rapidfuzz-3.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efe6e200a75a792d37b960457904c4fce7c928a96ae9e5d21d2bd382fe39066e"}, + {file = "rapidfuzz-3.9.3-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:de077c468c225d4c18f7188c47d955a16d65f21aab121cbdd98e3e2011002c37"}, + {file = "rapidfuzz-3.9.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8f917eaadf5388466a95f6a236f678a1588d231e52eda85374077101842e794e"}, + {file = "rapidfuzz-3.9.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:858ba57c05afd720db8088a8707079e8d024afe4644001fe0dbd26ef7ca74a65"}, + {file = "rapidfuzz-3.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d36447d21b05f90282a6f98c5a33771805f9222e5d0441d03eb8824e33e5bbb4"}, + {file = "rapidfuzz-3.9.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:acbe4b6f1ccd5b90c29d428e849aa4242e51bb6cab0448d5f3c022eb9a25f7b1"}, + {file = "rapidfuzz-3.9.3-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:53c7f27cdf899e94712972237bda48cfd427646aa6f5d939bf45d084780e4c16"}, + {file = "rapidfuzz-3.9.3-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:6175682a829c6dea4d35ed707f1dadc16513270ef64436568d03b81ccb6bdb74"}, + {file = "rapidfuzz-3.9.3-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:5276df395bd8497397197fca2b5c85f052d2e6a66ffc3eb0544dd9664d661f95"}, + {file = "rapidfuzz-3.9.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:77b5c4f3e72924d7845f0e189c304270066d0f49635cf8a3938e122c437e58de"}, + {file = "rapidfuzz-3.9.3-cp38-cp38-win32.whl", hash = "sha256:8add34061e5cd561c72ed4febb5c15969e7b25bda2bb5102d02afc3abc1f52d0"}, + {file = "rapidfuzz-3.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:604e0502a39cf8e67fa9ad239394dddad4cdef6d7008fdb037553817d420e108"}, + {file = "rapidfuzz-3.9.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:21047f55d674614eb4b0ab34e35c3dc66f36403b9fbfae645199c4a19d4ed447"}, + {file = "rapidfuzz-3.9.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a56da3aff97cb56fe85d9ca957d1f55dbac7c27da927a86a2a86d8a7e17f80aa"}, + {file = "rapidfuzz-3.9.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:964c08481aec2fe574f0062e342924db2c6b321391aeb73d68853ed42420fd6d"}, + {file = "rapidfuzz-3.9.3-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5e2b827258beefbe5d3f958243caa5a44cf46187eff0c20e0b2ab62d1550327a"}, + {file = "rapidfuzz-3.9.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c6e65a301fcd19fbfbee3a514cc0014ff3f3b254b9fd65886e8a9d6957fb7bca"}, + {file = "rapidfuzz-3.9.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cbe93ba1725a8d47d2b9dca6c1f435174859427fbc054d83de52aea5adc65729"}, + {file = "rapidfuzz-3.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aca21c0a34adee582775da997a600283e012a608a107398d80a42f9a57ad323d"}, + {file = "rapidfuzz-3.9.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:256e07d3465173b2a91c35715a2277b1ee3ae0b9bbab4e519df6af78570741d0"}, + {file = "rapidfuzz-3.9.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:802ca2cc8aa6b8b34c6fdafb9e32540c1ba05fca7ad60b3bbd7ec89ed1797a87"}, + {file = "rapidfuzz-3.9.3-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:dd789100fc852cffac1449f82af0da139d36d84fd9faa4f79fc4140a88778343"}, + {file = "rapidfuzz-3.9.3-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:5d0abbacdb06e27ff803d7ae0bd0624020096802758068ebdcab9bd49cf53115"}, + {file = "rapidfuzz-3.9.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:378d1744828e27490a823fc6fe6ebfb98c15228d54826bf4e49e4b76eb5f5579"}, + {file = "rapidfuzz-3.9.3-cp39-cp39-win32.whl", hash = "sha256:5d0cb272d43e6d3c0dedefdcd9d00007471f77b52d2787a4695e9dd319bb39d2"}, + {file = "rapidfuzz-3.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:15e4158ac4b3fb58108072ec35b8a69165f651ba1c8f43559a36d518dbf9fb3f"}, + {file = "rapidfuzz-3.9.3-cp39-cp39-win_arm64.whl", hash = "sha256:58c6a4936190c558d5626b79fc9e16497e5df7098589a7e80d8bff68148ff096"}, + {file = "rapidfuzz-3.9.3-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5410dc848c947a603792f4f51b904a3331cf1dc60621586bfbe7a6de72da1091"}, + {file = "rapidfuzz-3.9.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:282d55700a1a3d3a7980746eb2fcd48c9bbc1572ebe0840d0340d548a54d01fe"}, + {file = "rapidfuzz-3.9.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc1037507810833646481f5729901a154523f98cbebb1157ba3a821012e16402"}, + {file = "rapidfuzz-3.9.3-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5e33f779391caedcba2ba3089fb6e8e557feab540e9149a5c3f7fea7a3a7df37"}, + {file = "rapidfuzz-3.9.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:41a81a9f311dc83d22661f9b1a1de983b201322df0c4554042ffffd0f2040c37"}, + {file = "rapidfuzz-3.9.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a93250bd8fae996350c251e1752f2c03335bb8a0a5b0c7e910a593849121a435"}, + {file = "rapidfuzz-3.9.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3617d1aa7716c57d120b6adc8f7c989f2d65bc2b0cbd5f9288f1fc7bf469da11"}, + {file = "rapidfuzz-3.9.3-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:ad04a3f5384b82933213bba2459f6424decc2823df40098920856bdee5fd6e88"}, + {file = "rapidfuzz-3.9.3-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8709918da8a88ad73c9d4dd0ecf24179a4f0ceba0bee21efc6ea21a8b5290349"}, + {file = "rapidfuzz-3.9.3-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b770f85eab24034e6ef7df04b2bfd9a45048e24f8a808e903441aa5abde8ecdd"}, + {file = "rapidfuzz-3.9.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:930b4e6fdb4d914390141a2b99a6f77a52beacf1d06aa4e170cba3a98e24c1bc"}, + {file = "rapidfuzz-3.9.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:c8444e921bfc3757c475c4f4d7416a7aa69b2d992d5114fe55af21411187ab0d"}, + {file = "rapidfuzz-3.9.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:2c1d3ef3878f871abe6826e386c3d61b5292ef5f7946fe646f4206b85836b5da"}, + {file = "rapidfuzz-3.9.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:d861bf326ee7dabc35c532a40384541578cd1ec1e1b7db9f9ecbba56eb76ca22"}, + {file = "rapidfuzz-3.9.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cde6b9d9ba5007077ee321ec722fa714ebc0cbd9a32ccf0f4dd3cc3f20952d71"}, + {file = "rapidfuzz-3.9.3-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3bb6546e7b6bed1aefbe24f68a5fb9b891cc5aef61bca6c1a7b1054b7f0359bb"}, + {file = "rapidfuzz-3.9.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d8a57261ef7996d5ced7c8cba9189ada3fbeffd1815f70f635e4558d93766cb"}, + {file = "rapidfuzz-3.9.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:67201c02efc596923ad950519e0b75ceb78d524177ea557134d6567b9ac2c283"}, + {file = "rapidfuzz-3.9.3.tar.gz", hash = "sha256:b398ea66e8ed50451bce5997c430197d5e4b06ac4aa74602717f792d8d8d06e2"}, +] + +[package.extras] +full = ["numpy"] + [[package]] name = "requests" -version = "2.32.1" +version = "2.32.3" description = "Python HTTP for Humans." optional = false python-versions = ">=3.8" files = [ - {file = "requests-2.32.1-py3-none-any.whl", hash = "sha256:21ac9465cdf8c1650fe1ecde8a71669a93d4e6f147550483a2967d08396a56a5"}, - {file = "requests-2.32.1.tar.gz", hash = "sha256:eb97e87e64c79e64e5b8ac75cee9dd1f97f49e289b083ee6be96268930725685"}, + {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, + {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, ] [package.dependencies] @@ -3069,19 +3397,19 @@ files = [ [[package]] name = "s3fs" -version = "2024.5.0" +version = "2024.6.0" description = "Convenient Filesystem interface over S3" optional = true python-versions = ">=3.8" files = [ - {file = "s3fs-2024.5.0-py3-none-any.whl", hash = "sha256:edccd9cc9f33a344a090e54b71e9f507e5b2d79369353b0e101237b20a720bc6"}, - {file = "s3fs-2024.5.0.tar.gz", hash = "sha256:b03471ae0d066b275b7dd0b0383cc5a93538ef40b2f6e730ce447bce849c1e32"}, + {file = "s3fs-2024.6.0-py3-none-any.whl", hash = "sha256:8d5f591956a61c7d64097eff4847598826f09d60b4ce9a16202565693569f6d4"}, + {file = "s3fs-2024.6.0.tar.gz", hash = "sha256:a59020ededc61e9666f1e473ce4aa28764e5f7b3c97414beb15cd9be522a87b6"}, ] [package.dependencies] aiobotocore = ">=2.5.4,<3.0.0" aiohttp = "<4.0.0a0 || >4.0.0a0,<4.0.0a1 || >4.0.0a1" -fsspec = "==2024.5.0.*" +fsspec = "==2024.6.0.*" [package.extras] awscli = ["aiobotocore[awscli] (>=2.5.4,<3.0.0)"] @@ -3089,103 +3417,106 @@ boto3 = ["aiobotocore[boto3] (>=2.5.4,<3.0.0)"] [[package]] name = "safety" -version = "2.4.0b2" +version = "3.2.3" description = "Checks installed dependencies for known vulnerabilities and licenses." optional = false -python-versions = "*" +python-versions = ">=3.7" files = [ - {file = "safety-2.4.0b2-py3-none-any.whl", hash = "sha256:63773ce92e17f5f80e7dff4c8a25d8abb7d62d375897b5f3bb4afe9313b100ff"}, - {file = "safety-2.4.0b2.tar.gz", hash = "sha256:9907010c6ca7720861ca7fa1496bdb80449b0619ca136eb7ac7e02bd3516cd4f"}, + {file = "safety-3.2.3-py3-none-any.whl", hash = "sha256:cda1e91749f610337a18b7f21f78267c127e44ebbbbcbbd419c83284279a5024"}, + {file = "safety-3.2.3.tar.gz", hash = "sha256:414154934f1727daf8a6473493944fecb380540c3f00875dc1ae377382f7d83f"}, ] [package.dependencies] +Authlib = ">=1.2.0" Click = ">=8.0.2" -dparse = ">=0.6.2" -jinja2 = {version = ">=3.1.0", markers = "python_version >= \"3.7\""} -marshmallow = {version = ">=3.15.0", markers = "python_version >= \"3.7\""} +dparse = ">=0.6.4b0" +jinja2 = ">=3.1.0" +marshmallow = ">=3.15.0" packaging = ">=21.0" +pydantic = ">=1.10.12" requests = "*" +rich = "*" "ruamel.yaml" = ">=0.17.21" -setuptools = {version = ">=65.5.1", markers = "python_version >= \"3.7\""} +safety-schemas = ">=0.0.2" +setuptools = ">=65.5.1" +typer = "*" +typing-extensions = ">=4.7.1" urllib3 = ">=1.26.5" [package.extras] github = ["pygithub (>=1.43.3)"] gitlab = ["python-gitlab (>=1.3.0)"] +spdx = ["spdx-tools (>=0.8.2)"] [[package]] -name = "segyio" -version = "1.9.12" -description = "Simple & fast IO for SEG-Y files" +name = "safety-schemas" +version = "0.0.2" +description = "Schemas for Safety tools" optional = false -python-versions = "*" +python-versions = ">=3.7" +files = [ + {file = "safety_schemas-0.0.2-py3-none-any.whl", hash = "sha256:277c077ce6e53221874a87c29515ffdd2f3773a6db4d035a9f67cc98db3b8c7f"}, + {file = "safety_schemas-0.0.2.tar.gz", hash = "sha256:7d1b040ec06480f05cff6b45ea7a93e09c8942df864fb0d01ddeb67c323cfa8c"}, +] + +[package.dependencies] +dparse = ">=0.6.4b0" +packaging = ">=21.0" +pydantic = "*" +ruamel-yaml = ">=0.17.21" +typing-extensions = ">=4.7.1" + +[[package]] +name = "segy" +version = "0.1.4" +description = "The Ultimate Python SEG-Y I/O with Cloud Support and Schemas" +optional = false +python-versions = "<3.13,>=3.9" files = [ - {file = "segyio-1.9.12-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:64ceafb9fe16d1ab59351a4a22dbb929698f88533a8dce1ce3b50d1a6a5c806a"}, - {file = "segyio-1.9.12-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3075beeaf2cb49eb723c6237feb78b5fddc6d1910a45e2afbf303e96b44239a2"}, - {file = "segyio-1.9.12-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6c5ba0365900a37c13b3dbf5e04b76c2fe1b7754e4db7d1e1d046ec9107f5b5"}, - {file = "segyio-1.9.12-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:576ee6fe3094e17b3da4177e8a31addbfd06095d89bab9290c41a307cfc89296"}, - {file = "segyio-1.9.12-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2f8f7c1a5ae8627c3133c9ba9ac2afab23ed1d97a010ac531bbf563c020c2bb7"}, - {file = "segyio-1.9.12-cp310-cp310-win32.whl", hash = "sha256:dcf184fdc716db341f1db4b5d9f1fd71a8ae8e8899481e7640c63524ee2f6633"}, - {file = "segyio-1.9.12-cp310-cp310-win_amd64.whl", hash = "sha256:e9123504d40c763e1ca36469186d90efa79f5989e9d7d8508c4a1c55450f0c8c"}, - {file = "segyio-1.9.12-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5ab879943ff8ece64af63e88f89037a6d5963da6f604a57c955bf33afda088ff"}, - {file = "segyio-1.9.12-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b52412f3512d6f09da2878c3c77fd4487f9679864b57c02896611af9a16c02a4"}, - {file = "segyio-1.9.12-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a1296145f8ff8ae14f35d3cdc225baaf53a6f891f7cb2021c1711c0cad0eea20"}, - {file = "segyio-1.9.12-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a814ff1a01939d92279859870b02cc9c24435b265568b2aef068b6a1fcc6f9fd"}, - {file = "segyio-1.9.12-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9495a7f47bd5f8a8ae134d3840191f49c366c8b8e48f2483fa350699047fcd14"}, - {file = "segyio-1.9.12-cp311-cp311-win32.whl", hash = "sha256:22430b55f17b727ed59926e36354d446abeb1c75490d510b44243e490f3b5381"}, - {file = "segyio-1.9.12-cp311-cp311-win_amd64.whl", hash = "sha256:cc5ce29a4d27e0a87c439be90664ebcf78fb0e366ea86a540a24720263bd35b5"}, - {file = "segyio-1.9.12-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a6017117d3ad280fc489b2f00a5981c729e43f362650cf835054289aba610a59"}, - {file = "segyio-1.9.12-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a7c6f6e55d01005dd2828035c6e02a0259dca76eadd35c35ba3206f6be00fc5"}, - {file = "segyio-1.9.12-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:17577df1865a7e1a03fe05836089e3493cf9f62a731bfab33ad437ef91b711db"}, - {file = "segyio-1.9.12-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85eb614cb6d5b293ad2c1537a082db8cd44b825a915c92868d6df3d29a5b911a"}, - {file = "segyio-1.9.12-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b2fc17fa50ff2828ef3d8764e2f2fe51bed1363a70399cd2bdcac37dffa1877f"}, - {file = "segyio-1.9.12-cp312-cp312-win32.whl", hash = "sha256:9fd86353710bd0bcdddeb5084f7bb6b05799e4222327caf3ef3f5bf966ee1456"}, - {file = "segyio-1.9.12-cp312-cp312-win_amd64.whl", hash = "sha256:050f70d180573530979b575863cb07a29de20f48a442aa126d817558d3dafb07"}, - {file = "segyio-1.9.12-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:951429218c5ac94a2aeeaac3e1270bff9a1e70bee3648432899b0363d9ec0ff5"}, - {file = "segyio-1.9.12-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e3634bea7e0a5adc1e9ab238d92236ea2cc74098a99a7ba184aeb916ac857142"}, - {file = "segyio-1.9.12-cp36-cp36m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0aaf1d6e6dea06351037c62f515289cf74bd4ea0bd9764c09880a9c2613fa404"}, - {file = "segyio-1.9.12-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1888972f847da5e79ef389654b8cd2f22156790416d8c7d29c8008df8c8e037"}, - {file = "segyio-1.9.12-cp36-cp36m-win32.whl", hash = "sha256:28fa62882fc22811d08688ca6f3a9718006bbc7587976c1146c07ca63799cfff"}, - {file = "segyio-1.9.12-cp36-cp36m-win_amd64.whl", hash = "sha256:ddac89eabf1785cfb3a033b16f5707351a420ef6016293de688fd24f5a31645d"}, - {file = "segyio-1.9.12-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5112cc5d2f0c8516ff79f3cfa27da50ad2f27fc4102ae5fa32b95ec6ea1ac6e4"}, - {file = "segyio-1.9.12-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:499cdd920ca985a438d33bcfa02d6fadc286d8f7671a901aa3bbd233f36a4de0"}, - {file = "segyio-1.9.12-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9c1ba43d1269aa82aa8e4cd52fd6364ff86dbd31f1d6cf365e3bc8a07cd739f2"}, - {file = "segyio-1.9.12-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f34a4cd610a4f61be0f4c68984972799dc12fadc7fa10ea4fa393b0529383e0c"}, - {file = "segyio-1.9.12-cp37-cp37m-win32.whl", hash = "sha256:f2df9e0e8c9dddbcf1e71b04127247ff50e26b60def02659c7636e7c57c495e7"}, - {file = "segyio-1.9.12-cp37-cp37m-win_amd64.whl", hash = "sha256:6e6eee893af39c76a71024309f21c31bf5b6ac3a84a04e9285b977cad72a5547"}, - {file = "segyio-1.9.12-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:389ef203a776e643e4da13aabe33b5d0dadd499a6309e33c87bd2aa8f12230ee"}, - {file = "segyio-1.9.12-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8620bf1ae507dfa4c48d596b4fe39e331a4b4bba19324efd796577c9bb311d8a"}, - {file = "segyio-1.9.12-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed85a6a19f9ff95a8b7b002e2815d944910b37748157b262a59f73ae166bd858"}, - {file = "segyio-1.9.12-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:03d617063df1e1ff4206405763494a6b2dbdde490bedb851a57a77adf11163a4"}, - {file = "segyio-1.9.12-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0eb0978f19f335d34da7bf14906141e776110f740299cebe02305c0149194064"}, - {file = "segyio-1.9.12-cp38-cp38-win32.whl", hash = "sha256:0a8cea8806f8bd7224fbeb503f1ce2e24f238ad95b20110bda76d39170b7e9f4"}, - {file = "segyio-1.9.12-cp38-cp38-win_amd64.whl", hash = "sha256:eeeaee3b385ac2fb7de6ef890414b9a2746ab17887e0e5c3f0cc2acb149a4020"}, - {file = "segyio-1.9.12-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9aec160892f9a8aa09ef1b87a03c9a4e49e9601711339541f2fe7fbf7c6ded07"}, - {file = "segyio-1.9.12-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:406f1155e94b9eced332e75efe83b4563333490780d06f882f347e5f74bb9bb4"}, - {file = "segyio-1.9.12-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b79b8d0278f070ec61c191ca7703b27100b93d78e1b92b3259873de927c4ada0"}, - {file = "segyio-1.9.12-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:15fb23b000a335a1878886600332a98dfe795d8cb79858961ee70ab07ae7dd46"}, - {file = "segyio-1.9.12-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a38ba0c61ff88d8ee1704a8b4bb4ad54513642311154d8b23d8959a8d43d7038"}, - {file = "segyio-1.9.12-cp39-cp39-win32.whl", hash = "sha256:91b1a1201bae0a703181fa2f0c9c610d32428da746b19e4248d1ba4fe8180bde"}, - {file = "segyio-1.9.12-cp39-cp39-win_amd64.whl", hash = "sha256:09cf6f6dae326be0970e96bbaf11fe33f9e5beeb156564f35e580e9c6e0fc701"}, -] - -[package.dependencies] -numpy = ">=1.10" + {file = "segy-0.1.4-py3-none-any.whl", hash = "sha256:3d66990459b653da57dadce56839d56a92c7829f44ae2b7814ca561531f6c716"}, + {file = "segy-0.1.4.tar.gz", hash = "sha256:5d14bf8740fcc1e941f7e4d54908db295382197939467c2436b2c59bcc2f0fd2"}, +] + +[package.dependencies] +bidict = ">=0.23.1,<0.24.0" +eval-type-backport = {version = ">=0.1.3,<0.2.0", markers = "python_version < \"3.10\""} +fsspec = ">=2024.6.0" +numba = ">=0.60.0,<0.61.0" +numpy = ">=1.26.4,<2.0.0" +pandas = ">=2.2.2,<3.0.0" +pydantic = ">=2.7.4,<3.0.0" +pydantic-settings = ">=2.3.3,<3.0.0" +rapidfuzz = ">=3.9.3,<4.0.0" +typer = ">=0.12.3,<0.13.0" + +[package.extras] +cloud = ["adlfs (>=2024.4.1)", "gcsfs (>=2024.6.0)", "s3fs (>=2024.6.0)"] [[package]] name = "setuptools" -version = "70.0.0" +version = "70.1.1" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-70.0.0-py3-none-any.whl", hash = "sha256:54faa7f2e8d2d11bcd2c07bed282eef1046b5c080d1c32add737d7b5817b1ad4"}, - {file = "setuptools-70.0.0.tar.gz", hash = "sha256:f211a66637b8fa059bb28183da127d4e86396c991a942b028c6650d4319c3fd0"}, + {file = "setuptools-70.1.1-py3-none-any.whl", hash = "sha256:a58a8fde0541dab0419750bcc521fbdf8585f6e5cb41909df3a472ef7b81ca95"}, + {file = "setuptools-70.1.1.tar.gz", hash = "sha256:937a48c7cdb7a21eb53cd7f9b59e525503aa8abaf3584c730dc5f7a5bec3a650"}, ] [package.extras] docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "mypy (==1.9)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.1)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "mypy (==1.10.0)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.1)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (>=0.3.2)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] + +[[package]] +name = "shellingham" +version = "1.5.4" +description = "Tool to Detect Surrounding Shell" +optional = false +python-versions = ">=3.7" +files = [ + {file = "shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686"}, + {file = "shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de"}, +] [[package]] name = "six" @@ -3198,6 +3529,17 @@ files = [ {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, ] +[[package]] +name = "sniffio" +version = "1.3.1" +description = "Sniff out which async library your code is running under" +optional = false +python-versions = ">=3.7" +files = [ + {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, + {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, +] + [[package]] name = "snowballstemmer" version = "2.2.0" @@ -3269,22 +3611,25 @@ test = ["cython (>=3.0)", "defusedxml (>=0.7.1)", "pytest (>=6.0)", "setuptools [[package]] name = "sphinx-autobuild" -version = "2021.3.14" -description = "Rebuild Sphinx documentation on changes, with live-reload in the browser." +version = "2024.4.16" +description = "Rebuild Sphinx documentation on changes, with hot reloading in the browser." optional = false -python-versions = ">=3.6" +python-versions = ">=3.9" files = [ - {file = "sphinx-autobuild-2021.3.14.tar.gz", hash = "sha256:de1ca3b66e271d2b5b5140c35034c89e47f263f2cd5db302c9217065f7443f05"}, - {file = "sphinx_autobuild-2021.3.14-py3-none-any.whl", hash = "sha256:8fe8cbfdb75db04475232f05187c776f46f6e9e04cacf1e49ce81bdac649ccac"}, + {file = "sphinx_autobuild-2024.4.16-py3-none-any.whl", hash = "sha256:f2522779d30fcbf0253e09714f274ce8c608cb6ebcd67922b1c54de59faba702"}, + {file = "sphinx_autobuild-2024.4.16.tar.gz", hash = "sha256:1c0ed37a1970eed197f9c5a66d65759e7c4e4cba7b5a5d77940752bf1a59f2c7"}, ] [package.dependencies] colorama = "*" -livereload = "*" sphinx = "*" +starlette = ">=0.35" +uvicorn = ">=0.25" +watchfiles = ">=0.20" +websockets = ">=11" [package.extras] -test = ["pytest", "pytest-cov"] +test = ["pytest (>=6)"] [[package]] name = "sphinx-basic-ng" @@ -3305,19 +3650,19 @@ docs = ["furo", "ipython", "myst-parser", "sphinx-copybutton", "sphinx-inline-ta [[package]] name = "sphinx-click" -version = "5.2.1" +version = "6.0.0" description = "Sphinx extension that automatically documents click applications" optional = false python-versions = ">=3.8" files = [ - {file = "sphinx_click-5.2.1-py3-none-any.whl", hash = "sha256:7aaa97bdce6fe315b3e719c085cd566e75470cbd91f1f6998b91213a09b8e7ec"}, - {file = "sphinx_click-5.2.1.tar.gz", hash = "sha256:a669773f76db05a3e04c163da91cd5e7db1a4761a6ea9eb074404a393094cde7"}, + {file = "sphinx_click-6.0.0-py3-none-any.whl", hash = "sha256:1e0a3c83bcb7c55497751b19d07ebe56b5d7b85eb76dd399cf9061b497adc317"}, + {file = "sphinx_click-6.0.0.tar.gz", hash = "sha256:f5d664321dc0c6622ff019f1e1c84e58ce0cecfddeb510e004cf60c2a3ab465b"}, ] [package.dependencies] -click = ">=7.0" +click = ">=8.0" docutils = "*" -sphinx = ">=2.0" +sphinx = ">=4.0" [[package]] name = "sphinx-copybutton" @@ -3431,6 +3776,24 @@ lint = ["docutils-stubs", "flake8", "mypy"] standalone = ["Sphinx (>=5)"] test = ["pytest"] +[[package]] +name = "starlette" +version = "0.37.2" +description = "The little ASGI library that shines." +optional = false +python-versions = ">=3.8" +files = [ + {file = "starlette-0.37.2-py3-none-any.whl", hash = "sha256:6fe59f29268538e5d0d182f2791a479a0c64638e6935d1c6989e63fb2699c6ee"}, + {file = "starlette-0.37.2.tar.gz", hash = "sha256:9af890290133b79fc3db55474ade20f6220a364a0402e0b556e7cd5e1e093823"}, +] + +[package.dependencies] +anyio = ">=3.4.0,<5" +typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} + +[package.extras] +full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.7)", "pyyaml"] + [[package]] name = "stevedore" version = "5.2.0" @@ -3491,22 +3854,22 @@ files = [ [[package]] name = "tornado" -version = "6.4" +version = "6.4.1" description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." -optional = false -python-versions = ">= 3.8" +optional = true +python-versions = ">=3.8" files = [ - {file = "tornado-6.4-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:02ccefc7d8211e5a7f9e8bc3f9e5b0ad6262ba2fbb683a6443ecc804e5224ce0"}, - {file = "tornado-6.4-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:27787de946a9cffd63ce5814c33f734c627a87072ec7eed71f7fc4417bb16263"}, - {file = "tornado-6.4-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7894c581ecdcf91666a0912f18ce5e757213999e183ebfc2c3fdbf4d5bd764e"}, - {file = "tornado-6.4-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e43bc2e5370a6a8e413e1e1cd0c91bedc5bd62a74a532371042a18ef19e10579"}, - {file = "tornado-6.4-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0251554cdd50b4b44362f73ad5ba7126fc5b2c2895cc62b14a1c2d7ea32f212"}, - {file = "tornado-6.4-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:fd03192e287fbd0899dd8f81c6fb9cbbc69194d2074b38f384cb6fa72b80e9c2"}, - {file = "tornado-6.4-cp38-abi3-musllinux_1_1_i686.whl", hash = "sha256:88b84956273fbd73420e6d4b8d5ccbe913c65d31351b4c004ae362eba06e1f78"}, - {file = "tornado-6.4-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:71ddfc23a0e03ef2df1c1397d859868d158c8276a0603b96cf86892bff58149f"}, - {file = "tornado-6.4-cp38-abi3-win32.whl", hash = "sha256:6f8a6c77900f5ae93d8b4ae1196472d0ccc2775cc1dfdc9e7727889145c45052"}, - {file = "tornado-6.4-cp38-abi3-win_amd64.whl", hash = "sha256:10aeaa8006333433da48dec9fe417877f8bcc21f48dda8d661ae79da357b2a63"}, - {file = "tornado-6.4.tar.gz", hash = "sha256:72291fa6e6bc84e626589f1c29d90a5a6d593ef5ae68052ee2ef000dfd273dee"}, + {file = "tornado-6.4.1-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:163b0aafc8e23d8cdc3c9dfb24c5368af84a81e3364745ccb4427669bf84aec8"}, + {file = "tornado-6.4.1-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:6d5ce3437e18a2b66fbadb183c1d3364fb03f2be71299e7d10dbeeb69f4b2a14"}, + {file = "tornado-6.4.1-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2e20b9113cd7293f164dc46fffb13535266e713cdb87bd2d15ddb336e96cfc4"}, + {file = "tornado-6.4.1-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ae50a504a740365267b2a8d1a90c9fbc86b780a39170feca9bcc1787ff80842"}, + {file = "tornado-6.4.1-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:613bf4ddf5c7a95509218b149b555621497a6cc0d46ac341b30bd9ec19eac7f3"}, + {file = "tornado-6.4.1-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:25486eb223babe3eed4b8aecbac33b37e3dd6d776bc730ca14e1bf93888b979f"}, + {file = "tornado-6.4.1-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:454db8a7ecfcf2ff6042dde58404164d969b6f5d58b926da15e6b23817950fc4"}, + {file = "tornado-6.4.1-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a02a08cc7a9314b006f653ce40483b9b3c12cda222d6a46d4ac63bb6c9057698"}, + {file = "tornado-6.4.1-cp38-abi3-win32.whl", hash = "sha256:d9a566c40b89757c9aa8e6f032bcdb8ca8795d7c1a9762910c722b1635c9de4d"}, + {file = "tornado-6.4.1-cp38-abi3-win_amd64.whl", hash = "sha256:b24b8982ed444378d7f21d563f4180a2de31ced9d8d84443907a0a64da2072e7"}, + {file = "tornado-6.4.1.tar.gz", hash = "sha256:92d3ab53183d8c50f8204a51e6f91d18a15d5ef261e84d452800d4ff6fc504e9"}, ] [[package]] @@ -3531,39 +3894,56 @@ telegram = ["requests"] [[package]] name = "typeguard" -version = "4.2.1" +version = "4.3.0" description = "Run-time type checker for Python" optional = false python-versions = ">=3.8" files = [ - {file = "typeguard-4.2.1-py3-none-any.whl", hash = "sha256:7da3bd46e61f03e0852f8d251dcbdc2a336aa495d7daff01e092b55327796eb8"}, - {file = "typeguard-4.2.1.tar.gz", hash = "sha256:c556a1b95948230510070ca53fa0341fb0964611bd05d598d87fb52115d65fee"}, + {file = "typeguard-4.3.0-py3-none-any.whl", hash = "sha256:4d24c5b39a117f8a895b9da7a9b3114f04eb63bade45a4492de49b175b6f7dfa"}, + {file = "typeguard-4.3.0.tar.gz", hash = "sha256:92ee6a0aec9135181eae6067ebd617fd9de8d75d714fb548728a4933b1dea651"}, ] [package.dependencies] importlib-metadata = {version = ">=3.6", markers = "python_version < \"3.10\""} -typing-extensions = {version = ">=4.10.0", markers = "python_version < \"3.13\""} +typing-extensions = ">=4.10.0" [package.extras] -doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)"] +doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme (>=1.3.0)"] test = ["coverage[toml] (>=7)", "mypy (>=1.2.0)", "pytest (>=7)"] +[[package]] +name = "typer" +version = "0.12.3" +description = "Typer, build great CLIs. Easy to code. Based on Python type hints." +optional = false +python-versions = ">=3.7" +files = [ + {file = "typer-0.12.3-py3-none-any.whl", hash = "sha256:070d7ca53f785acbccba8e7d28b08dcd88f79f1fbda035ade0aecec71ca5c914"}, + {file = "typer-0.12.3.tar.gz", hash = "sha256:49e73131481d804288ef62598d97a1ceef3058905aa536a1134f90891ba35482"}, +] + +[package.dependencies] +click = ">=8.0.0" +rich = ">=10.11.0" +shellingham = ">=1.3.0" +typing-extensions = ">=3.7.4.3" + [[package]] name = "typing-extensions" -version = "4.11.0" +version = "4.12.2" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" files = [ - {file = "typing_extensions-4.11.0-py3-none-any.whl", hash = "sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a"}, - {file = "typing_extensions-4.11.0.tar.gz", hash = "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0"}, + {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, + {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, ] [[package]] name = "tzdata" version = "2024.1" description = "Provider of IANA time zone data" -optional = true +optional = false python-versions = ">=2" files = [ {file = "tzdata-2024.1-py2.py3-none-any.whl", hash = "sha256:9068bc196136463f5245e51efda838afa15aaeca9903f49050dfa2679db4d252"}, @@ -3572,13 +3952,13 @@ files = [ [[package]] name = "urllib3" -version = "1.26.18" +version = "1.26.19" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" files = [ - {file = "urllib3-1.26.18-py2.py3-none-any.whl", hash = "sha256:34b97092d7e0a3a8cf7cd10e386f401b3737364026c45e622aa02903dffe0f07"}, - {file = "urllib3-1.26.18.tar.gz", hash = "sha256:f8ecc1bba5667413457c529ab955bf8c67b45db799d159066261719e328580a0"}, + {file = "urllib3-1.26.19-py2.py3-none-any.whl", hash = "sha256:37a0344459b199fce0e80b0d3569837ec6b6937435c5244e7fd73fa6006830f3"}, + {file = "urllib3-1.26.19.tar.gz", hash = "sha256:3e3d753a8618b86d7de333b4223005f68720bcd6a7d2bcb9fbd2229ec7c1e429"}, ] [package.extras] @@ -3586,6 +3966,25 @@ 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 = "uvicorn" +version = "0.30.1" +description = "The lightning-fast ASGI server." +optional = false +python-versions = ">=3.8" +files = [ + {file = "uvicorn-0.30.1-py3-none-any.whl", hash = "sha256:cd17daa7f3b9d7a24de3617820e634d0933b69eed8e33a516071174427238c81"}, + {file = "uvicorn-0.30.1.tar.gz", hash = "sha256:d46cd8e0fd80240baffbcd9ec1012a712938754afcf81bce56c024c1656aece8"}, +] + +[package.dependencies] +click = ">=7.0" +h11 = ">=0.8" +typing-extensions = {version = ">=4.0", markers = "python_version < \"3.11\""} + +[package.extras] +standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"] + [[package]] name = "validators" version = "0.22.0" @@ -3610,13 +4009,13 @@ tooling-extras = ["pyaml (>=23.7.0)", "pypandoc-binary (>=1.11)", "pytest (>=7.4 [[package]] name = "virtualenv" -version = "20.26.2" +version = "20.26.3" description = "Virtual Python Environment builder" optional = false python-versions = ">=3.7" files = [ - {file = "virtualenv-20.26.2-py3-none-any.whl", hash = "sha256:a624db5e94f01ad993d476b9ee5346fdf7b9de43ccaee0e0197012dc838a0e9b"}, - {file = "virtualenv-20.26.2.tar.gz", hash = "sha256:82bf0f4eebbb78d36ddaee0283d43fe5736b53880b8a8cdcd37390a07ac3741c"}, + {file = "virtualenv-20.26.3-py3-none-any.whl", hash = "sha256:8cc4a31139e796e9a7de2cd5cf2489de1217193116a8fd42328f1bd65f434589"}, + {file = "virtualenv-20.26.3.tar.gz", hash = "sha256:4c43a2a236279d9ea36a0d76f98d84bd6ca94ac4e0f4a3b9d46d05e10fea542a"}, ] [package.dependencies] @@ -3628,6 +4027,174 @@ platformdirs = ">=3.9.1,<5" docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"] +[[package]] +name = "watchfiles" +version = "0.22.0" +description = "Simple, modern and high performance file watching and code reload in python." +optional = false +python-versions = ">=3.8" +files = [ + {file = "watchfiles-0.22.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:da1e0a8caebf17976e2ffd00fa15f258e14749db5e014660f53114b676e68538"}, + {file = "watchfiles-0.22.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:61af9efa0733dc4ca462347becb82e8ef4945aba5135b1638bfc20fad64d4f0e"}, + {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d9188979a58a096b6f8090e816ccc3f255f137a009dd4bbec628e27696d67c1"}, + {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2bdadf6b90c099ca079d468f976fd50062905d61fae183f769637cb0f68ba59a"}, + {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:067dea90c43bf837d41e72e546196e674f68c23702d3ef80e4e816937b0a3ffd"}, + {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bbf8a20266136507abf88b0df2328e6a9a7c7309e8daff124dda3803306a9fdb"}, + {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1235c11510ea557fe21be5d0e354bae2c655a8ee6519c94617fe63e05bca4171"}, + {file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c2444dc7cb9d8cc5ab88ebe792a8d75709d96eeef47f4c8fccb6df7c7bc5be71"}, + {file = "watchfiles-0.22.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c5af2347d17ab0bd59366db8752d9e037982e259cacb2ba06f2c41c08af02c39"}, + {file = "watchfiles-0.22.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9624a68b96c878c10437199d9a8b7d7e542feddda8d5ecff58fdc8e67b460848"}, + {file = "watchfiles-0.22.0-cp310-none-win32.whl", hash = "sha256:4b9f2a128a32a2c273d63eb1fdbf49ad64852fc38d15b34eaa3f7ca2f0d2b797"}, + {file = "watchfiles-0.22.0-cp310-none-win_amd64.whl", hash = "sha256:2627a91e8110b8de2406d8b2474427c86f5a62bf7d9ab3654f541f319ef22bcb"}, + {file = "watchfiles-0.22.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8c39987a1397a877217be1ac0fb1d8b9f662c6077b90ff3de2c05f235e6a8f96"}, + {file = "watchfiles-0.22.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a927b3034d0672f62fb2ef7ea3c9fc76d063c4b15ea852d1db2dc75fe2c09696"}, + {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:052d668a167e9fc345c24203b104c313c86654dd6c0feb4b8a6dfc2462239249"}, + {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e45fb0d70dda1623a7045bd00c9e036e6f1f6a85e4ef2c8ae602b1dfadf7550"}, + {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c49b76a78c156979759d759339fb62eb0549515acfe4fd18bb151cc07366629c"}, + {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4a65474fd2b4c63e2c18ac67a0c6c66b82f4e73e2e4d940f837ed3d2fd9d4da"}, + {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1cc0cba54f47c660d9fa3218158b8963c517ed23bd9f45fe463f08262a4adae1"}, + {file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94ebe84a035993bb7668f58a0ebf998174fb723a39e4ef9fce95baabb42b787f"}, + {file = "watchfiles-0.22.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e0f0a874231e2839abbf473256efffe577d6ee2e3bfa5b540479e892e47c172d"}, + {file = "watchfiles-0.22.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:213792c2cd3150b903e6e7884d40660e0bcec4465e00563a5fc03f30ea9c166c"}, + {file = "watchfiles-0.22.0-cp311-none-win32.whl", hash = "sha256:b44b70850f0073b5fcc0b31ede8b4e736860d70e2dbf55701e05d3227a154a67"}, + {file = "watchfiles-0.22.0-cp311-none-win_amd64.whl", hash = "sha256:00f39592cdd124b4ec5ed0b1edfae091567c72c7da1487ae645426d1b0ffcad1"}, + {file = "watchfiles-0.22.0-cp311-none-win_arm64.whl", hash = "sha256:3218a6f908f6a276941422b035b511b6d0d8328edd89a53ae8c65be139073f84"}, + {file = "watchfiles-0.22.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:c7b978c384e29d6c7372209cbf421d82286a807bbcdeb315427687f8371c340a"}, + {file = "watchfiles-0.22.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bd4c06100bce70a20c4b81e599e5886cf504c9532951df65ad1133e508bf20be"}, + {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:425440e55cd735386ec7925f64d5dde392e69979d4c8459f6bb4e920210407f2"}, + {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:68fe0c4d22332d7ce53ad094622b27e67440dacefbaedd29e0794d26e247280c"}, + {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a8a31bfd98f846c3c284ba694c6365620b637debdd36e46e1859c897123aa232"}, + {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc2e8fe41f3cac0660197d95216c42910c2b7e9c70d48e6d84e22f577d106fc1"}, + {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55b7cc10261c2786c41d9207193a85c1db1b725cf87936df40972aab466179b6"}, + {file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28585744c931576e535860eaf3f2c0ec7deb68e3b9c5a85ca566d69d36d8dd27"}, + {file = "watchfiles-0.22.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:00095dd368f73f8f1c3a7982a9801190cc88a2f3582dd395b289294f8975172b"}, + {file = "watchfiles-0.22.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:52fc9b0dbf54d43301a19b236b4a4614e610605f95e8c3f0f65c3a456ffd7d35"}, + {file = "watchfiles-0.22.0-cp312-none-win32.whl", hash = "sha256:581f0a051ba7bafd03e17127735d92f4d286af941dacf94bcf823b101366249e"}, + {file = "watchfiles-0.22.0-cp312-none-win_amd64.whl", hash = "sha256:aec83c3ba24c723eac14225194b862af176d52292d271c98820199110e31141e"}, + {file = "watchfiles-0.22.0-cp312-none-win_arm64.whl", hash = "sha256:c668228833c5619f6618699a2c12be057711b0ea6396aeaece4ded94184304ea"}, + {file = "watchfiles-0.22.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d47e9ef1a94cc7a536039e46738e17cce058ac1593b2eccdede8bf72e45f372a"}, + {file = "watchfiles-0.22.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:28f393c1194b6eaadcdd8f941307fc9bbd7eb567995232c830f6aef38e8a6e88"}, + {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd64f3a4db121bc161644c9e10a9acdb836853155a108c2446db2f5ae1778c3d"}, + {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2abeb79209630da981f8ebca30a2c84b4c3516a214451bfc5f106723c5f45843"}, + {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4cc382083afba7918e32d5ef12321421ef43d685b9a67cc452a6e6e18920890e"}, + {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d048ad5d25b363ba1d19f92dcf29023988524bee6f9d952130b316c5802069cb"}, + {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:103622865599f8082f03af4214eaff90e2426edff5e8522c8f9e93dc17caee13"}, + {file = "watchfiles-0.22.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3e1f3cf81f1f823e7874ae563457828e940d75573c8fbf0ee66818c8b6a9099"}, + {file = "watchfiles-0.22.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8597b6f9dc410bdafc8bb362dac1cbc9b4684a8310e16b1ff5eee8725d13dcd6"}, + {file = "watchfiles-0.22.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0b04a2cbc30e110303baa6d3ddce8ca3664bc3403be0f0ad513d1843a41c97d1"}, + {file = "watchfiles-0.22.0-cp38-none-win32.whl", hash = "sha256:b610fb5e27825b570554d01cec427b6620ce9bd21ff8ab775fc3a32f28bba63e"}, + {file = "watchfiles-0.22.0-cp38-none-win_amd64.whl", hash = "sha256:fe82d13461418ca5e5a808a9e40f79c1879351fcaeddbede094028e74d836e86"}, + {file = "watchfiles-0.22.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:3973145235a38f73c61474d56ad6199124e7488822f3a4fc97c72009751ae3b0"}, + {file = "watchfiles-0.22.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:280a4afbc607cdfc9571b9904b03a478fc9f08bbeec382d648181c695648202f"}, + {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a0d883351a34c01bd53cfa75cd0292e3f7e268bacf2f9e33af4ecede7e21d1d"}, + {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9165bcab15f2b6d90eedc5c20a7f8a03156b3773e5fb06a790b54ccecdb73385"}, + {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc1b9b56f051209be458b87edb6856a449ad3f803315d87b2da4c93b43a6fe72"}, + {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8dc1fc25a1dedf2dd952909c8e5cb210791e5f2d9bc5e0e8ebc28dd42fed7562"}, + {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dc92d2d2706d2b862ce0568b24987eba51e17e14b79a1abcd2edc39e48e743c8"}, + {file = "watchfiles-0.22.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97b94e14b88409c58cdf4a8eaf0e67dfd3ece7e9ce7140ea6ff48b0407a593ec"}, + {file = "watchfiles-0.22.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:96eec15e5ea7c0b6eb5bfffe990fc7c6bd833acf7e26704eb18387fb2f5fd087"}, + {file = "watchfiles-0.22.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:28324d6b28bcb8d7c1041648d7b63be07a16db5510bea923fc80b91a2a6cbed6"}, + {file = "watchfiles-0.22.0-cp39-none-win32.whl", hash = "sha256:8c3e3675e6e39dc59b8fe5c914a19d30029e36e9f99468dddffd432d8a7b1c93"}, + {file = "watchfiles-0.22.0-cp39-none-win_amd64.whl", hash = "sha256:25c817ff2a86bc3de3ed2df1703e3d24ce03479b27bb4527c57e722f8554d971"}, + {file = "watchfiles-0.22.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b810a2c7878cbdecca12feae2c2ae8af59bea016a78bc353c184fa1e09f76b68"}, + {file = "watchfiles-0.22.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:f7e1f9c5d1160d03b93fc4b68a0aeb82fe25563e12fbcdc8507f8434ab6f823c"}, + {file = "watchfiles-0.22.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:030bc4e68d14bcad2294ff68c1ed87215fbd9a10d9dea74e7cfe8a17869785ab"}, + {file = "watchfiles-0.22.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ace7d060432acde5532e26863e897ee684780337afb775107c0a90ae8dbccfd2"}, + {file = "watchfiles-0.22.0-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5834e1f8b71476a26df97d121c0c0ed3549d869124ed2433e02491553cb468c2"}, + {file = "watchfiles-0.22.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:0bc3b2f93a140df6806c8467c7f51ed5e55a931b031b5c2d7ff6132292e803d6"}, + {file = "watchfiles-0.22.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8fdebb655bb1ba0122402352b0a4254812717a017d2dc49372a1d47e24073795"}, + {file = "watchfiles-0.22.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c8e0aa0e8cc2a43561e0184c0513e291ca891db13a269d8d47cb9841ced7c71"}, + {file = "watchfiles-0.22.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2f350cbaa4bb812314af5dab0eb8d538481e2e2279472890864547f3fe2281ed"}, + {file = "watchfiles-0.22.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7a74436c415843af2a769b36bf043b6ccbc0f8d784814ba3d42fc961cdb0a9dc"}, + {file = "watchfiles-0.22.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00ad0bcd399503a84cc688590cdffbe7a991691314dde5b57b3ed50a41319a31"}, + {file = "watchfiles-0.22.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72a44e9481afc7a5ee3291b09c419abab93b7e9c306c9ef9108cb76728ca58d2"}, + {file = "watchfiles-0.22.0.tar.gz", hash = "sha256:988e981aaab4f3955209e7e28c7794acdb690be1efa7f16f8ea5aba7ffdadacb"}, +] + +[package.dependencies] +anyio = ">=3.0.0" + +[[package]] +name = "websockets" +version = "12.0" +description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "websockets-12.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d554236b2a2006e0ce16315c16eaa0d628dab009c33b63ea03f41c6107958374"}, + {file = "websockets-12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2d225bb6886591b1746b17c0573e29804619c8f755b5598d875bb4235ea639be"}, + {file = "websockets-12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:eb809e816916a3b210bed3c82fb88eaf16e8afcf9c115ebb2bacede1797d2547"}, + {file = "websockets-12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c588f6abc13f78a67044c6b1273a99e1cf31038ad51815b3b016ce699f0d75c2"}, + {file = "websockets-12.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5aa9348186d79a5f232115ed3fa9020eab66d6c3437d72f9d2c8ac0c6858c558"}, + {file = "websockets-12.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6350b14a40c95ddd53e775dbdbbbc59b124a5c8ecd6fbb09c2e52029f7a9f480"}, + {file = "websockets-12.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:70ec754cc2a769bcd218ed8d7209055667b30860ffecb8633a834dde27d6307c"}, + {file = "websockets-12.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6e96f5ed1b83a8ddb07909b45bd94833b0710f738115751cdaa9da1fb0cb66e8"}, + {file = "websockets-12.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4d87be612cbef86f994178d5186add3d94e9f31cc3cb499a0482b866ec477603"}, + {file = "websockets-12.0-cp310-cp310-win32.whl", hash = "sha256:befe90632d66caaf72e8b2ed4d7f02b348913813c8b0a32fae1cc5fe3730902f"}, + {file = "websockets-12.0-cp310-cp310-win_amd64.whl", hash = "sha256:363f57ca8bc8576195d0540c648aa58ac18cf85b76ad5202b9f976918f4219cf"}, + {file = "websockets-12.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5d873c7de42dea355d73f170be0f23788cf3fa9f7bed718fd2830eefedce01b4"}, + {file = "websockets-12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3f61726cae9f65b872502ff3c1496abc93ffbe31b278455c418492016e2afc8f"}, + {file = "websockets-12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ed2fcf7a07334c77fc8a230755c2209223a7cc44fc27597729b8ef5425aa61a3"}, + {file = "websockets-12.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e332c210b14b57904869ca9f9bf4ca32f5427a03eeb625da9b616c85a3a506c"}, + {file = "websockets-12.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5693ef74233122f8ebab026817b1b37fe25c411ecfca084b29bc7d6efc548f45"}, + {file = "websockets-12.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e9e7db18b4539a29cc5ad8c8b252738a30e2b13f033c2d6e9d0549b45841c04"}, + {file = "websockets-12.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6e2df67b8014767d0f785baa98393725739287684b9f8d8a1001eb2839031447"}, + {file = "websockets-12.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:bea88d71630c5900690fcb03161ab18f8f244805c59e2e0dc4ffadae0a7ee0ca"}, + {file = "websockets-12.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dff6cdf35e31d1315790149fee351f9e52978130cef6c87c4b6c9b3baf78bc53"}, + {file = "websockets-12.0-cp311-cp311-win32.whl", hash = "sha256:3e3aa8c468af01d70332a382350ee95f6986db479ce7af14d5e81ec52aa2b402"}, + {file = "websockets-12.0-cp311-cp311-win_amd64.whl", hash = "sha256:25eb766c8ad27da0f79420b2af4b85d29914ba0edf69f547cc4f06ca6f1d403b"}, + {file = "websockets-12.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0e6e2711d5a8e6e482cacb927a49a3d432345dfe7dea8ace7b5790df5932e4df"}, + {file = "websockets-12.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:dbcf72a37f0b3316e993e13ecf32f10c0e1259c28ffd0a85cee26e8549595fbc"}, + {file = "websockets-12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12743ab88ab2af1d17dd4acb4645677cb7063ef4db93abffbf164218a5d54c6b"}, + {file = "websockets-12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b645f491f3c48d3f8a00d1fce07445fab7347fec54a3e65f0725d730d5b99cb"}, + {file = "websockets-12.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9893d1aa45a7f8b3bc4510f6ccf8db8c3b62120917af15e3de247f0780294b92"}, + {file = "websockets-12.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f38a7b376117ef7aff996e737583172bdf535932c9ca021746573bce40165ed"}, + {file = "websockets-12.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:f764ba54e33daf20e167915edc443b6f88956f37fb606449b4a5b10ba42235a5"}, + {file = "websockets-12.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:1e4b3f8ea6a9cfa8be8484c9221ec0257508e3a1ec43c36acdefb2a9c3b00aa2"}, + {file = "websockets-12.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9fdf06fd06c32205a07e47328ab49c40fc1407cdec801d698a7c41167ea45113"}, + {file = "websockets-12.0-cp312-cp312-win32.whl", hash = "sha256:baa386875b70cbd81798fa9f71be689c1bf484f65fd6fb08d051a0ee4e79924d"}, + {file = "websockets-12.0-cp312-cp312-win_amd64.whl", hash = "sha256:ae0a5da8f35a5be197f328d4727dbcfafa53d1824fac3d96cdd3a642fe09394f"}, + {file = "websockets-12.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5f6ffe2c6598f7f7207eef9a1228b6f5c818f9f4d53ee920aacd35cec8110438"}, + {file = "websockets-12.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9edf3fc590cc2ec20dc9d7a45108b5bbaf21c0d89f9fd3fd1685e223771dc0b2"}, + {file = "websockets-12.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8572132c7be52632201a35f5e08348137f658e5ffd21f51f94572ca6c05ea81d"}, + {file = "websockets-12.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:604428d1b87edbf02b233e2c207d7d528460fa978f9e391bd8aaf9c8311de137"}, + {file = "websockets-12.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1a9d160fd080c6285e202327aba140fc9a0d910b09e423afff4ae5cbbf1c7205"}, + {file = "websockets-12.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87b4aafed34653e465eb77b7c93ef058516cb5acf3eb21e42f33928616172def"}, + {file = "websockets-12.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b2ee7288b85959797970114deae81ab41b731f19ebcd3bd499ae9ca0e3f1d2c8"}, + {file = "websockets-12.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:7fa3d25e81bfe6a89718e9791128398a50dec6d57faf23770787ff441d851967"}, + {file = "websockets-12.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:a571f035a47212288e3b3519944f6bf4ac7bc7553243e41eac50dd48552b6df7"}, + {file = "websockets-12.0-cp38-cp38-win32.whl", hash = "sha256:3c6cc1360c10c17463aadd29dd3af332d4a1adaa8796f6b0e9f9df1fdb0bad62"}, + {file = "websockets-12.0-cp38-cp38-win_amd64.whl", hash = "sha256:1bf386089178ea69d720f8db6199a0504a406209a0fc23e603b27b300fdd6892"}, + {file = "websockets-12.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ab3d732ad50a4fbd04a4490ef08acd0517b6ae6b77eb967251f4c263011a990d"}, + {file = "websockets-12.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a1d9697f3337a89691e3bd8dc56dea45a6f6d975f92e7d5f773bc715c15dde28"}, + {file = "websockets-12.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1df2fbd2c8a98d38a66f5238484405b8d1d16f929bb7a33ed73e4801222a6f53"}, + {file = "websockets-12.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23509452b3bc38e3a057382c2e941d5ac2e01e251acce7adc74011d7d8de434c"}, + {file = "websockets-12.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e5fc14ec6ea568200ea4ef46545073da81900a2b67b3e666f04adf53ad452ec"}, + {file = "websockets-12.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46e71dbbd12850224243f5d2aeec90f0aaa0f2dde5aeeb8fc8df21e04d99eff9"}, + {file = "websockets-12.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b81f90dcc6c85a9b7f29873beb56c94c85d6f0dac2ea8b60d995bd18bf3e2aae"}, + {file = "websockets-12.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:a02413bc474feda2849c59ed2dfb2cddb4cd3d2f03a2fedec51d6e959d9b608b"}, + {file = "websockets-12.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bbe6013f9f791944ed31ca08b077e26249309639313fff132bfbf3ba105673b9"}, + {file = "websockets-12.0-cp39-cp39-win32.whl", hash = "sha256:cbe83a6bbdf207ff0541de01e11904827540aa069293696dd528a6640bd6a5f6"}, + {file = "websockets-12.0-cp39-cp39-win_amd64.whl", hash = "sha256:fc4e7fa5414512b481a2483775a8e8be7803a35b30ca805afa4998a84f9fd9e8"}, + {file = "websockets-12.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:248d8e2446e13c1d4326e0a6a4e9629cb13a11195051a73acf414812700badbd"}, + {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f44069528d45a933997a6fef143030d8ca8042f0dfaad753e2906398290e2870"}, + {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c4e37d36f0d19f0a4413d3e18c0d03d0c268ada2061868c1e6f5ab1a6d575077"}, + {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d829f975fc2e527a3ef2f9c8f25e553eb7bc779c6665e8e1d52aa22800bb38b"}, + {file = "websockets-12.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:2c71bd45a777433dd9113847af751aae36e448bc6b8c361a566cb043eda6ec30"}, + {file = "websockets-12.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0bee75f400895aef54157b36ed6d3b308fcab62e5260703add87f44cee9c82a6"}, + {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:423fc1ed29f7512fceb727e2d2aecb952c46aa34895e9ed96071821309951123"}, + {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27a5e9964ef509016759f2ef3f2c1e13f403725a5e6a1775555994966a66e931"}, + {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3181df4583c4d3994d31fb235dc681d2aaad744fbdbf94c4802485ececdecf2"}, + {file = "websockets-12.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:b067cb952ce8bf40115f6c19f478dc71c5e719b7fbaa511359795dfd9d1a6468"}, + {file = "websockets-12.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:00700340c6c7ab788f176d118775202aadea7602c5cc6be6ae127761c16d6b0b"}, + {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e469d01137942849cff40517c97a30a93ae79917752b34029f0ec72df6b46399"}, + {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffefa1374cd508d633646d51a8e9277763a9b78ae71324183693959cf94635a7"}, + {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba0cab91b3956dfa9f512147860783a1829a8d905ee218a9837c18f683239611"}, + {file = "websockets-12.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2cb388a5bfb56df4d9a406783b7f9dbefb888c09b71629351cc6b036e9259370"}, + {file = "websockets-12.0-py3-none-any.whl", hash = "sha256:dc284bbc8d7c78a6c69e0c7325ab46ee5e40bb4d50e494d8131a07ef47500e9e"}, + {file = "websockets-12.0.tar.gz", hash = "sha256:81df9cbcbb6c260de1e007e58c011bfebe2dafc8435107b0537f393dd38c8b1b"}, +] + [[package]] name = "wrapt" version = "1.16.0" @@ -3709,13 +4276,13 @@ files = [ [[package]] name = "xdoctest" -version = "1.1.3" +version = "1.1.5" description = "A rewrite of the builtin doctest module" optional = false python-versions = ">=3.6" files = [ - {file = "xdoctest-1.1.3-py3-none-any.whl", hash = "sha256:9360535bd1a971ffc216d9613898cedceb81d0fd024587cc3c03c74d14c00a31"}, - {file = "xdoctest-1.1.3.tar.gz", hash = "sha256:84e76a42a11a5926ff66d9d84c616bc101821099672550481ad96549cbdd02ae"}, + {file = "xdoctest-1.1.5-py3-none-any.whl", hash = "sha256:f36fe64d7c0ad0553dbff39ff05c43a0aab69d313466f24a38d00e757182ade0"}, + {file = "xdoctest-1.1.5.tar.gz", hash = "sha256:89b0c3ad7fe03a068e22a457ab18c38fc70c62329c2963f43954b83c29374e66"}, ] [package.dependencies] @@ -3736,13 +4303,13 @@ tests-strict = ["pytest (==4.6.0)", "pytest (==4.6.0)", "pytest (==6.2.5)", "pyt [[package]] name = "xyzservices" -version = "2024.4.0" +version = "2024.6.0" description = "Source of XYZ tiles providers" optional = true python-versions = ">=3.8" files = [ - {file = "xyzservices-2024.4.0-py3-none-any.whl", hash = "sha256:b83e48c5b776c9969fffcfff57b03d02b1b1cd6607a9d9c4e7f568b01ef47f4c"}, - {file = "xyzservices-2024.4.0.tar.gz", hash = "sha256:6a04f11487a6fb77d92a98984cd107fbd9157fd5e65f929add9c3d6e604ee88c"}, + {file = "xyzservices-2024.6.0-py3-none-any.whl", hash = "sha256:fecb2508f0f2b71c819aecf5df2c03cef001c56a4b49302e640f3b34710d25e4"}, + {file = "xyzservices-2024.6.0.tar.gz", hash = "sha256:58c1bdab4257d2551b9ef91cd48571f77b7c4d2bc45bf5e3c05ac97b3a4d7282"}, ] [[package]] @@ -3850,13 +4417,13 @@ multidict = ">=4.0" [[package]] name = "zarr" -version = "2.18.1" +version = "2.18.2" description = "An implementation of chunked, compressed, N-dimensional arrays for Python" optional = false python-versions = ">=3.9" files = [ - {file = "zarr-2.18.1-py3-none-any.whl", hash = "sha256:a1770d194eec4ec0a41a01295a6f724e1c3471d704d3aca906d3b3a7f8830245"}, - {file = "zarr-2.18.1.tar.gz", hash = "sha256:28c360ed123e606c425a694a83300227a907cb86a995fc9eef620ecafbe5f92d"}, + {file = "zarr-2.18.2-py3-none-any.whl", hash = "sha256:a638754902f97efa99b406083fdc807a0e2ccf12a949117389d2a4ba9b05df38"}, + {file = "zarr-2.18.2.tar.gz", hash = "sha256:9bb393b8a0a38fb121dbb913b047d75db28de9890f6d644a217a73cf4ae74f47"}, ] [package.dependencies] @@ -3922,18 +4489,18 @@ files = [ [[package]] name = "zipp" -version = "3.18.2" +version = "3.19.2" description = "Backport of pathlib-compatible object wrapper for zip files" optional = false python-versions = ">=3.8" files = [ - {file = "zipp-3.18.2-py3-none-any.whl", hash = "sha256:dce197b859eb796242b0622af1b8beb0a722d52aa2f57133ead08edd5bf5374e"}, - {file = "zipp-3.18.2.tar.gz", hash = "sha256:6278d9ddbcfb1f1089a88fde84481528b07b0e10474e09dcfe53dad4069fa059"}, + {file = "zipp-3.19.2-py3-none-any.whl", hash = "sha256:f091755f667055f2d02b32c53771a7a6c8b47e1fdbc4b72a8b9072b3eef8015c"}, + {file = "zipp-3.19.2.tar.gz", hash = "sha256:bf1dcf6450f873a13e952a29504887c89e6de7506209e5b1bcc3460135d4de19"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] [extras] cloud = ["adlfs", "gcsfs", "s3fs"] @@ -3943,4 +4510,4 @@ lossy = ["zfpy"] [metadata] lock-version = "2.0" python-versions = ">=3.9,<3.13" -content-hash = "d85fa9099c458a46c6351fbe69401d60612752f7e53e98aeeb41dde224553ac6" +content-hash = "252e55b9e1f03a229f289f30a01bef0722459b0dc84e5c4d8ffa80758978cfc6" diff --git a/pyproject.toml b/pyproject.toml index 46e63470..9e22645d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "multidimio" -version = "0.7.4" +version = "0.8.0" description = "Cloud-native, scalable, and user-friendly multi dimensional energy data!" authors = ["TGS "] maintainers = [ @@ -26,22 +26,21 @@ Changelog = "https://github.com/TGSAI/mdio-python/releases" python = ">=3.9,<3.13" click = "^8.1.7" click-params = "^0.5.0" -zarr = "^2.16.1" -dask = ">=2023.10.0" -tqdm = "^4.66.1" -segyio = "^1.9.3" -numba = "^0.59.1" -psutil = "^5.9.5" -fsspec = ">=2023.9.1" +zarr = "^2.18.2" +dask = ">=2024.6.1" +tqdm = "^4.66.4" +psutil = "^6.0.0" +fsspec = ">=2024.6.0" +segy = "^0.1.4" rich = "^13.7.1" urllib3 = "^1.26.18" # Workaround for poetry-plugin-export/issues/183 # Extras -distributed = {version = ">=2023.10.0", optional = true} -bokeh = {version = "^3.2.2", optional = true} -s3fs = {version = ">=2023.5.0", optional = true} -gcsfs = {version = ">=2023.5.0", optional = true} -adlfs = {version = ">=2023.4.0", optional = true} +distributed = {version = ">=2024.6.1", optional = true} +bokeh = {version = "^3.4.1", optional = true} +s3fs = {version = ">=2024.6.0", optional = true} +gcsfs = {version = ">=2024.6.0", optional = true} +adlfs = {version = ">=2024.4.1", optional = true} zfpy = {version = "^0.5.5", optional = true} [tool.poetry.extras] @@ -51,30 +50,31 @@ lossy = ["zfpy"] [tool.poetry.group.dev.dependencies] black = "^24.4.2" -coverage = {version = "^7.4.0", extras = ["toml"]} +coverage = {version = "^7.5.3", extras = ["toml"]} darglint = "^1.8.1" -flake8 = "^7.0.0" +flake8 = "^7.1.0" flake8-bandit = "^4.1.1" -flake8-bugbear = "^23.12.2" +flake8-bugbear = "^24.4.26" flake8-docstrings = "^1.7.0" flake8-rst-docstrings = "^0.3.0" -furo = ">=2023.9.10" +furo = ">=2024.5.6" isort = "^5.13.2" -mypy = "^1.8.0" -pep8-naming = "^0.13.3" -pre-commit = "^3.6.0" -pre-commit-hooks = "^4.5.0" -pytest = "^7.4.4" -pyupgrade = "^3.15.0" -safety = "^2.3.5" -sphinx-autobuild = "^2021.3.14" -sphinx-click = "^5.1.0" +mypy = "^1.10.0" +pep8-naming = "^0.14.1" +pre-commit = "^3.7.1" +pre-commit-hooks = "^4.6.0" +pytest = "^8.2.2" +pytest-dependency = "^0.6.0" +pyupgrade = "^3.16.0" +safety = "^3.2.3" +sphinx-autobuild = ">=2024.4.16" +sphinx-click = "^6.0.0" sphinx-copybutton = "^0.5.2" -typeguard = "^4.1.5" -xdoctest = {version = "^1.1.2", extras = ["colors"]} -myst-parser = "^2.0.0" -Pygments = "^2.17.2" -Sphinx = "^7.2.6" +typeguard = "^4.3.0" +xdoctest = {version = "^1.1.5", extras = ["colors"]} +myst-parser = "^3.0.1" +Pygments = "^2.18.0" +Sphinx = "^7.3.7" [tool.poetry.scripts] mdio = "mdio.__main__:main" diff --git a/src/mdio/commands/segy.py b/src/mdio/commands/segy.py index 5a98bb53..4692909a 100644 --- a/src/mdio/commands/segy.py +++ b/src/mdio/commands/segy.py @@ -96,16 +96,6 @@ help="Custom chunk size for bricked storage", type=IntListParamType(), ) -@option( - "-endian", - "--endian", - required=False, - default="big", - help="Endianness of the SEG-Y file", - type=Choice(["little", "big"]), - show_default=True, - show_choices=True, -) @option( "-lossless", "--lossless", @@ -152,7 +142,6 @@ def segy_import( header_types: list[str], header_names: list[str], chunk_size: list[int], - endian: str, lossless: bool, compression_tolerance: float, storage_options: dict[str, Any], @@ -356,7 +345,6 @@ def segy_import( index_types=header_types, index_names=header_names, chunksize=chunk_size, - endian=endian, lossless=lossless, compression_tolerance=compression_tolerance, storage_options=storage_options, @@ -377,16 +365,6 @@ def segy_import( type=STRING, show_default=True, ) -@option( - "-format", - "--segy-format", - required=False, - default="ibm32", - help="SEG-Y sample format", - type=Choice(["ibm32", "ieee32"]), - show_default=True, - show_choices=True, -) @option( "-storage", "--storage-options", @@ -408,7 +386,6 @@ def segy_export( mdio_file: str, segy_path: str, access_pattern: str, - segy_format: str, storage_options: dict[str, Any], endian: str, ): @@ -438,7 +415,6 @@ def segy_export( mdio_path_or_buffer=mdio_file, output_segy_path=segy_path, access_pattern=access_pattern, - out_sample_format=segy_format, storage_options=storage_options, endian=endian, ) diff --git a/src/mdio/converters/mdio.py b/src/mdio/converters/mdio.py index 9cd83661..2060eb64 100644 --- a/src/mdio/converters/mdio.py +++ b/src/mdio/converters/mdio.py @@ -12,8 +12,6 @@ from mdio import MDIOReader from mdio.segy.blocked_io import to_segy -from mdio.segy.byte_utils import ByteOrder -from mdio.segy.byte_utils import Dtype from mdio.segy.creation import concat_files from mdio.segy.creation import mdio_spec_to_segy from mdio.segy.utilities import segy_export_rechunker @@ -34,7 +32,6 @@ def mdio_to_segy( # noqa: C901 output_segy_path: str, endian: str = "big", access_pattern: str = "012", - out_sample_format: str = "ibm32", storage_options: dict = None, new_chunks: tuple[int, ...] = None, selection_mask: np.ndarray = None, @@ -65,8 +62,6 @@ def mdio_to_segy( # noqa: C901 endian. Default is 'big'. access_pattern: This specificies the chunk access pattern. Underlying zarr.Array must exist. Examples: '012', '01' - out_sample_format: Output sample format. - Currently support: {'ibm32', 'float32'}. Default is 'ibm32'. storage_options: Storage options for the cloud storage backend. Default: None (will assume anonymous access) new_chunks: Set manual chunksize. For development purposes only. @@ -99,7 +94,6 @@ def mdio_to_segy( # noqa: C901 ... mdio_path_or_buffer="prefix2/file.mdio", ... output_segy_path="prefix/file.segy", ... selection_mask=boolean_mask, - ... out_sample_format="float32", ... ) """ @@ -117,12 +111,10 @@ def mdio_to_segy( # noqa: C901 creation_args = [ mdio_path_or_buffer, output_segy_path, - endian, access_pattern, - out_sample_format, + endian, storage_options, new_chunks, - selection_mask, backend, ] @@ -130,12 +122,12 @@ def mdio_to_segy( # noqa: C901 if distributed is not None: # This is in case we work with big data feature = client.submit(mdio_spec_to_segy, *creation_args) - mdio, sample_format = feature.result() + mdio, segy_factory = feature.result() else: msg = "Distributed client was provided, but `distributed` is not installed" raise ImportError(msg) else: - mdio, sample_format = mdio_spec_to_segy(*creation_args) + mdio, segy_factory = mdio_spec_to_segy(*creation_args) live_mask = mdio.live_mask.compute() @@ -163,10 +155,6 @@ def mdio_to_segy( # noqa: C901 selection_mask = selection_mask[dim_slices] live_mask = live_mask & selection_mask - # Parse output type and byte order - out_dtype = Dtype[out_sample_format.upper()] - out_byteorder = ByteOrder[endian.upper()] - # tmp file root out_dir = path.dirname(output_segy_path) tmp_dir = TemporaryDirectory(dir=out_dir) @@ -177,8 +165,7 @@ def mdio_to_segy( # noqa: C901 samples=samples, headers=headers, live_mask=live_mask, - out_dtype=out_dtype, - out_byteorder=out_byteorder, + segy_factory=segy_factory, file_root=tmp_dir.name, axis=tuple(range(1, samples.ndim)), ) diff --git a/src/mdio/converters/segy.py b/src/mdio/converters/segy.py index 64ced345..d75d0fc7 100644 --- a/src/mdio/converters/segy.py +++ b/src/mdio/converters/segy.py @@ -11,8 +11,9 @@ from typing import Sequence import numpy as np -import segyio import zarr +from segy import SegyFile +from segy.schema import HeaderField from mdio.api.io_utils import process_url from mdio.converters.exceptions import EnvironmentFormatError @@ -21,10 +22,8 @@ from mdio.core import Grid from mdio.core.utils_write import write_attribute from mdio.segy import blocked_io -from mdio.segy.byte_utils import Dtype +from mdio.segy.compat import mdio_segy_spec from mdio.segy.helpers_segy import create_zarr_hierarchy -from mdio.segy.parsers import parse_binary_header -from mdio.segy.parsers import parse_text_header from mdio.segy.utilities import get_grid_plan @@ -38,25 +37,6 @@ BACKENDS = ["s3", "gcs", "gs", "az", "abfs"] -def parse_index_types( - str_types: Sequence[str] | None, num_index: int -) -> Sequence[Dtype]: - """Convert string type keys to Dtype enums.""" - if str_types is None: - parsed_types = [Dtype.INT32] * num_index - else: - try: - parsed_types = [Dtype[_type.upper()] for _type in str_types] - except KeyError as exc: - msg = ( - "Unsupported header data-type. 'index_types' must be in " - f"{list(Dtype.__members__.keys())}" - ) - raise KeyError(msg) from exc - - return parsed_types - - def grid_density_qc(grid: Grid, num_traces: int) -> None: """QC for sensible Grid density. @@ -124,14 +104,13 @@ def grid_density_qc(grid: Grid, num_traces: int) -> None: raise GridTraceSparsityError(grid.shape, num_traces, msg) -def segy_to_mdio( +def segy_to_mdio( # noqa: C901 segy_path: str, mdio_path_or_buffer: str, index_bytes: Sequence[int], index_names: Sequence[str] | None = None, index_types: Sequence[str] | None = None, chunksize: Sequence[int] | None = None, - endian: str = "big", lossless: bool = True, compression_tolerance: float = 0.01, storage_options: dict[str, Any] | None = None, @@ -180,8 +159,6 @@ def segy_to_mdio( Default is 4-byte integers for each index key. chunksize : Override default chunk size, which is (64, 64, 64) if 3D, and (512, 512) for 2D. - endian: Endianness of the input SEG-Y. Rev.2 allows little endian. - Default is 'big'. Must be in `{"big", "little"}` lossless: Lossless Blosc with zstandard, or ZFP with fixed precision. compression_tolerance: Tolerance ZFP compression, optional. The fixed accuracy mode in ZFP guarantees there won't be any errors larger @@ -364,7 +341,11 @@ def segy_to_mdio( ... grid_overrides={"HasDuplicates": True}, ... ) """ - num_index = len(index_bytes) + if index_names is None: + index_names = [f"dim_{i}" for i in range(len(index_bytes))] + + if index_types is None: + index_types = ["int32"] * len(index_bytes) if chunksize is not None: if len(chunksize) != len(index_bytes) + 1: @@ -385,33 +366,30 @@ def segy_to_mdio( disk_cache=False, # Making sure disk caching is disabled ) - # Read file specific metadata, build grid, and live trace mask. - with segyio.open( - filename=segy_path, mode="r", ignore_geometry=True, endian=endian - ) as segy_handle: - text_header = parse_text_header(segy_handle) - binary_header = parse_binary_header(segy_handle) - num_traces = segy_handle.tracecount + # Open SEG-Y with MDIO's SegySpec. Endianness will be inferred. + mdio_spec = mdio_segy_spec() + segy = SegyFile(url=segy_path, spec=mdio_spec) + + text_header = segy.text_header + binary_header = segy.binary_header + num_traces = segy.num_traces - index_types = parse_index_types(index_types, num_index) + # Index the dataset using a spec that interprets the user provided index headers. + index_fields = [] + # TODO: Add strict=True and remove noqa when minimum Python is 3.10 + for name, byte, format_ in zip(index_names, index_bytes, index_types): # noqa: B905 + index_fields.append(HeaderField(name=name, byte=byte, format=format_)) + mdio_spec_grid = mdio_spec.customize(trace_header_fields=index_fields) + segy_grid = SegyFile(url=segy_path, spec=mdio_spec_grid) dimensions, chunksize, index_headers = get_grid_plan( - segy_path=segy_path, - segy_endian=endian, - index_bytes=index_bytes, - index_names=index_names, - index_types=index_types, - binary_header=binary_header, + segy_file=segy_grid, return_headers=True, chunksize=chunksize, grid_overrides=grid_overrides, ) - - # Make grid and build global live trace mask grid = Grid(dims=dimensions) - grid_density_qc(grid, num_traces) - grid.build_map(index_headers) # Check grid validity by comparing trace numbers @@ -452,17 +430,17 @@ def segy_to_mdio( write_attribute( name="text_header", zarr_group=zarr_root["metadata"], - attribute=text_header, + attribute=text_header.split("\n"), ) write_attribute( name="binary_header", zarr_group=zarr_root["metadata"], - attribute=binary_header, + attribute=binary_header.to_dict(), ) if chunksize is None: - dim_count = len(index_headers) + 1 + dim_count = len(index_names) + 1 if dim_count == 2: chunksize = (512,) * 2 @@ -484,8 +462,7 @@ def segy_to_mdio( suffix = "".join(suffix) stats = blocked_io.to_zarr( - segy_path=segy_path, - segy_endian=endian, + segy_file=segy, grid=grid, data_root=zarr_root["data"], metadata_root=zarr_root["metadata"], diff --git a/src/mdio/segy/_standards_common.py b/src/mdio/segy/_standards_common.py deleted file mode 100644 index 74b2fbe0..00000000 --- a/src/mdio/segy/_standards_common.py +++ /dev/null @@ -1,37 +0,0 @@ -"""Common elements for SEG-Y standards datasets.""" - -from enum import IntEnum - - -class SegyFloatFormat(IntEnum): - """Numeric type to SEG-Y code mapping.""" - - IBM32 = 1 - INT32 = 2 - INT16 = 3 - FLOAT32 = 5 - FLOAT64 = 6 - INT8 = 8 - INT64 = 9 - UINT32 = 10 - UINT16 = 11 - UINT64 = 12 - UINT8 = 16 - - -class TraceSortingCode(IntEnum): - """Data sorting type to SEG-Y code mapping.""" - - NO_SORTING = 1 - CDP_ENSEMBLE = 2 - SINGLE_FOLD = 3 - HORZ_STACKED = 4 - - -class SweepTypeCode(IntEnum): - """Sweep type to SEG-Y code mapping.""" - - LINEAR = 1 - PARABOLIC = 2 - EXPONENTIAL = 3 - OTHER = 4 diff --git a/src/mdio/segy/_standards_rev0.py b/src/mdio/segy/_standards_rev0.py deleted file mode 100644 index e0d3bf26..00000000 --- a/src/mdio/segy/_standards_rev0.py +++ /dev/null @@ -1,124 +0,0 @@ -"""SEG-Y Rev 0 standard and its definitions.""" - -from mdio.segy.byte_utils import ByteOrder -from mdio.segy.byte_utils import Dtype -from mdio.segy.byte_utils import OrderedType -from mdio.segy.headers import Header -from mdio.segy.headers import HeaderGroup - - -SEGY_REV0_TEXT = {"rows": 40, "cols": 80, "word_length": 4} - -# fmt: off -SEGY_REV0_BINARY_HEADER = [ - Header(name="JobIdentificationNumber", offset=0, type=Dtype.INT32, endian=ByteOrder.BIG), - Header(name="LineNumber", offset=4, type=Dtype.INT32, endian=ByteOrder.BIG), - Header(name="ReelNumber", offset=8, type=Dtype.INT32, endian=ByteOrder.BIG), - Header(name="NumTracesPerRecord", offset=12, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="NumAuxTracesPerRecord", offset=14, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="SampleRate", offset=16, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="SampleRateOriginal", offset=18, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="NumSamples", offset=20, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="NumSamplesOriginal", offset=22, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="SampleFormat", offset=24, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="CdpFold", offset=26, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="Sorting", offset=28, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="VerticalSum", offset=30, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="SweepFreqStart", offset=32, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="SweepFreqEnd", offset=34, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="SweepLength", offset=36, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="SweepType", offset=38, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="SweepTraceNumber", offset=40, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="SweepTaperStartLen", offset=42, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="SweepTaperEndLen", offset=44, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="SweepTaperType", offset=46, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="Correlated", offset=48, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="BinaryGainRecovered", offset=50, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="AmplitudeRecoveryMethod", offset=52, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="MeasurementSystem", offset=54, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="ImpulseSignal", offset=56, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="VibratorPolarity", offset=58, type=Dtype.INT16, endian=ByteOrder.BIG), -] # fmt: on - -# fmt: off -SEGY_REV0_TRACE_HEADER = [ - Header(name="TraceSequenceNumberLine", offset=0, type=Dtype.INT32, endian=ByteOrder.BIG), - Header(name="TraceSequenceNumberReel", offset=4, type=Dtype.INT32, endian=ByteOrder.BIG), - Header(name="OriginalFieldRecordNumber", offset=8, type=Dtype.INT32, endian=ByteOrder.BIG), - Header(name="TraceNumberOriginalFieldRecord", offset=12, type=Dtype.INT32, endian=ByteOrder.BIG), - Header(name="EnergySourcePointNumber", offset=16, type=Dtype.INT32, endian=ByteOrder.BIG), - Header(name="CdpEnsembleNumber", offset=20, type=Dtype.INT32, endian=ByteOrder.BIG), - Header(name="TraceNumberWithinCdp", offset=24, type=Dtype.INT32, endian=ByteOrder.BIG), - Header(name="TraceIdentification", offset=28, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="NumVerticallySummedTraces", offset=30, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="NumHorizontallyStackedTraces", offset=32, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="DataUse", offset=34, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="SourceReceiverDistance", offset=36, type=Dtype.INT32, endian=ByteOrder.BIG), - Header(name="ReceiverGroupElevation", offset=40, type=Dtype.INT32, endian=ByteOrder.BIG), - Header(name="SourceElevation", offset=44, type=Dtype.INT32, endian=ByteOrder.BIG), - Header(name="SourceDepth", offset=48, type=Dtype.INT32, endian=ByteOrder.BIG), - Header(name="ReceiverDatumElevation", offset=52, type=Dtype.INT32, endian=ByteOrder.BIG), - Header(name="SourceDatumElevation", offset=56, type=Dtype.INT32, endian=ByteOrder.BIG), - Header(name="SourceWaterDepth", offset=60, type=Dtype.INT32, endian=ByteOrder.BIG), - Header(name="ReceiverGroupWaterDepth", offset=64, type=Dtype.INT32, endian=ByteOrder.BIG), - Header(name="ScalerElevationDepth", offset=68, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="ScalerCoordinates", offset=70, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="SourceCoordinateX", offset=72, type=Dtype.INT32, endian=ByteOrder.BIG), - Header(name="SourceCoordinateY", offset=76, type=Dtype.INT32, endian=ByteOrder.BIG), - Header(name="GroupCoordinateX", offset=80, type=Dtype.INT32, endian=ByteOrder.BIG), - Header(name="GroupCoordinateY", offset=84, type=Dtype.INT32, endian=ByteOrder.BIG), - Header(name="CoordinateUnits", offset=88, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="WeatheringVelocity", offset=90, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="SubWeatheringVelocity", offset=92, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="SourceUpholeTime", offset=94, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="GroupUpholeTime", offset=96, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="SourceStaticCorrection", offset=98, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="GroupStaticCorrection", offset=100, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="TotalStatic", offset=102, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="LagTimeA", offset=104, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="LagTimeB", offset=106, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="DelayRecordingTime", offset=108, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="BruteTimeStart", offset=110, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="MuteTimeEnd", offset=112, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="SampleRateTrace", offset=114, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="NumSamplesTrace", offset=116, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="GainTypeField", offset=118, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="InstrumentGainConst", offset=120, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="InstrumentInitGain", offset=122, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="Correlated", offset=124, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="SweepFreqStart", offset=126, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="SweepFreqEnd", offset=128, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="SweepLength", offset=130, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="SweepType", offset=132, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="SweepTaperStartLen", offset=134, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="SweepTaperEndLen", offset=136, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="SweepTaperType", offset=138, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="AliasFilterFreq", offset=140, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="AliasFilterSlope", offset=142, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="NotchFilterFreq", offset=144, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="NotchFilterSlope", offset=146, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="LowCutFreq", offset=148, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="HighCutFreq", offset=150, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="LowCutSlope", offset=152, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="HighCutSlope", offset=154, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="Year", offset=156, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="Day", offset=158, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="Hour", offset=160, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="Minute", offset=162, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="Second", offset=164, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="TimeBasis", offset=166, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="TraceWeightingFactor", offset=168, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="GeophoneGroupNumberOfRoll", offset=170, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="GroupNumberOfFirstTrace", offset=172, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="GroupNumberOfLastTrace", offset=174, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="GapSize", offset=176, type=Dtype.INT16, endian=ByteOrder.BIG), - Header(name="OvertravelTaper", offset=178, type=Dtype.INT16, endian=ByteOrder.BIG), -] # fmt: on - -# fmt: off -SEGY_REV0 = { - "text_header": SEGY_REV0_TEXT, - "binary_header": HeaderGroup(name='BinaryHeader', offset=3200, itemsize=400, headers=SEGY_REV0_BINARY_HEADER), - "trace_header": HeaderGroup(name='TraceHeader', offset=3600, itemsize=240, headers=SEGY_REV0_TRACE_HEADER), - "trace_format": OrderedType(Dtype.IBM32, ByteOrder.BIG), -} # fmt: on diff --git a/src/mdio/segy/_workers.py b/src/mdio/segy/_workers.py index 4b61b5d5..9e3da566 100644 --- a/src/mdio/segy/_workers.py +++ b/src/mdio/segy/_workers.py @@ -2,29 +2,24 @@ from __future__ import annotations +from typing import TYPE_CHECKING from typing import Any -from typing import Sequence import numpy as np -import segyio -from numpy.typing import ArrayLike -from zarr import Array -from mdio.constants import UINT32_MAX -from mdio.core import Grid -from mdio.segy.byte_utils import ByteOrder -from mdio.segy.byte_utils import Dtype -from mdio.segy.ibm_float import ibm2ieee + +if TYPE_CHECKING: + from segy import SegyFile + from segy.arrays import HeaderArray + from zarr import Array + + from mdio.core import Grid def header_scan_worker( - segy_path_or_handle: str | segyio.SegyFile, - trace_range: Sequence[int], - byte_locs: Sequence[int], - byte_types: Sequence[Dtype], - index_names: Sequence[str], - segy_endian: str, -) -> dict[str, ArrayLike]: + segy_file: SegyFile, + trace_range: tuple[int, int], +) -> HeaderArray: """Header scan worker. Can accept file path or segyio.SegyFile. @@ -36,111 +31,21 @@ def header_scan_worker( that was opened in a different context manager. Args: - segy_path_or_handle: Path or handle to the input SEG-Y file - byte_locs: Byte locations to return. It will be a subset of the headers. - byte_types: Tuple consisting of the data types for the index attributes. - trace_range: Tuple consisting of the trace ranges to read - index_names: Tuple of the names for the index attributes - segy_endian: Endianness of the input SEG-Y. Rev.2 allows little endian + segy_file: SegyFile instance. + trace_range: Tuple consisting of the trace ranges to read. Returns: - dictionary with headers: keys are the index names, values are numpy - arrays of parsed headers for the current block. Array is of type - byte_type with the exception of IBM32 which is mapped to FLOAT32. - - Raises: - TypeError: if segy_path_or_handle is incorrect / unsupported. + HeaderArray parsed from SEG-Y library. """ - start, stop = trace_range - - if isinstance(segy_path_or_handle, str): - with segyio.open( - filename=segy_path_or_handle, - mode="r", - ignore_geometry=True, - endian=segy_endian, - ) as segy_handle: - block_headers = [ - segy_handle.header[trc_idx] for trc_idx in range(start, stop) - ] - - elif isinstance(segy_path_or_handle, segyio.SegyFile): - block_headers = [ - segy_path_or_handle.header[trc_idx] for trc_idx in range(start, stop) - ] - - else: - raise TypeError("Unsupported type for segy_path_or_handle") - - # We keep only the ones we want here (if there is a subset). - # Sometimes we have custom header locations that are not SEG-Y Std Rev 1. - # In this case we can't use segyio's byte unpacking anymore. - # First we create a struct to unpack the 240-byte trace headers. - # The struct only knows about dimension keys, and their byte offsets. - # Pads the rest of the data with voids. - # NOTE: segyio buffer is always big endian. This is why we force it here. - # This used to be the same as `segy_endian` but we hard code it to big. - endian = ByteOrder.BIG - - # Handle byte offsets - offsets = [0 if byte_loc is None else byte_loc - 1 for byte_loc in byte_locs] - formats = [type_.numpy_dtype.newbyteorder(endian) for type_ in byte_types] - - struct_dtype = np.dtype( - { - "names": index_names, - "formats": formats, - "offsets": offsets, - "itemsize": 240, - } - ) - - # Then for each trace header, we take the unpacked byte buffer from segyio - # and join them into one byte array. Then we use numpy's frombuffer() to unpack - block_headers = b"".join([trace_headers.buf for trace_headers in block_headers]) - n_traces = stop - start - block_headers = np.frombuffer(block_headers, struct_dtype, count=n_traces) - block_headers = {name: block_headers[name] for name in index_names} - - out_dtype = [] - for name, type_ in zip(index_names, byte_types): # noqa: B905 - if type_ == Dtype.IBM32: - native_dtype = Dtype.FLOAT32.numpy_dtype - else: - native_dtype = type_.numpy_dtype - - out_dtype.append((name, native_dtype)) - - # out_array = np.empty(n_traces, out_dtype) - out_array = {} - - # TODO: Add strict=True and remove noqa when minimum Python is 3.10 - for name, loc, type_ in zip(index_names, byte_locs, byte_types): # noqa: B905 - # Handle exception when a byte_loc is None - if loc is None: - out_array[name] = 0 - del block_headers[name] - continue - - header = block_headers[name] - - if type_ == Dtype.IBM32: - header = ibm2ieee(header) - - out_array[name] = header - - del block_headers[name] - - return out_array + return segy_file.header[slice(*trace_range)] def trace_worker( - segy_path: str, + segy_file: SegyFile, data_array: Array, metadata_array: Array, grid: Grid, chunk_indices: tuple[slice, ...], - segy_endian: str, ) -> tuple[Any, ...] | None: """Worker function for multi-process enabled blocked SEG-Y I/O. @@ -156,23 +61,21 @@ def trace_worker( worry about it. Args: - segy_path: Path to the input SEG-Y file + segy_file: SegyFile instance. data_array: Handle for zarr.Array we are writing traces to metadata_array: Handle for zarr.Array we are writing trace headers grid: mdio.Grid instance chunk_indices: Tuple consisting of the chunk slice indices for each dimension - segy_endian: Endianness of the input SEG-Y. Rev.2 allows little endian Returns: Partial statistics for chunk, or None - """ # Special case where there are no traces inside chunk. live_subset = grid.live_mask[chunk_indices[:-1]] - n_dim = grid.ndim + if np.count_nonzero(live_subset) == 0: - return + return None # Let's get trace numbers from grid map using the chunk indices. seq_trace_indices = grid.map[chunk_indices[:-1]] @@ -180,27 +83,19 @@ def trace_worker( tmp_data = np.zeros( seq_trace_indices.shape + (grid.shape[-1],), dtype=data_array.dtype ) + tmp_metadata = np.zeros(seq_trace_indices.shape, dtype=metadata_array.dtype) del grid # To save some memory # Read headers and traces for block - with segyio.open( - filename=segy_path, mode="r", ignore_geometry=True, endian=segy_endian - ) as segy_handle: - # Here we utilize ndenumerate so it is dimension agnostic! - # We don't have to write custom implementations (nested loops) for each case. - for index, trace_num in np.ndenumerate(seq_trace_indices): - # We check if the trace is "valid" or "live" - # 4294967295 is our NULL value. uint32 equivalent of -1. (max uint32) - if trace_num == UINT32_MAX: - continue - - # Read header and trace - # We tested trace vs trace.raw on a single trace - # They are the same performance. Keeping the lazy version here. - tmp_metadata[index] = tuple(segy_handle.header[trace_num].values()) - tmp_data[index] = segy_handle.trace[trace_num] + valid_indices = seq_trace_indices[live_subset] + + traces = segy_file.trace[valid_indices.tolist()] + headers, samples = traces["header"], traces["data"] + + tmp_metadata[live_subset] = headers.view(tmp_metadata.dtype) + tmp_data[live_subset] = samples # Flush metadata to zarr metadata_array.set_basic_selection( @@ -208,32 +103,22 @@ def trace_worker( value=tmp_metadata, ) - # Find first non-zero index in sample (last) dimension - non_sample_axes = tuple(range(n_dim - 1)) - nonzero_z = np.where(np.any(tmp_data != 0, axis=non_sample_axes)) + nonzero_mask = samples != 0 + nonzero_count = nonzero_mask.sum(dtype="uint32") - if len(nonzero_z[0]) == 0: - return + if nonzero_count == 0: + return None - dimn_start = np.min(nonzero_z) - dimn_end = np.max(nonzero_z) + 1 - - z_slice = slice(dimn_start, dimn_end) - # We write if there are any values - chunk_indices = chunk_indices[:-1] + (z_slice,) data_array.set_basic_selection( selection=chunk_indices, - value=tmp_data[..., z_slice], + value=tmp_data, ) # Calculate statistics - nonzero_mask = tmp_data != 0 - count = nonzero_mask.sum(dtype="uint32") - - tmp_data = tmp_data[nonzero_mask] + tmp_data = samples[nonzero_mask] chunk_sum = tmp_data.sum(dtype="float64") chunk_sum_squares = np.square(tmp_data, dtype="float64").sum() min_val = tmp_data.min() max_val = tmp_data.max() - return count, chunk_sum, chunk_sum_squares, min_val, max_val + return nonzero_count, chunk_sum, chunk_sum_squares, min_val, max_val diff --git a/src/mdio/segy/blocked_io.py b/src/mdio/segy/blocked_io.py index bc6d1aab..0c10d7f8 100644 --- a/src/mdio/segy/blocked_io.py +++ b/src/mdio/segy/blocked_io.py @@ -6,14 +6,13 @@ import os from concurrent.futures import ProcessPoolExecutor from itertools import repeat +from typing import TYPE_CHECKING import numpy as np from dask.array import Array from dask.array import blockwise from dask.array.reductions import _tree_reduce -from numpy.typing import NDArray from psutil import cpu_count -from segyio.tracefield import keys as segy_hdr_keys from tqdm.auto import tqdm from zarr import Blosc from zarr import Group @@ -21,12 +20,15 @@ from mdio.core import Grid from mdio.core.indexing import ChunkIterator from mdio.segy._workers import trace_worker -from mdio.segy.byte_utils import ByteOrder -from mdio.segy.byte_utils import Dtype from mdio.segy.creation import concat_files from mdio.segy.creation import write_to_segy_stack +if TYPE_CHECKING: + from numpy.typing import NDArray + from segy import SegyFactory + from segy import SegyFile + try: import zfpy # Base library from zarr import ZFPY # Codec @@ -40,8 +42,7 @@ def to_zarr( - segy_path: str, - segy_endian: str, + segy_file: SegyFile, grid: Grid, data_root: Group, metadata_root: Group, @@ -54,8 +55,7 @@ def to_zarr( """Blocked I/O from SEG-Y to chunked `zarr.core.Array`. Args: - segy_path: Path to the input SEG-Y file - segy_endian: Endianness of the input SEG-Y. + segy_file: SEG-Y file instance. grid: mdio.Grid instance data_root: Handle for zarr.core.Group we are writing traces metadata_root: Handle for zarr.core.Group we are writing trace headers @@ -96,30 +96,12 @@ def to_zarr( compressor=trace_compressor, chunks=chunks, dimension_separator="/", + write_empty_chunks=False, **kwargs, ) - # Here we read the byte locations of the rev.1 SEG-Y standard as defined in segyio - # We skip the last two, because segyio doesn't read it when we ask for traces - rev1_bytes = list(segy_hdr_keys.values())[:-2] - - # Then we diff the byte locations to get lengths of headers. Last one has to be - # manually added because it is forward diff. - header_byte_loc = list(map(str, rev1_bytes)) - header_byte_len = [ - rev1_bytes[idx + 1] - rev1_bytes[idx] for idx in range(len(header_byte_loc) - 1) - ] - header_byte_len += [2] # Length of last TraceField (SourceMeasurementUnit) - - # Make numpy.dtype - # We assume either 16-bit or 32-bit signed integers (per SEG-Y standard). - # In numpy these are 'i2' (aka 'int16') or 'i4' (aka 'int32') - header_dtype = { - "names": header_byte_loc, - "formats": [f"i{length}" for length in header_byte_len], - } - header_dtype = np.dtype(header_dtype) - + # Get header dtype in native order (little-endian 99.9% of the time) + header_dtype = segy_file.spec.trace.header.dtype.newbyteorder("=") header_array = metadata_root.create_dataset( name="_".join([name, "trace_headers"]), shape=grid.shape[:-1], # Same spatial shape as data @@ -127,6 +109,7 @@ def to_zarr( compressor=header_compressor, dtype=header_dtype, dimension_separator="/", + write_empty_chunks=False, ) # Initialize chunk iterator (returns next chunk slice indices each iteration) @@ -148,12 +131,11 @@ def to_zarr( with executor: lazy_work = executor.map( trace_worker, # fn - repeat(segy_path), + repeat(segy_file), repeat(trace_array), repeat(header_array), repeat(grid), chunker, - repeat(segy_endian), chunksize=pool_chunksize, ) @@ -252,8 +234,7 @@ def to_segy( samples: Array, headers: Array, live_mask: Array, - out_dtype: Dtype, - out_byteorder: ByteOrder, + segy_factory: SegyFactory, file_root: str, axis: tuple[int] | None = None, ) -> Array: @@ -296,8 +277,7 @@ def to_segy( samples: Sample array. headers: Header array. live_mask: Live mask array. - out_dtype: Desired type of output samples. - out_byteorder: Desired output data byte order. + segy_factory: A SEG-Y factory configured to write out with user params. file_root: Root directory to write partial SEG-Y files. axis: Which axes to merge on. Excluding sample axis. @@ -319,8 +299,7 @@ def to_segy( meta_inds, *args, file_root=file_root, - out_dtype=out_dtype, - out_byteorder=out_byteorder, + segy_factory=segy_factory, concatenate=True, ) diff --git a/src/mdio/segy/byte_utils.py b/src/mdio/segy/byte_utils.py deleted file mode 100644 index 7931f721..00000000 --- a/src/mdio/segy/byte_utils.py +++ /dev/null @@ -1,92 +0,0 @@ -"""Module for custom struct abstraction utilities.""" - -import sys -from dataclasses import dataclass -from enum import Enum - -import numpy as np -from numpy.typing import NDArray - - -class Dtype(Enum): - """Dtype string to Numpy format enum.""" - - STRING = ("STRING", "S") - UINT8 = ("UINT8", "u1") - UINT16 = ("UINT16", "u2") - UINT32 = ("UINT32", "u4") - UINT64 = ("UINT64", "u8") - INT8 = ("INT8", "i1") - INT16 = ("INT16", "i2") - INT32 = ("INT32", "i4") - INT64 = ("INT64", "i8") - FLOAT16 = ("FLOAT16", "f2") - FLOAT32 = ("FLOAT32", "f4") - FLOAT64 = ("FLOAT64", "f8") - IBM32 = ("IBM32", "u4") - - @property - def numpy_dtype(self): - """Return a numpy dtype of the Enum.""" - return np.dtype(self.value[1]) - - -class ByteOrder(str, Enum): - """Endianness string to Numpy format enum.""" - - LITTLE = "<" - BIG = ">" - - -@dataclass -class OrderedType: - """Ordered Data Type (Format) abstraction. - - Args: - type: Type definition. - endian: Endianness of the data type. - - Attributes: - dtype: Structured `numpy` data type. - - Methods: - byteswap: Swaps endianness in place. - """ - - type: Dtype - endian: ByteOrder - - def __len__(self) -> int: - """Size of struct in bytes.""" - return self.dtype.itemsize - - @property - def dtype(self): - """Return Numpy dtype of the struct.""" - return np.dtype(self.endian + self.type.numpy_dtype) - - def byteswap(self): - """Swap endianness in place.""" - swapped_dtype = self.dtype.newbyteorder() - swapped_order = swapped_dtype.byteorder - self.endian = ByteOrder(swapped_order) - - -SYS_BYTEORDER = ByteOrder[sys.byteorder.upper()] - - -def get_byteorder(array: NDArray) -> str: - """Get byte order of numpy array. - - Args: - array: Array like with `.dtype` attribute. - - Returns: - String representing byte order in {"<", ">"} - """ - if array.dtype.isnative: - return SYS_BYTEORDER - - byteorder = array.dtype.byteorder - - return byteorder diff --git a/src/mdio/segy/compat.py b/src/mdio/segy/compat.py new file mode 100644 index 00000000..1ebbbae8 --- /dev/null +++ b/src/mdio/segy/compat.py @@ -0,0 +1,73 @@ +"""Generate SEG-Y spec MDIO backward compatibility. + +We were limited to fixed field names and byte locations due to using the segyio +library. Since MDIO 0.8.0 we have a more powerful SEG-Y parser and it gives more +flexibility. To support older files, we need to open them with the old SEG-Y spec. +This is where we define it. +""" + +from __future__ import annotations + +from importlib import metadata + +from segy.alias.segyio import SEGYIO_BIN_FIELD_MAP +from segy.alias.segyio import SEGYIO_TRACE_FIELD_MAP +from segy.schema import HeaderField +from segy.schema import HeaderSpec +from segy.schema import ScalarType +from segy.schema import SegySpec +from segy.schema import TextHeaderSpec +from segy.schema import TraceDataSpec +from segy.schema import TraceSpec + + +MDIO_VERSION = metadata.version("multidimio") + + +def get_binary_fields() -> list[HeaderField]: + """Generate binary header fields from equinor/segyio fields.""" + return [field.model for field in SEGYIO_BIN_FIELD_MAP.values()] + + +def get_trace_fields(version: str) -> list[HeaderField]: + """Generate trace header fields. + + This part allows us to configure custom rules for different MDIO versions. + + For instance, since MDIO 0.8.0 we also save the unassigned parts of the + trace header (after byte 233 / offset 232). To be able to ingest/export + new MDIO files and also support exporting older MDIO files, we conditionally + add the new field based on MDIO version specified above. + + Current rules: + * mdio<=0.7.4 use the segyio mappings directly. + * mdio>=0.8.0 adds an extra field to the end to fill the last 8 bytes + + Args: + version: MDIO version to generate the trace fields for. + + Returns: + List of header fields for specified MDIO version trace header encoding. + """ + trace_fields = [field.model for field in SEGYIO_TRACE_FIELD_MAP.values()] + if version > "0.7.4": + trace_fields.append(HeaderField(name="unassigned", byte=233, format="int64")) + return trace_fields + + +def mdio_segy_spec(version: str | None = None) -> SegySpec: + """Get a SEG-Y encoding spec for MDIO based on version.""" + version = MDIO_VERSION if version is None else version + + binary_fields = get_binary_fields() + trace_fields = get_trace_fields(version) + + return SegySpec( + segy_standard=None, + text_header=TextHeaderSpec(), # default EBCDIC + binary_header=HeaderSpec(fields=binary_fields, item_size=400, offset=3200), + trace=TraceSpec( + header=HeaderSpec(fields=trace_fields, item_size=240), + data=TraceDataSpec(format=ScalarType.IBM32), # placeholder + ), + ) diff --git a/src/mdio/segy/creation.py b/src/mdio/segy/creation.py index dce20aa9..c7b434a5 100644 --- a/src/mdio/segy/creation.py +++ b/src/mdio/segy/creation.py @@ -5,32 +5,47 @@ import os from os import path from shutil import copyfileobj -from time import sleep +from typing import TYPE_CHECKING from uuid import uuid4 import numpy as np -import segyio -from numpy.typing import NDArray -from segyio.binfield import keys as bfkeys +from segy.factory import SegyFactory +from segy.schema import Endianness +from segy.schema import SegySpec from tqdm.auto import tqdm from mdio.api.accessor import MDIOReader -from mdio.segy._standards_common import SegyFloatFormat -from mdio.segy.byte_utils import ByteOrder -from mdio.segy.byte_utils import Dtype -from mdio.segy.byte_utils import get_byteorder -from mdio.segy.ibm_float import ieee2ibm +from mdio.segy.compat import mdio_segy_spec + + +if TYPE_CHECKING: + from numpy.typing import NDArray + + +def make_segy_factory( + mdio: MDIOReader, + spec: SegySpec, +) -> SegyFactory: + """Generate SEG-Y factory from MDIO metadata.""" + grid = mdio.grid + sample_dim = grid.select_dim("sample") + sample_interval = sample_dim[1] - sample_dim[0] + samples_per_trace = len(sample_dim) + + return SegyFactory( + spec=spec, + sample_interval=sample_interval * 1000, + samples_per_trace=samples_per_trace, + ) def mdio_spec_to_segy( mdio_path_or_buffer, output_segy_path, - endian, access_pattern, - out_sample_format, + output_endian, storage_options, new_chunks, - selection_mask, backend, ): """Create SEG-Y file without any traces given MDIO specification. @@ -47,20 +62,16 @@ def mdio_spec_to_segy( Args: mdio_path_or_buffer: Input path where the MDIO is located. output_segy_path: Path to the output SEG-Y file. - endian: Endianness of the input SEG-Y. Rev.2 allows little endian. - Default is 'big'. Must be in {"big", "little"}. access_pattern: This specificies the chunk access pattern. Underlying zarr.Array must exist. Examples: '012', '01'. - out_sample_format: Output sample format. Currently support: - {'ibm', 'ieee'}. Default is 'ibm'. + output_endian: Endianness of the output file. storage_options: Storage options for the cloud storage backend. Default: None (will assume anonymous) new_chunks: Set manual chunksize. For development purposes only. - selection_mask: Array that lists the subset of traces to be written backend: Eager (zarr) or lazy but more flexible 'dask' backend. Returns: - Initialized MDIOReader for MDIO file and sample format parsed as integer + Initialized MDIOReader for MDIO file and return SegyFactory """ mdio = MDIOReader( mdio_path_or_buffer=mdio_path_or_buffer, @@ -73,57 +84,28 @@ def mdio_spec_to_segy( disk_cache=False, # Making sure disk caching is disabled ) - sleep(0.5) # So the connection message prints before tqdm + mdio_file_version = mdio.root.attrs["api_version"] + spec = mdio_segy_spec(mdio_file_version) + spec.endianness = Endianness(output_endian) + factory = make_segy_factory(mdio, spec=spec) - # Get grid, tracecount, and sample dimension - grid = mdio.grid - tracecount = mdio.trace_count # Only LIVE - if selection_mask is not None: - tracecount = (grid.live_mask & selection_mask).sum() - sample_dim = grid.select_dim("sample") # Last axis is samples - - # Convert text header to bytearray. First merge all lines, and then encode. - text_header = "".join(mdio.text_header) - text_header = text_header.encode() - - # Get binary header dictionary - binary_header = mdio.binary_header - - # Check and set output sample format. - # This is only executed if the user parameter - # doesn't match the original SEG-Y that was ingested. - out_sample_format = SegyFloatFormat[out_sample_format.upper()] - if out_sample_format != binary_header["Format"]: - binary_header["Format"] = out_sample_format - - # Make sure binary header for format is in sync - sample_format = binary_header["Format"] - - # Use `segyio` to create file and write initial metadata - segy_spec = segyio.spec() - segy_spec.samples = sample_dim - segy_spec.endian = endian - segy_spec.tracecount = tracecount - segy_spec.format = sample_format - - with segyio.create(output_segy_path, segy_spec) as output_segy_file: - # Write text and binary headers. - # For binary header, we use the key mappings (str -> byte loc) from segyio - output_segy_file.text[0] = text_header - output_segy_file.bin = [ - (bfkeys[key], binary_header[key]) for key in binary_header - ] - - return mdio, out_sample_format + text_str = "\n".join(mdio.text_header) + text_bytes = factory.create_textual_header(text_str) + bin_hdr_bytes = factory.create_binary_header(mdio.binary_header) + + with open(output_segy_path, mode="wb") as fp: + fp.write(text_bytes) + fp.write(bin_hdr_bytes) + + return mdio, factory def write_to_segy_stack( samples: NDArray, headers: NDArray, live: NDArray, - out_dtype: Dtype, - out_byteorder: ByteOrder, file_root: str, + segy_factory: SegyFactory, ) -> NDArray: """Pre-process seismic data for SEG-Y and write partial blocks. @@ -143,9 +125,8 @@ def write_to_segy_stack( samples: Array containing the trace samples. headers: Array containing the trace headers. live: Array containing the trace live mask. - out_dtype: Desired output data type. - out_byteorder: Desired output data byte order. file_root: Root directory to write partial SEG-Y files. + segy_factory: A SEG-Y factory configured to write out with user params. Returns: Array containing file names for partial data. None means @@ -163,21 +144,6 @@ def write_to_segy_stack( if np.count_nonzero(live) == 0: return part_segy_paths - samples = cast_sample_format(samples, out_dtype) - samples = check_byteswap(samples, out_byteorder) - headers = check_byteswap(headers, out_byteorder) - - trace_dtype = np.dtype( - { - "names": ("header", "pad", "trace"), - "formats": [ - headers.dtype, - np.dtype("int64"), - samples.shape[-1] * samples.dtype, - ], - }, - ) - # Iterate on N-1 axes of live mask. Last axis can be written # without worrying about order because it is sequential. for index in np.ndindex(live.shape[:-1]): @@ -191,59 +157,18 @@ def write_to_segy_stack( file_path = path.join(file_root, uuid4().hex) part_segy_paths[index] = file_path - # Interleave samples and headers - part_traces = np.empty(num_live, dtype=trace_dtype) - part_traces["header"] = headers[index][part_live] - part_traces["trace"] = samples[index][part_live] - part_traces["pad"] = 0 + # Create traces in bytes + trace_bytes = segy_factory.create_traces( + headers=headers[index][part_live], + samples=samples[index][part_live], + ) with open(file_path, mode="wb") as fp: - part_traces.tofile(fp) + fp.write(trace_bytes) return part_segy_paths -def check_byteswap(array: NDArray, out_byteorder: ByteOrder) -> NDArray: - """Check input byteorder and swap if user wants the other. - - Args: - array: Array containing the data. - out_byteorder: Desired output data byte order. - - Returns: - Original or byte-order swapped array. - """ - in_byteorder = get_byteorder(array) - - if in_byteorder != out_byteorder: - array.byteswap(inplace=True) - array = array.newbyteorder() - - return array - - -def cast_sample_format( - samples: NDArray, - out_dtype: Dtype, -) -> NDArray: - """Cast sample format (dtype). - - Args: - samples: Array containing the trace samples. - out_dtype: Desired output data type. - - Returns: - New structured array with pre-processing applied. - """ - if out_dtype == Dtype.IBM32: - samples = samples.astype("float32", copy=False) - samples = ieee2ibm(samples) - else: - samples = samples.astype(out_dtype.numpy_dtype, copy=False) - - return samples - - # TODO: Abstract this to support various implementations by # object stores and file systems. Probably fsspec solution. def concat_files(paths: list[str], progress=False) -> str: diff --git a/src/mdio/segy/ebcdic.py b/src/mdio/segy/ebcdic.py deleted file mode 100644 index d34487d8..00000000 --- a/src/mdio/segy/ebcdic.py +++ /dev/null @@ -1,71 +0,0 @@ -"""Conversion tables from ASCII to SEG-Y EBCDIC and vice versa. - -For more information see: -https://www.ibm.com/docs/en/iis/11.7?topic=schemas-ascii-ebcdic-conversion-tables -https://library.seg.org/seg-technical-standards (Appendix F. EBCDIC and ASCII Codes) - -Each integer index in the arrays maps to another Hex (integer) element. -The binary representations of the Hex are the ASCII or EBCDIC codes. - -Examples: - Upper case Letter "A" - EBCDIC / ASCII Hex: 0xC1 / 0x41 - * 0xC1 is the integer 193. - * If we get `EBCDIC_TO_ASCII[193]` then that maps to Hex `0x41` which is `65`. - * Then reverse it and get `ASCII_TO_EBCDIC[65]` that maps back to `0xC1` which is letter "A". - - However, some EBCDIC characters don't directly map to ASCII - https://www.ibm.com/docs/en/iis/11.7?topic=tables-conversion-table-irregularities - The pipe or vertical line operator "|" EBCDIC / ASCII Hex: 0x4F / 0x21 (instead of 0x7C per SEGY) - * 0x4F is the integer 79. - * If we get `EBCDIC_TO_ASCII[79]` then that maps to Hex `0x21` which is `33`. - * Then reverse it and get `ASCII_TO_EBCDIC[33]` that maps back to `0x4F` which is "|". -""" - -import numpy as np - - -# fmt: off -ASCII_TO_EBCDIC = np.asarray( - [ - 0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F, 0x16, 0x05, 0x25, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, # 15 - 0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26, 0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F, # 31 - 0x40, 0x4F, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D, 0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61, # 47 - 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F, # 63 - 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, # 79 - 0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0x4A, 0xE0, 0x5A, 0x5F, 0x6D, # 95 - 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, # 111 - 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xC0, 0x6A, 0xD0, 0xA1, 0x07, # 127 - 0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x09, 0x0A, 0x1B, # 143 - 0x30, 0x31, 0x1A, 0x33, 0x34, 0x35, 0x36, 0x08, 0x38, 0x39, 0x3A, 0x3B, 0x04, 0x14, 0x3E, 0xE1, # 159 - 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, # 175 - 0x58, 0x59, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, # 191 - 0x76, 0x77, 0x78, 0x80, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, # 207 - 0x9F, 0xA0, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, # 223 - 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xDA, 0xDB, # 239 - 0xDC, 0xDD, 0xDE, 0xDF, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, # 255 - ], - dtype="uint8", -) - -EBCDIC_TO_ASCII = np.asarray( - [ - 0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F, 0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, # 15 - 0x10, 0x11, 0x12, 0x13, 0x9D, 0x85, 0x08, 0x87, 0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F, # 31 - 0x80, 0x81, 0x82, 0x83, 0x84, 0x0A, 0x17, 0x1B, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07, # 47 - 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04, 0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A, # 63 - 0x20, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0x5B, 0x2E, 0x3C, 0x28, 0x2B, 0x21, # 79 - 0x26, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0x5D, 0x24, 0x2A, 0x29, 0x3B, 0x5E, # 95 - 0x2D, 0x2F, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0x7C, 0x2C, 0x25, 0x5F, 0x3E, 0x3F, # 111 - 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, 0xC2, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22, # 127 - 0xC3, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, # 143 - 0xCA, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, # 159 - 0xD1, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, # 175 - 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, # 191 - 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, # 207 - 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, # 223 - 0x5C, 0x9F, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, # 239 - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, # 255 - ], - dtype="uint8", -) -# fmt: on diff --git a/src/mdio/segy/geometry.py b/src/mdio/segy/geometry.py index fe21919b..c48753a0 100644 --- a/src/mdio/segy/geometry.py +++ b/src/mdio/segy/geometry.py @@ -8,10 +8,11 @@ from abc import abstractmethod from enum import Enum from enum import auto +from typing import TYPE_CHECKING from typing import Sequence import numpy as np -import numpy.typing as npt +from numpy.lib import recfunctions as rfn from mdio.segy.exceptions import GridOverrideIncompatibleError from mdio.segy.exceptions import GridOverrideKeysError @@ -19,6 +20,11 @@ from mdio.segy.exceptions import GridOverrideUnknownError +if TYPE_CHECKING: + from numpy.typing import NDArray + from segy.arrays import HeaderArray + + logger = logging.getLogger(__name__) @@ -83,8 +89,8 @@ class ShotGunGeometryType(Enum): def analyze_streamer_headers( - index_headers: dict[str, npt.NDArray], -) -> tuple[npt.NDArray, npt.NDArray, npt.NDArray, StreamerShotGeometryType]: + index_headers: HeaderArray, +) -> tuple[NDArray, NDArray, NDArray, StreamerShotGeometryType]: """Check input headers for SEG-Y input to help determine geometry. This function reads in trace_qc_count headers and finds the unique cable values. @@ -148,8 +154,8 @@ def analyze_streamer_headers( def analyze_shotlines_for_guns( - index_headers: dict[str, npt.NDArray], -) -> tuple[npt.NDArray, npt.NDArray, ShotGunGeometryType]: + index_headers: HeaderArray, +) -> tuple[NDArray, dict[str, list], ShotGunGeometryType]: """Check input headers for SEG-Y input to help determine geometry of shots and guns. This function reads in trace_qc_count headers and finds the unique gun values. @@ -180,7 +186,6 @@ def analyze_shotlines_for_guns( unique_guns_sl = np.sort(np.unique(gun_current_sl)) num_guns_sl = unique_guns_sl.shape[0] - # unique_guns_in_shot_line[idx] = list(unique_guns_sl) unique_guns_in_shot_line[str(shot_line)] = list(unique_guns_sl) for gun in unique_guns_sl: @@ -202,7 +207,7 @@ def analyze_shotlines_for_guns( def create_counter( depth: int, total_depth: int, - unique_headers: dict[str, npt.NDArray], + unique_headers: dict[str, NDArray], header_names: list[str], ): """Helper function to create dictionary tree for counting trace key for auto index.""" @@ -223,17 +228,19 @@ def create_counter( def create_trace_index( depth: int, counter: dict, - index_headers: dict[str, npt.NDArray], + index_headers: HeaderArray, header_names: list, dtype=np.int16, ): """Update dictionary counter tree for counting trace key for auto index.""" # Add index header - index_headers["trace"] = np.empty(index_headers[header_names[0]].shape, dtype=dtype) - + trace_no_hdr = np.empty(index_headers[header_names[0]].shape, dtype=dtype) + index_headers = rfn.append_fields( + index_headers, "trace", trace_no_hdr, usemask=False + ) idx = 0 if depth == 0: - return + return None for idx_values in zip( # noqa: B905 *(index_headers[header_names[i]] for i in range(depth)) @@ -250,10 +257,10 @@ def create_trace_index( idx += 1 + return index_headers + -def analyze_non_indexed_headers( - index_headers: dict[str, npt.NDArray], dtype=np.int16 -) -> dict[str, npt.NDArray]: +def analyze_non_indexed_headers(index_headers: HeaderArray, dtype=np.int16) -> NDArray: """Check input headers for SEG-Y input to help determine geometry. This function reads in trace_qc_count headers and finds the unique cable values. @@ -272,7 +279,7 @@ def analyze_non_indexed_headers( unique_headers = {} total_depth = 0 header_names = [] - for header_key in index_headers.keys(): + for header_key in index_headers.dtype.names: if header_key != "trace": unique_headers[header_key] = np.sort(np.unique(index_headers[header_key])) header_names.append(header_key) @@ -280,7 +287,9 @@ def analyze_non_indexed_headers( counter = create_counter(0, total_depth, unique_headers, header_names) - create_trace_index(total_depth, counter, index_headers, header_names, dtype=dtype) + index_headers = create_trace_index( + total_depth, counter, index_headers, header_names, dtype=dtype + ) t_stop = time.perf_counter() logger.debug(f"Time spent generating trace index: {t_start - t_stop:.4f} s") @@ -302,16 +311,16 @@ def required_parameters(self) -> set: @abstractmethod def validate( - self, index_headers: npt.NDArray, grid_overrides: dict[str, bool | int] + self, index_headers: HeaderArray, grid_overrides: dict[str, bool | int] ) -> None: """Validate if this transform should run on the type of data.""" @abstractmethod def transform( self, - index_headers: dict[str, npt.NDArray], + index_headers: HeaderArray, grid_overrides: dict[str, bool | int], - ) -> dict[str, npt.NDArray]: + ) -> NDArray: """Perform the grid transform.""" def transform_index_names( @@ -357,9 +366,9 @@ def name(self) -> str: """Convenience property to get the name of the command.""" return self.__class__.__name__ - def check_required_keys(self, index_headers: dict[str, npt.NDArray]) -> None: + def check_required_keys(self, index_headers: HeaderArray) -> None: """Check if all required keys are present in the index headers.""" - index_names = index_headers.keys() + index_names = index_headers.dtype.names if not self.required_keys.issubset(index_names): raise GridOverrideKeysError(self.name, self.required_keys) @@ -383,7 +392,7 @@ class DuplicateIndex(GridOverrideCommand): def validate( self, - index_headers: dict[str, npt.NDArray], + index_headers: HeaderArray, grid_overrides: dict[str, bool | int], ) -> None: """Validate if this transform should run on the type of data.""" @@ -399,9 +408,9 @@ def validate( def transform( self, - index_headers: dict[str, npt.NDArray], + index_headers: HeaderArray, grid_overrides: dict[str, bool | int], - ) -> dict[str, npt.NDArray]: + ) -> NDArray: """Perform the grid transform.""" self.validate(index_headers, grid_overrides) @@ -452,7 +461,7 @@ class AutoChannelWrap(GridOverrideCommand): def validate( self, - index_headers: dict[str, npt.NDArray], + index_headers: HeaderArray, grid_overrides: dict[str, bool | int], ) -> None: """Validate if this transform should run on the type of data.""" @@ -467,9 +476,9 @@ def validate( def transform( self, - index_headers: dict[str, npt.NDArray], + index_headers: HeaderArray, grid_overrides: dict[str, bool | int], - ) -> dict[str, npt.NDArray]: + ) -> NDArray: """Perform the grid transform.""" self.validate(index_headers, grid_overrides) @@ -506,7 +515,7 @@ class ChannelWrap(GridOverrideCommand): required_parameters = {"ChannelsPerCable"} def validate( - self, index_headers: dict, grid_overrides: dict[str, bool | int] + self, index_headers: HeaderArray, grid_overrides: dict[str, bool | int] ) -> None: """Validate if this transform should run on the type of data.""" if "AutoChannelWrap" in grid_overrides: @@ -517,9 +526,9 @@ def validate( def transform( self, - index_headers: dict[str, npt.NDArray], + index_headers: HeaderArray, grid_overrides: dict[str, bool | int], - ) -> dict[str, npt.NDArray]: + ) -> NDArray: """Perform the grid transform.""" self.validate(index_headers, grid_overrides) @@ -539,7 +548,7 @@ class CalculateCable(GridOverrideCommand): def validate( self, - index_headers: dict[str, npt.NDArray], + index_headers: HeaderArray, grid_overrides: dict[str, bool | int], ) -> None: """Validate if this transform should run on the type of data.""" @@ -551,9 +560,9 @@ def validate( def transform( self, - index_headers: dict[str, npt.NDArray], + index_headers: HeaderArray, grid_overrides: dict[str, bool | int], - ) -> dict[str, npt.NDArray]: + ) -> NDArray: """Perform the grid transform.""" self.validate(index_headers, grid_overrides) @@ -573,7 +582,7 @@ class AutoShotWrap(GridOverrideCommand): def validate( self, - index_headers: dict[str, npt.NDArray], + index_headers: HeaderArray, grid_overrides: dict[str, bool | int], ) -> None: """Validate if this transform should run on the type of data.""" @@ -582,9 +591,9 @@ def validate( def transform( self, - index_headers: dict[str, npt.NDArray], + index_headers: HeaderArray, grid_overrides: dict[str, bool | int], - ) -> dict[str, npt.NDArray]: + ) -> NDArray: """Perform the grid transform.""" self.validate(index_headers, grid_overrides) @@ -648,11 +657,11 @@ def get_allowed_parameters(self) -> set: def run( self, - index_headers: dict[str, npt.NDArray], + index_headers: HeaderArray, index_names: Sequence[str], grid_overrides: dict[str, bool], chunksize: Sequence[int] | None = None, - ) -> tuple[dict[str, npt.NDArray], tuple[str], tuple[int]]: + ) -> tuple[HeaderArray, tuple[str], tuple[int]]: """Run grid overrides and return result.""" for override in grid_overrides: if override in self.parameters: diff --git a/src/mdio/segy/headers.py b/src/mdio/segy/headers.py deleted file mode 100644 index b0e91141..00000000 --- a/src/mdio/segy/headers.py +++ /dev/null @@ -1,102 +0,0 @@ -"""SEG-Y header abstractions.""" - -from collections import abc -from dataclasses import dataclass -from dataclasses import field - -import numpy as np - -from mdio.segy.byte_utils import OrderedType - - -@dataclass -class Header(OrderedType): - """Header data type class. - - Attributes: - type: Type definition. - endian: Endianness of the data type. - name: Name of the header field. - offset: Byte offset of header field. - """ - - name: str - offset: int - - -@dataclass -class HeaderGroup(abc.MutableSequence): - """Group of headers. Such as: SEG-Y binary header or trace header. - - Args: - name: Name of header group. - offset: Byte offset of the group. - itemsize: Expected length of the header group. - headers: List of header objects. Default is an empty list. - - Attributes: - dtype: Structured `numpy` data type. - - Methods: - append: Append header to the list of headers. - insert: Insert new header to given index. - byteswap: Swaps endianness in place. - """ - - name: str - offset: int - itemsize: int - - headers: list[Header] = field(default_factory=list) - - def append(self, header: Header) -> None: - """Append a new header.""" - self.headers.append(header) - - def insert(self, index: int, header) -> None: - """Insert a new header to given index.""" - self.headers.insert(index, header) - - def __getitem__(self, item) -> Header: - """Get a specific header by index.""" - return self.headers.__getitem__(item) - - def __setitem__(self, key, value) -> None: - """Set a specific header by index.""" - self.headers.__setitem__(key, value) - - def __len__(self) -> int: - """Size of struct in bytes.""" - return self.dtype.itemsize - - def __delitem__(self, key) -> None: - """Delete header by index.""" - self.headers.__delitem__(key) - - @property - def dtype(self) -> np.dtype: - """Return Numpy dtype of the struct.""" - names = [] - formats = [] - offsets = [] - for header in self.headers: - names.append(header.name) - formats.append(header.dtype) - offsets.append(header.offset) - - # TODO: Add strict=True and remove noqa when minimum Python is 3.10 - headers_sort = sorted(zip(offsets, names, formats)) # noqa: B905 - offsets, names, formats = zip(*headers_sort) # noqa: B905 - - dtype_dict = dict( - names=names, - formats=formats, - offsets=offsets, - itemsize=self.itemsize, - ) - - return np.dtype(dtype_dict) - - def byteswap(self): - """Swap endianness in place.""" - [header.byteswap() for header in self.headers] diff --git a/src/mdio/segy/headers_text.py b/src/mdio/segy/headers_text.py deleted file mode 100644 index 502bd092..00000000 --- a/src/mdio/segy/headers_text.py +++ /dev/null @@ -1,112 +0,0 @@ -"""Text header manipulation utilities.""" - -from __future__ import annotations - -from typing import Sequence - -import numpy as np - -from mdio.segy.ebcdic import ASCII_TO_EBCDIC -from mdio.segy.ebcdic import EBCDIC_TO_ASCII - - -def wrap_strings(text_header: Sequence[str]) -> str: - """Wrap list of strings into one. - - Args: - text_header: list of str or tuple of str - Text header in ASCII. List should contain N-strings where N is the - number of lines in the text header. By default, SEG-Y text headers - have 40 lines and 80 characters each. - - Returns: - Concatenated string. - """ - joined = "".join(text_header) - return joined - - -def unwrap_string(text_header: str, rows: int = 40, cols: int = 80) -> list[str]: - """Unwrap string into a list of strings with given rows and columns. - - Args: - text_header: Text header in ASCII. Should be single string of text - header. By default, SEG-Y text headers have 40 lines and 80 - characters each. A total of 3200 characters are expected, - however this can be changed via the parameters `rows` and - `columns` if needed. - rows: Numbers of output rows. Default is 40. `rows` x `cols` must - equal `len(text_header)`. - cols: Number of output columns. Default is 80. `rows` x `cols` must - equal `len(text_header)`. - - Returns: - List of strings unwrapped to given specification. - - Raises: - ValueError: if rows and columns don't match the size of string. - """ - if rows * cols != len(text_header): - raise ValueError("rows x cols must be equal text_header length.") - - unwrapped = [] - for idx in range(rows): - start = idx * cols - stop = start + cols - unwrapped.append(text_header[start:stop]) - - return unwrapped - - -def ascii_to_ebcdic(text_header: Sequence[str]) -> bytearray: - """Convert ASCII encoded strings to EBCDIC bytearray. - - Args: - text_header: Text header in ASCII. List should contain N-strings - where N is the number of lines in the text header. By default, - SEG-Y text headers have 40 lines and 80 characters each. - Which totals 3200-bytes. - - Returns: - EBCDIC encoded string as bytearray. - """ - ascii_flat = wrap_strings(text_header) - ascii_encoded = ascii_flat.encode() - ascii_uint = np.frombuffer(ascii_encoded, dtype="uint8") - ebcdic_uint = ASCII_TO_EBCDIC[ascii_uint] - ebcdic_bytes = ebcdic_uint.tobytes() - return ebcdic_bytes - - -def ebcdic_to_ascii( - byte_string: bytearray | bytes, - unwrap: bool = True, - rows: int = 40, - cols: int = 80, -) -> list[str] | str: - """Convert EBCDIC encoded bytearray to ASCII string(s). - - Args: - byte_string: EBCDIC encoded bytearray. - unwrap: Option to unwrap the lines. Default is True. - rows: Numbers of output rows. Default is 40. `rows` x `cols` must - equal `len(text_header)` - cols: Number of output columns. Default is 80. `rows` x `cols` must - equal `len(text_header)` - - Returns: - ASCII decoded text header. - """ - length = len(byte_string) - - uint_repr = np.frombuffer(byte_string, dtype="uint8") - ascii_bytes = EBCDIC_TO_ASCII[uint_repr].view(f"S{length}") - ascii_str = ascii_bytes.astype("str") - - # Get rid of dimensions if not unwrapped - ascii_str = np.array_str(np.squeeze(ascii_str)) - - if unwrap is True: - ascii_str = unwrap_string(ascii_str, rows, cols) - - return ascii_str diff --git a/src/mdio/segy/ibm_float.py b/src/mdio/segy/ibm_float.py deleted file mode 100644 index 787ac8e2..00000000 --- a/src/mdio/segy/ibm_float.py +++ /dev/null @@ -1,189 +0,0 @@ -"""Low-level floating point conversion operations.""" - -import os - -import numba as nb -import numpy as np - - -# If Numba's JIT compilation is disabled, force vectorized -# functions to Numba's Object Mode. This is only used when running -# tests and we want a coverage report to JIT functions. -# In every other case, functions will be JIT compiled. -try: - NUMBA_DISABLE_JIT = os.environ["NUMBA_DISABLE_JIT"] -except KeyError: # pragma: no cover - NUMBA_DISABLE_JIT = 0 - -OBJECT_MODE = True if NUMBA_DISABLE_JIT else False -JIT_CACHE = False if NUMBA_DISABLE_JIT else True -JIT_TARGET = "cpu" -JIT_KWARGS = dict(cache=JIT_CACHE, forceobj=OBJECT_MODE) - -# IEEE to IBM MASKS ETC -IEEE32_SIGN = np.uint32(0x80000000) -IEEE32_EXPONENT = np.int32(0x7F800000) -IEEE32_FRACTION = np.uint32(0x7FFFFF) - -# IBM to IEEE MASKS ETC -BASE2POW24 = np.uint32(0x1000000) -IBM32_EXPONENT = np.uint32(0x7F000000) -IBM32_FRACTION = np.uint32(0xFFFFFF) - -# For Byte Swapping -BYTEMASK_1_3 = np.uint32(0xFF00FF00) -BYTEMASK_2_4 = np.uint32(0xFF00FF) - - -@nb.njit( - "uint32(float32)", - cache=JIT_CACHE, - locals={ - "sign": nb.uint32, - "exponent": nb.int32, - "exp_remainder": nb.int8, - "downshift": nb.int8, - "ibm_mantissa": nb.int32, - }, -) -def ieee2ibm_single(ieee: np.float32) -> np.uint32: - """IEEE Float to IBM Float conversion. - - Modified from here: - https://mail.python.org/pipermail/scipy-user/2011-June/029661.html - - Had to do some CPU and memory optimizations + Numba JIT compilation - - Assuming `ieee_array` is little endian and float32. Will convert to float32 if not. - Returns `ibm_array` as little endian too. - - Byte swapping is up to user after this function. - - Args: - ieee: Numpy IEEE 32-bit float array. - - Returns: - IBM 32-bit float converted array with int32 view. - """ - ieee = np.float32(ieee).view(np.uint32) - - if ieee in [0, 2147483648]: # 0.0 or np.float32(-0.0).view('uint32') - return 0 - - # Get IEEE's sign and exponent - sign = ieee & IEEE32_SIGN - exponent = ((ieee & IEEE32_EXPONENT) >> 23) - 127 - # The IBM 7-bit exponent is to the base 16 and the mantissa is presumed to - # be entirely to the right of the radix point. In contrast, the IEEE - # exponent is to the base 2 and there is an assumed 1-bit to the left of - # the radix point. - # Note: reusing exponent variable, -> it is actually exp16 - - # exp16, exp_remainder - exponent, exp_remainder = divmod(exponent + 1, 4) - exponent += exp_remainder != 0 - downshift = 4 - exp_remainder if exp_remainder else 0 - exponent = exponent + 64 - # From here down exponent -> ibm_exponent - exponent = 0 if exponent < 0 else exponent - exponent = 127 if exponent > 127 else exponent - exponent = exponent << 24 - exponent = exponent if ieee else 0 - - # Add the implicit initial 1-bit to the 23-bit IEEE mantissa to get the - # 24-bit IBM mantissa. Downshift it by the remainder from the exponent's - # division by 4. It is allowed to have up to 3 leading 0s. - ibm_mantissa = ((ieee & IEEE32_FRACTION) | 0x800000) >> downshift - ibm = sign | exponent | ibm_mantissa - - return ibm - - -@nb.njit( - "float32(uint32)", - cache=JIT_CACHE, - locals={ - "sign_bit": nb.boolean, - "sign": nb.int8, - "exponent": nb.uint8, - "mantissa": nb.float32, - "ieee": nb.float32, - }, -) -def ibm2ieee_single(ibm: np.uint32) -> np.float32: - """Converts a 32-bit IBM floating point number into 32-bit IEEE format. - - https://en.wikipedia.org/wiki/IBM_hexadecimal_floating-point - https://en.wikipedia.org/wiki/IEEE_754 - - FP Number = (IBM) -1**sign_bit × 0.significand × 16**(exponent−64) - - Args: - ibm: Value in 32-bit IBM Float in Little-Endian Format. - - Returns: - Value parsed to 32-bit IEEE Float in Little-Endian Format. - """ - if ibm & IBM32_FRACTION == 0: - return 0.0 - - sign_bit = ibm >> 31 - - exponent = (ibm & IBM32_EXPONENT) >> 24 - mantissa = (ibm & IBM32_FRACTION) / BASE2POW24 - - # (1 - 2 * sign_bit) is about 50x faster than (-1)**sign_bit - sign = 1 - 2 * sign_bit - - # This 16.0 (instead of just 16) is super important. - # If the base is not a float, it won't work for negative - # exponents, and fail silently and return zero. - ieee = sign * mantissa * 16.0 ** (exponent - 64) - - return ieee - - -@nb.njit("uint32(uint32)", cache=JIT_CACHE) -def byteswap_uint32_single(value): - """Endianness swapping that can be JIT compiled. - - This is faster or on par with the numpy implementation depending - on the size of the array. - - We first shift (4, 3, 2, 1) to (3, 4, 1, 2) - Then shift (3, 4, 3, 2) to (1, 2, 3, 4) - - Which yields (4, 3, 2, 1) -> (1, 2, 3, 4) or vice-versa. - - Args: - value: Value to be byte-swapped. - - Returns: - Byte-swapped value in same dtype. - """ - value = np.uint32(value) - - if value == 0: - return value - - value = ((value << 8) & BYTEMASK_1_3) | ((value >> 8) & BYTEMASK_2_4) - value = np.uint32(value << 16) | np.uint32(value >> 16) - return value - - -@nb.vectorize("uint32(float32)", target=JIT_TARGET, **JIT_KWARGS) -def ieee2ibm(ieee_array: np.float32) -> np.uint32: # pragma: no cover - """Wrapper for vectorizing IEEE to IBM conversion to arrays.""" - return ieee2ibm_single(ieee_array) - - -@nb.vectorize("float32(uint32)", target=JIT_TARGET, **JIT_KWARGS) -def ibm2ieee(ibm_array: np.uint32) -> np.float32: # pragma: no cover - """Wrapper for vectorizing IBM to IEEE conversion to arrays.""" - return ibm2ieee_single(ibm_array) - - -@nb.vectorize("uint32(uint32)", **JIT_KWARGS) -def byteswap_uint32(value): # pragma: no cover - """Wrapper for vectorizing byte-swap to arrays.""" - return byteswap_uint32_single(value) diff --git a/src/mdio/segy/parsers.py b/src/mdio/segy/parsers.py index 5c49d645..2b13186e 100644 --- a/src/mdio/segy/parsers.py +++ b/src/mdio/segy/parsers.py @@ -2,104 +2,45 @@ from __future__ import annotations +import os from concurrent.futures import ProcessPoolExecutor from itertools import repeat from math import ceil -from typing import Any -from typing import Sequence +from typing import TYPE_CHECKING import numpy as np -import segyio -from numpy.typing import NDArray from psutil import cpu_count +from segy.arrays import HeaderArray from tqdm.auto import tqdm -from mdio.core import Dimension from mdio.segy._workers import header_scan_worker -from mdio.segy.byte_utils import Dtype -NUM_CORES = cpu_count(logical=False) +if TYPE_CHECKING: + from segy import SegyFile +default_cpus = cpu_count(logical=True) +NUM_CPUS = int(os.getenv("MDIO__IMPORT__CPU_COUNT", default_cpus)) -def get_trace_count(segy_path, segy_endian): - """Get trace count from SEG-Y file (size).""" - with segyio.open( - filename=segy_path, - mode="r", - ignore_geometry=True, - endian=segy_endian, - ) as segy_handle: - trace_count = segy_handle.tracecount - return trace_count - - -def parse_binary_header(segy_handle: segyio.SegyFile) -> dict[str, Any]: - """Parse `segyio.BinField` as python `dict`. - - The `segyio` library returns the binary header as a `BinField` instance, - which is not serializable. Here we parse it as a dictionary, so we can - later convert it to JSON. - - Args: - segy_handle: The SegyFile instance in context. - - Returns: - Parsed binary header key, value pairs. - """ - binary_header = segy_handle.bin - return {str(entry): binary_header[entry] for entry in binary_header} - - -def parse_text_header(segy_handle: segyio.SegyFile) -> list[str]: - """Parse text header from `bytearray` to python `list` of `str` per line. - - The `segyio` library returns the text header as a `bytearray` instance. - Here we parse it as a list of strings (per line). - - Args: - segy_handle: The SegyFile instance in context. - - Returns: - Parsed text header in list with lines as elements. - """ - text_header = segy_handle.text[0].decode(errors="ignore") - text_header = [ - text_header[char_idx : char_idx + 80] - for char_idx in range(0, len(text_header), 80) - ] - return text_header - - -def parse_trace_headers( - segy_path: str, - segy_endian: str, - byte_locs: Sequence[int], - byte_types: Sequence[Dtype], - index_names: Sequence[str], - block_size: int = 50000, +def parse_index_headers( + segy_file: SegyFile, + block_size: int = 10000, progress_bar: bool = True, -) -> dict[str, NDArray]: +) -> HeaderArray: """Read and parse given `byte_locations` from SEG-Y file. Args: - segy_path: Path to the input SEG-Y file. - segy_endian: Endianness of the input SEG-Y in {'big', 'little'}. - byte_locs: Byte locations to return. It will be a subset of headers. - byte_types: Data types of each header key to index. Must be the - same count as `byte_lengths`. - index_names: Tuple of the names for the index attributes + segy_file: SegyFile instance. block_size: Number of traces to read for each block. progress_bar: Enable or disable progress bar. Default is True. Returns: - dictionary with headers: keys are the index names, values are numpy + Numpy array of headers. Keys are the index names, values are numpy arrays of parsed headers for the current block. Array is of type - byte_type with the exception of IBM32 which is mapped to FLOAT32. - + byte_type except IBM32 which is mapped to FLOAT32. """ - trace_count = get_trace_count(segy_path, segy_endian) + trace_count = segy_file.num_traces n_blocks = int(ceil(trace_count / block_size)) trace_ranges = [] @@ -110,20 +51,15 @@ def parse_trace_headers( trace_ranges.append((start, stop)) - num_workers = min(n_blocks, NUM_CORES) + num_workers = min(n_blocks, NUM_CPUS) tqdm_kw = dict(unit="block", dynamic_ncols=True) with ProcessPoolExecutor(num_workers) as executor: # pool.imap is lazy lazy_work = executor.map( header_scan_worker, # fn - repeat(segy_path), + repeat(segy_file), trace_ranges, - repeat(byte_locs), - repeat(byte_types), - repeat(index_names), - repeat(segy_endian), - chunksize=2, # Not array chunks. This is for `multiprocessing` ) if progress_bar is True: @@ -135,29 +71,7 @@ def parse_trace_headers( ) # This executes the lazy work. - headers = list(lazy_work) + headers: list[HeaderArray] = list(lazy_work) - final_headers = {} - for header_name in index_names: - final_headers[header_name] = np.concatenate( - [header[header_name] for header in headers] - ) # Merge blocks before return - return final_headers - - -def parse_sample_axis(binary_header: dict) -> Dimension: - """Parse sample axis from binary header. - - Args: - binary_header: Dictionary representing binary header. - - Returns: - MDIO Dimension instance for sample axis. - """ - num_samp = binary_header["Samples"] - interval = binary_header["Interval"] // 1000 - - max_val = num_samp * interval - - return Dimension(coords=range(0, max_val, interval), name="sample") + return np.concatenate(headers) diff --git a/src/mdio/segy/utilities.py b/src/mdio/segy/utilities.py index bf14d7c2..dd8e677b 100644 --- a/src/mdio/segy/utilities.py +++ b/src/mdio/segy/utilities.py @@ -2,33 +2,30 @@ from __future__ import annotations -from typing import Sequence +from typing import TYPE_CHECKING import numpy as np from dask.array.core import auto_chunks -from numpy.typing import DTypeLike -from numpy.typing import NDArray from mdio.core import Dimension -from mdio.segy.byte_utils import Dtype from mdio.segy.geometry import GridOverrider -from mdio.segy.parsers import parse_sample_axis -from mdio.segy.parsers import parse_trace_headers +from mdio.segy.parsers import parse_index_headers + + +if TYPE_CHECKING: + from numpy.typing import DTypeLike + from segy import SegyFile + from segy.arrays import HeaderArray def get_grid_plan( # noqa: C901 - segy_path: str, - segy_endian: str, - index_bytes: Sequence[int], - index_names: Sequence[str], - index_types: Sequence[Dtype], - chunksize: Sequence[int], - binary_header: dict, + segy_file: SegyFile, + chunksize: list[int], return_headers: bool = False, grid_overrides: dict | None = None, ) -> ( - tuple[list[Dimension], tuple[int]] - | tuple[list[Dimension], tuple[int], dict[str, NDArray]] + tuple[list[Dimension], tuple[int, ...]] + | tuple[list[Dimension], tuple[int, ...], HeaderArray] ): """Infer dimension ranges, and increments. @@ -39,13 +36,8 @@ def get_grid_plan( # noqa: C901 4. Create `Dimension` for sample axis using binary header. Args: - segy_path: Path to the input SEG-Y file - segy_endian: Endianness of the input SEG-Y. - index_bytes: Tuple of the byte location for the index attributes - index_names: Tuple of the names for the index attributes - index_types: Tuple of the data types for the index attributes. + segy_file: SegyFile instance. chunksize: Chunk sizes to be used in grid plan. - binary_header: Dictionary containing binary header key, value pairs. return_headers: Option to return parsed headers with `Dimension` objects. Default is False. grid_overrides: Option to add grid overrides. See main documentation. @@ -57,18 +49,8 @@ def get_grid_plan( # noqa: C901 if grid_overrides is None: grid_overrides = {} - index_dim = len(index_bytes) - - if index_names is None: - index_names = [f"index_{dim}" for dim in range(index_dim)] - - index_headers = parse_trace_headers( - segy_path=segy_path, - segy_endian=segy_endian, - byte_locs=index_bytes, - byte_types=index_types, - index_names=index_names, - ) + index_headers = parse_index_headers(segy_file=segy_file) + index_names = [name for name in index_headers.dtype.names] dims = [] @@ -85,7 +67,12 @@ def get_grid_plan( # noqa: C901 dim_unique = np.unique(index_headers[index_name]) dims.append(Dimension(coords=dim_unique, name=index_name)) - sample_dim = parse_sample_axis(binary_header=binary_header) + sample_labels = segy_file.sample_labels / 1000 # normalize + + if all(sample_labels.astype("int64") == sample_labels): + sample_labels = sample_labels.astype("int64") + + sample_dim = Dimension(coords=sample_labels, name="sample") dims.append(sample_dim) diff --git a/tests/conftest.py b/tests/conftest.py index 91be127b..2e5430c3 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -24,14 +24,14 @@ def segy_input(tmp_path_factory): return tmp_file -@pytest.fixture(scope="session") +@pytest.fixture(scope="module") def zarr_tmp(tmp_path_factory): """Make a temp file for the output MDIO.""" tmp_file = tmp_path_factory.mktemp(r"mdio") return tmp_file -@pytest.fixture(scope="session") +@pytest.fixture(scope="module") def zarr_tmp2(tmp_path_factory): """Make a temp file for the output MDIO.""" tmp_file = tmp_path_factory.mktemp(r"mdio2") @@ -39,18 +39,9 @@ def zarr_tmp2(tmp_path_factory): @pytest.fixture(scope="session") -def segy_export_ibm_tmp(tmp_path_factory): +def segy_export_tmp(tmp_path_factory): """Make a temp file for the round-trip IBM SEG-Y.""" tmp_dir = tmp_path_factory.mktemp("segy") - tmp_file = path.join(tmp_dir, "teapot_roundtrip_ibm.segy") - - return tmp_file - - -@pytest.fixture(scope="session") -def segy_export_ieee_tmp(tmp_path_factory): - """Make a temp file for the round-trip IEEE SEG-Y.""" - tmp_dir = tmp_path_factory.mktemp("segy") - tmp_file = path.join(tmp_dir, "teapot_roundtrip_ieee.segy") + tmp_file = path.join(tmp_dir, "teapot_roundtrip.segy") return tmp_file diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 0ef324db..e45d41ad 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -6,7 +6,10 @@ import numpy as np import pytest -import segyio +from segy.factory import SegyFactory +from segy.schema import HeaderField +from segy.standards import SegyStandard +from segy.standards import get_segy_standard from mdio.segy.geometry import StreamerShotGeometryType @@ -22,18 +25,12 @@ def create_segy_mock_4d( index_receivers: bool = True, ) -> str: """Dummy 4D SEG-Y file for use in tests.""" - spec = segyio.spec() - segy_file = os.path.join(fake_segy_tmp, f"4d_type_{chan_header_type}.sgy") + segy_path = os.path.join(fake_segy_tmp, f"4d_type_{chan_header_type}.sgy") shot_count = len(shots) total_chan = np.sum(receivers_per_cable) trace_count = shot_count * total_chan - spec.format = 1 - spec.samples = range(num_samples) - spec.tracecount = trace_count - spec.endian = "big" - # Calculate shot, cable, channel/receiver numbers and header values cable_headers = [] channel_headers = [] @@ -64,46 +61,56 @@ def create_segy_mock_4d( cable_headers = np.tile(cable_headers, shot_count) channel_headers = np.tile(channel_headers, shot_count) - with segyio.create(segy_file, spec) as f: - for trc_idx in range(trace_count): - shot = shot_headers[trc_idx] - gun = gun_headers[trc_idx] - cable = cable_headers[trc_idx] - channel = channel_headers[trc_idx] - source_line = 1 - - # offset is byte location 37 - offset 4 bytes - # fldr is byte location 9 - shot 4 byte - # ep is byte location 17 - shot 4 byte - # stae is byte location 137 - cable 2 byte - # tracf is byte location 13 - channel 4 byte - # grnors is byte location 171 - gun 2 bytes - # styp is byte location 133 - source_line 2 bytes - - if index_receivers: - f.header[trc_idx].update( - offset=0, - fldr=shot, - ep=shot, - stae=cable, - tracf=channel, - grnors=gun, - styp=source_line, - ) - else: - f.header[trc_idx].update( - offset=0, - fldr=shot, - ep=shot, - stae=cable, - ) - - samples = np.linspace(start=shot, stop=shot + 1, num=num_samples) - f.trace[trc_idx] = samples.astype("float32") - - f.bin.update() - - return segy_file + trace_header_fields = [ + HeaderField(name="field_rec_no", byte=9, format="int32"), + HeaderField(name="channel", byte=13, format="int32"), + HeaderField(name="shot_point", byte=17, format="int32"), + HeaderField(name="offset", byte=37, format="int32"), + HeaderField(name="samples_per_trace", byte=115, format="int32"), + HeaderField(name="sample_interval", byte=117, format="int32"), + HeaderField(name="shot_line", byte=133, format="int16"), + HeaderField(name="cable", byte=137, format="int16"), + HeaderField(name="gun", byte=171, format="int16"), + ] + + rev1_spec = get_segy_standard(1.0) + spec = rev1_spec.customize(trace_header_fields=trace_header_fields) + spec.segy_standard = SegyStandard.REV1 + factory = SegyFactory( + spec=spec, + sample_interval=1000, + samples_per_trace=num_samples, + ) + + headers = factory.create_trace_header_template(trace_count) + samples = factory.create_trace_sample_template(trace_count) + + for trc_idx in range(trace_count): + shot = shot_headers[trc_idx] + gun = gun_headers[trc_idx] + cable = cable_headers[trc_idx] + channel = channel_headers[trc_idx] + shot_line = 1 + offset = 0 + + if index_receivers is False: + channel, gun, shot_line = 0, 0, 0 + + header_data = (shot, channel, shot, offset, shot_line, cable, gun) + + fields = list(headers.dtype.names) + fields.remove("samples_per_trace") + fields.remove("sample_interval") + + headers[fields][trc_idx] = header_data + samples[trc_idx] = np.linspace(start=shot, stop=shot + 1, num=num_samples) + + with open(segy_path, mode="wb") as fp: + fp.write(factory.create_textual_header()) + fp.write(factory.create_binary_header()) + fp.write(factory.create_traces(headers, samples)) + + return segy_path @pytest.fixture(scope="module") diff --git a/tests/integration/test_segy_import_export.py b/tests/integration/test_segy_import_export.py index 0eb0cf23..7e8d06ae 100644 --- a/tests/integration/test_segy_import_export.py +++ b/tests/integration/test_segy_import_export.py @@ -6,22 +6,22 @@ import numpy as np import numpy.testing as npt import pytest -import segyio +from segy import SegyFile from mdio import MDIOReader from mdio import mdio_to_segy from mdio.converters import segy_to_mdio from mdio.core import Dimension +from mdio.segy.compat import mdio_segy_spec from mdio.segy.geometry import StreamerShotGeometryType dask.config.set(scheduler="synchronous") -@pytest.mark.parametrize("header_locations", [(17, 137)]) -@pytest.mark.parametrize("header_names", [("shot_point", "cable")]) -@pytest.mark.parametrize("header_types", [("int32", "int16")]) -@pytest.mark.parametrize("endian", ["big"]) +@pytest.mark.parametrize("index_bytes", [(17, 137)]) +@pytest.mark.parametrize("index_names", [("shot_point", "cable")]) +@pytest.mark.parametrize("index_types", [("int32", "int16")]) @pytest.mark.parametrize( "grid_overrides", [{"NonBinned": True, "chunksize": 2}, {"HasDuplicates": True}] ) @@ -33,10 +33,9 @@ def test_import_4d_segy( self, segy_mock_4d_shots, zarr_tmp, - header_locations, - header_names, - header_types, - endian, + index_bytes, + index_names, + index_types, grid_overrides, chan_header_type, ): @@ -46,12 +45,11 @@ def test_import_4d_segy( segy_to_mdio( segy_path=segy_path, mdio_path_or_buffer=zarr_tmp.__str__(), - index_bytes=header_locations, - index_names=header_names, - index_types=header_types, + index_bytes=index_bytes, + index_names=index_names, + index_types=index_types, chunksize=(8, 2, 10), overwrite=True, - endian=endian, grid_overrides=grid_overrides, ) @@ -63,11 +61,11 @@ def test_import_4d_segy( # QC mdio output mdio = MDIOReader(zarr_tmp.__str__(), access_pattern="0123") - assert mdio.binary_header["Samples"] == num_samples + assert mdio.binary_header["samples_per_trace"] == num_samples grid = mdio.grid - assert grid.select_dim(header_names[0]) == Dimension(shots, header_names[0]) - assert grid.select_dim(header_names[1]) == Dimension(cables, header_names[1]) + assert grid.select_dim(index_names[0]) == Dimension(shots, index_names[0]) + assert grid.select_dim(index_names[1]) == Dimension(cables, index_names[1]) assert grid.select_dim("trace") == Dimension( range(1, np.amax(receivers_per_cable) + 1), "trace" ) @@ -75,10 +73,9 @@ def test_import_4d_segy( assert grid.select_dim("sample") == samples_exp -@pytest.mark.parametrize("header_locations", [(17, 137, 13)]) -@pytest.mark.parametrize("header_names", [("shot_point", "cable", "channel")]) -@pytest.mark.parametrize("header_types", [("int32", "int16", "int32")]) -@pytest.mark.parametrize("endian", ["big"]) +@pytest.mark.parametrize("index_bytes", [(17, 137, 13)]) +@pytest.mark.parametrize("index_names", [("shot_point", "cable", "channel")]) +@pytest.mark.parametrize("index_types", [("int32", "int16", "int32")]) @pytest.mark.parametrize("grid_overrides", [{"AutoChannelWrap": True}, None]) @pytest.mark.parametrize( "chan_header_type", [StreamerShotGeometryType.A, StreamerShotGeometryType.B] @@ -90,10 +87,9 @@ def test_import_4d_segy( self, segy_mock_4d_shots, zarr_tmp, - header_locations, - header_names, - header_types, - endian, + index_bytes, + index_names, + index_types, grid_overrides, chan_header_type, ): @@ -103,12 +99,11 @@ def test_import_4d_segy( segy_to_mdio( segy_path=segy_path, mdio_path_or_buffer=zarr_tmp.__str__(), - index_bytes=header_locations, - index_names=header_names, - index_types=header_types, + index_bytes=index_bytes, + index_names=index_names, + index_types=index_types, chunksize=(8, 2, 128, 1024), overwrite=True, - endian=endian, grid_overrides=grid_overrides, ) @@ -120,41 +115,30 @@ def test_import_4d_segy( # QC mdio output mdio = MDIOReader(zarr_tmp.__str__(), access_pattern="0123") - assert mdio.binary_header["Samples"] == num_samples + assert mdio.binary_header["samples_per_trace"] == num_samples grid = mdio.grid - assert grid.select_dim(header_names[0]) == Dimension(shots, header_names[0]) - assert grid.select_dim(header_names[1]) == Dimension(cables, header_names[1]) + assert grid.select_dim(index_names[0]) == Dimension(shots, index_names[0]) + assert grid.select_dim(index_names[1]) == Dimension(cables, index_names[1]) if chan_header_type == StreamerShotGeometryType.B and grid_overrides is None: - assert grid.select_dim(header_names[2]) == Dimension( - range(1, np.sum(receivers_per_cable) + 1), header_names[2] + assert grid.select_dim(index_names[2]) == Dimension( + range(1, np.sum(receivers_per_cable) + 1), index_names[2] ) else: - assert grid.select_dim(header_names[2]) == Dimension( - range(1, np.amax(receivers_per_cable) + 1), header_names[2] + assert grid.select_dim(index_names[2]) == Dimension( + range(1, np.amax(receivers_per_cable) + 1), index_names[2] ) samples_exp = Dimension(range(0, num_samples, 1), "sample") assert grid.select_dim("sample") == samples_exp -@pytest.mark.parametrize("header_locations", [(17, 137, 13)]) -@pytest.mark.parametrize("header_names", [("shot_point", "cable", "channel")]) -@pytest.mark.parametrize("header_types", [("int32", "int16", "int32")]) -@pytest.mark.parametrize("endian", ["big"]) -@pytest.mark.parametrize( - "grid_overrides", - [ - None, - ], -) -@pytest.mark.parametrize( - "chan_header_type", - [ - StreamerShotGeometryType.A, - ], -) +@pytest.mark.parametrize("index_bytes", [(17, 137, 13)]) +@pytest.mark.parametrize("index_names", [("shot_point", "cable", "channel")]) +@pytest.mark.parametrize("index_types", [("int32", "int16", "int32")]) +@pytest.mark.parametrize("grid_overrides", [None]) +@pytest.mark.parametrize("chan_header_type", [StreamerShotGeometryType.A]) class TestImport4DSparse: """Test for 4D segy import with grid overrides.""" @@ -162,10 +146,9 @@ def test_import_4d_segy( self, segy_mock_4d_shots, zarr_tmp, - header_locations, - header_names, - header_types, - endian, + index_bytes, + index_names, + index_types, grid_overrides, chan_header_type, ): @@ -181,12 +164,11 @@ def test_import_4d_segy( segy_to_mdio( segy_path=segy_path, mdio_path_or_buffer=zarr_tmp.__str__(), - index_bytes=header_locations, - index_names=header_names, - index_types=header_types, + index_bytes=index_bytes, + index_names=index_names, + index_types=index_types, chunksize=(8, 2, 128, 1024), overwrite=True, - endian=endian, grid_overrides=grid_overrides, ) @@ -197,14 +179,11 @@ def test_import_4d_segy( ) -@pytest.mark.parametrize("header_locations", [(133, 171, 17, 137, 13)]) -@pytest.mark.parametrize( - "header_names", [("shot_line", "gun", "shot_point", "cable", "channel")] -) +@pytest.mark.parametrize("index_bytes", [(133, 171, 17, 137, 13)]) @pytest.mark.parametrize( - "header_types", [("int16", "int16", "int32", "int16", "int32")] + "index_names", [("shot_line", "gun", "shot_point", "cable", "channel")] ) -@pytest.mark.parametrize("endian", ["big"]) +@pytest.mark.parametrize("index_types", [("int16", "int16", "int32", "int16", "int32")]) @pytest.mark.parametrize( "grid_overrides", [{"AutoChannelWrap": True, "AutoShotWrap": True}, None] ) @@ -218,10 +197,9 @@ def test_import_6d_segy( self, segy_mock_4d_shots, zarr_tmp, - header_locations, - header_names, - header_types, - endian, + index_bytes, + index_names, + index_types, grid_overrides, chan_header_type, ): @@ -231,12 +209,11 @@ def test_import_6d_segy( segy_to_mdio( segy_path=segy_path, mdio_path_or_buffer=zarr_tmp.__str__(), - index_bytes=header_locations, - index_names=header_names, - index_types=header_types, + index_bytes=index_bytes, + index_names=index_names, + index_types=index_types, chunksize=(1, 1, 8, 1, 12, 36), overwrite=True, - endian=endian, grid_overrides=grid_overrides, ) @@ -255,54 +232,49 @@ def test_import_6d_segy( # QC mdio output mdio = MDIOReader(zarr_tmp.__str__(), access_pattern="012345") - assert mdio.binary_header["Samples"] == num_samples + assert mdio.binary_header["samples_per_trace"] == num_samples grid = mdio.grid - assert grid.select_dim(header_names[1]) == Dimension(guns, header_names[1]) - assert grid.select_dim(header_names[2]) == Dimension(shots, header_names[2]) - assert grid.select_dim(header_names[3]) == Dimension(cables, header_names[3]) + assert grid.select_dim(index_names[1]) == Dimension(guns, index_names[1]) + assert grid.select_dim(index_names[2]) == Dimension(shots, index_names[2]) + assert grid.select_dim(index_names[3]) == Dimension(cables, index_names[3]) if chan_header_type == StreamerShotGeometryType.B and grid_overrides is None: - assert grid.select_dim(header_names[4]) == Dimension( - range(1, np.sum(receivers_per_cable) + 1), header_names[4] + assert grid.select_dim(index_names[4]) == Dimension( + range(1, np.sum(receivers_per_cable) + 1), index_names[4] ) else: - assert grid.select_dim(header_names[4]) == Dimension( - range(1, np.amax(receivers_per_cable) + 1), header_names[4] + assert grid.select_dim(index_names[4]) == Dimension( + range(1, np.amax(receivers_per_cable) + 1), index_names[4] ) samples_exp = Dimension(range(0, num_samples, 1), "sample") assert grid.select_dim("sample") == samples_exp -@pytest.mark.parametrize("header_locations", [(17, 13)]) -@pytest.mark.parametrize("header_names", [("inline", "crossline")]) -@pytest.mark.parametrize("endian", ["big"]) -class TestImport: - """Import tests.""" - - def test_3d_import( - self, segy_input, zarr_tmp, header_locations, header_names, endian - ): - """Test importing a SEG-Y file to MDIO.""" - segy_to_mdio( - segy_path=segy_input.__str__(), - mdio_path_or_buffer=zarr_tmp.__str__(), - index_bytes=header_locations, - index_names=header_names, - overwrite=True, - endian=endian, - ) +@pytest.mark.dependency() +@pytest.mark.parametrize("index_bytes", [(17, 13)]) +@pytest.mark.parametrize("index_names", [("inline", "crossline")]) +def test_3d_import(segy_input, zarr_tmp, index_bytes, index_names): + """Test importing a SEG-Y file to MDIO.""" + segy_to_mdio( + segy_path=segy_input.__str__(), + mdio_path_or_buffer=zarr_tmp.__str__(), + index_bytes=index_bytes, + index_names=index_names, + overwrite=True, + ) +@pytest.mark.dependency("test_3d_import") class TestReader: """Test reader functionality.""" def test_meta_read(self, zarr_tmp): """Metadata reading tests.""" mdio = MDIOReader(zarr_tmp.__str__()) - assert mdio.binary_header["Samples"] == 1501 - assert mdio.binary_header["Interval"] == 2000 + assert mdio.binary_header["samples_per_trace"] == 1501 + assert mdio.binary_header["sample_interval"] == 2000 def test_grid(self, zarr_tmp): """Grid reading tests.""" @@ -350,75 +322,35 @@ def test_zslice(self, zarr_tmp): npt.assert_allclose([mean, std], [0.005236923, 0.61279935]) +@pytest.mark.dependency("test_3d_import") class TestExport: """Test SEG-Y exporting functionaliy.""" - def test_3d_export(self, zarr_tmp, segy_export_ibm_tmp, segy_export_ieee_tmp): + def test_3d_export(self, zarr_tmp, segy_export_tmp): """Test 3D export to IBM and IEEE.""" mdio_to_segy( mdio_path_or_buffer=zarr_tmp.__str__(), - output_segy_path=segy_export_ibm_tmp.__str__(), - out_sample_format="ibm32", - ) - - mdio_to_segy( - mdio_path_or_buffer=zarr_tmp.__str__(), - output_segy_path=segy_export_ieee_tmp.__str__(), - out_sample_format="float32", + output_segy_path=segy_export_tmp.__str__(), ) - def test_ibm_size_equal(self, segy_input, segy_export_ibm_tmp): + def test_size_equal(self, segy_input, segy_export_tmp): """Check if file sizes match on IBM file.""" - assert getsize(segy_input) == getsize(segy_export_ibm_tmp) - - def test_ieee_size_equal(self, segy_input, segy_export_ieee_tmp): - """Check if file sizes match on IEEE file.""" - assert getsize(segy_input) == getsize(segy_export_ieee_tmp) + assert getsize(segy_input) == getsize(segy_export_tmp) - def test_ibm_rand_equal(self, segy_input, segy_export_ibm_tmp): + def test_rand_equal(self, segy_input, segy_export_tmp): """IBM. Is random original traces and headers match round-trip file?""" - with segyio.open(segy_input, ignore_geometry=True) as in_segy: - in_tracecount = in_segy.tracecount - in_text = in_segy.text[0] - in_binary = in_segy.bin - random_indices = np.random.randint(0, in_tracecount, 100) - in_trc_hdrs = [in_segy.header[idx] for idx in random_indices] - in_traces = [in_segy.trace[idx] for idx in random_indices] - - with segyio.open(segy_export_ibm_tmp, ignore_geometry=True) as out_segy: - out_tracecount = out_segy.tracecount - out_text = out_segy.text[0] - out_binary = out_segy.bin - out_trc_hdrs = [out_segy.header[idx] for idx in random_indices] - out_traces = [out_segy.trace[idx] for idx in random_indices] - - assert in_tracecount == out_tracecount - assert in_text == out_text - assert in_binary == out_binary - assert in_trc_hdrs == out_trc_hdrs - npt.assert_array_equal(in_traces, out_traces) - - def test_ieee_rand_equal(self, segy_input, segy_export_ieee_tmp): - """IEEE. Is random original traces and headers match round-trip file?""" - with segyio.open(segy_input, ignore_geometry=True) as in_segy: - in_tracecount = in_segy.tracecount - in_text = in_segy.text[0] - in_binary = dict(in_segy.bin) # Cast to dict bc read-only - in_binary.pop(3225) # Remove format bc comparing IBM / IEEE - random_indices = np.random.randint(0, in_tracecount, 100) - in_trc_hdrs = [in_segy.header[idx] for idx in random_indices] - in_traces = [in_segy.trace[idx] for idx in random_indices] - - with segyio.open(segy_export_ieee_tmp, ignore_geometry=True) as out_segy: - out_tracecount = out_segy.tracecount - out_text = out_segy.text[0] - out_binary = dict(out_segy.bin) # Cast to dict bc read-only - out_binary.pop(3225) # Remove format bc comparing IBM / IEEE - out_trc_hdrs = [out_segy.header[idx] for idx in random_indices] - out_traces = [out_segy.trace[idx] for idx in random_indices] - - assert in_tracecount == out_tracecount - assert in_text == out_text - assert in_binary == out_binary - assert in_trc_hdrs == out_trc_hdrs - npt.assert_array_equal(in_traces, out_traces) + spec = mdio_segy_spec() + + in_segy = SegyFile(segy_input, spec=spec) + out_segy = SegyFile(segy_export_tmp, spec=spec) + + num_traces = in_segy.num_traces + random_indices = list(np.random.randint(0, num_traces, 100)) + in_traces = in_segy.trace[random_indices] + out_traces = out_segy.trace[random_indices] + + assert in_segy.num_traces == out_segy.num_traces + assert in_segy.text_header == out_segy.text_header + assert in_segy.binary_header == out_segy.binary_header + npt.assert_array_equal(in_traces.header, out_traces.header) + npt.assert_array_equal(in_traces.sample, out_traces.sample) diff --git a/tests/unit/test_ibm_ieee.py b/tests/unit/test_ibm_ieee.py deleted file mode 100644 index 14803da0..00000000 --- a/tests/unit/test_ibm_ieee.py +++ /dev/null @@ -1,88 +0,0 @@ -"""Tests for IBM and IEEE floating point conversions. - -Some references for test values -https://en.wikipedia.org/wiki/IBM_hexadecimal_floating-point -https://www.crewes.org/Documents/ResearchReports/2017/CRR201725.pdf -""" - -import numpy as np -import pytest - -from mdio.segy.ibm_float import byteswap_uint32 -from mdio.segy.ibm_float import ibm2ieee -from mdio.segy.ibm_float import ieee2ibm - - -@pytest.mark.parametrize( - "ieee, ibm", - [ - (0.0, 0x00000000), - (-0.0, 0x00000000), - (0.1, 0x40199999), - (-1, 0xC1100000), - (3.141593, 0x413243F7), - (-0.15625, 0xC0280000), - (118.625, 0x4276A000), - (-8521603, 0xC6820783), - (3.4028235e38, 0x60FFFFFF), - (-3.4028235e38, 0xE0FFFFFF), - ([-0.0, 0.1], [0x00000000, 0x40199999]), - ([0.0, 0.1, 3.141593], [0x00000000, 0x40199999, 0x413243F7]), - ([[0.0], [0.1], [3.141593]], [[0x00000000], [0x40199999], [0x413243F7]]), - ], -) -class TestIbmIeee: - """Test conversions, back and forth.""" - - def test_ieee_to_ibm(self, ieee, ibm): - """IEEE to IBM conversion.""" - ieee_fp32 = np.float32(ieee) - actual_ibm = ieee2ibm(ieee_fp32) - expected_ibm = np.uint32(ibm) - np.testing.assert_array_equal(actual_ibm, expected_ibm) - - def test_ibm_to_ieee(self, ieee, ibm): - """IBM to IEEE conversion.""" - expected_ieee = np.float32(ieee) - actual_ibm = np.uint32(ibm) - - # Assert up to 6 decimals (default) - actual_ieee = ibm2ieee(actual_ibm) - np.testing.assert_array_almost_equal(actual_ieee, expected_ieee) - - -@pytest.mark.parametrize("shape", [(1,), (10,), (20, 20), (150, 150)]) -def test_ieee_to_ibm_roundtrip(shape: tuple): - """IEEE to IBM and then back to IEEE conversion.""" - expected_ieee = np.random.randn(*shape).astype("float32") - - actual_ibm = ieee2ibm(expected_ieee) - actual_ieee = ibm2ieee(actual_ibm) - - # Assert up to 6 decimals (default) - np.testing.assert_array_almost_equal(actual_ieee, expected_ieee) - - -@pytest.mark.parametrize( - "original, swapped", - [ - (0x00000000, 0x00000000), - (0xF0000000, 0x000000F0), - (0x000FF000, 0x00F00F00), - (0x0F0F0F0F, 0x0F0F0F0F), - (0x0F0FF0F0F, 0x0F0FFFF0), - (0xABCD1234, 0x3412CDAB), - (0xA1B2C3D4, 0xD4C3B2A1), - (0xAB12CD34, 0x34CD12AB), - ], -) -def test_byteswap(original, swapped): - """Test endian swapping operations.""" - original = np.uint32(original) - expected = np.uint32(swapped) - - actual = byteswap_uint32(original) - original_roundtrip = byteswap_uint32(actual) - - np.testing.assert_array_equal(expected, actual) - np.testing.assert_array_equal(original, original_roundtrip) diff --git a/tests/unit/test_segy_grid_overrides.py b/tests/unit/test_segy_grid_overrides.py index 00354ee2..086ba78a 100644 --- a/tests/unit/test_segy_grid_overrides.py +++ b/tests/unit/test_segy_grid_overrides.py @@ -4,6 +4,7 @@ from typing import Any +import numpy as np import numpy.typing as npt import pytest from numpy import arange @@ -27,7 +28,7 @@ def run_override( grid_overrides: dict[str, Any], index_names: tuple[str, ...], - headers: dict[str, npt.NDArray], + headers: npt.NDArray, chunksize: tuple[int, ...] | None = None, ) -> tuple[dict[str, Any], tuple[str], tuple[int]]: """Initialize and run overrider.""" @@ -35,18 +36,19 @@ def run_override( return overrider.run(headers, index_names, grid_overrides, chunksize) -def get_dims(headers: dict[str, npt.NDArray]) -> list[Dimension]: +def get_dims(headers: npt.NDArray) -> list[Dimension]: """Get list of Dimensions from headers.""" dims = [] - for index_name, index_coords in headers.items(): + for index_name in headers.dtype.names: + index_coords = headers[index_name] dim_unique = unique(index_coords) dims.append(Dimension(coords=dim_unique, name=index_name)) return dims -@pytest.fixture -def mock_streamer_headers() -> dict[str, npt.NDArray]: +@pytest.fixture() +def mock_streamer_headers() -> npt.NDArray: """Generate dictionary of mocked streamer index headers.""" grids = meshgrid(SHOTS, CABLES, RECEIVERS, indexing="ij") permutations = column_stack([grid.ravel() for grid in grids]) @@ -56,12 +58,20 @@ def mock_streamer_headers() -> dict[str, npt.NDArray]: shot_mask = permutations[:, 0] == shot permutations[shot_mask, -1] = arange(1, len(CABLES) * len(RECEIVERS) + 1) - result = dict( - shot_point=permutations[:, 0], - cable=permutations[:, 1], - channel=permutations[:, 2], + hdr_dtype = np.dtype( + { + "names": ["shot_point", "cable", "channel"], + "formats": ["int32", "int32", "int32"], + } ) + n_traces = permutations.shape[0] + result = np.ndarray(dtype=hdr_dtype, shape=n_traces) + + result["shot_point"] = permutations[:, 0] + result["cable"] = permutations[:, 1] + result["channel"] = permutations[:, 2] + return result @@ -70,21 +80,21 @@ class TestAutoGridOverrides: def test_duplicates(self, mock_streamer_headers: dict[str, npt.NDArray]) -> None: """Test the HasDuplicates Grid Override command.""" - index_names = ("shot", "cable") + index_names = ("shot_point", "cable") grid_overrides = {"HasDuplicates": True} # Remove channel header - del mock_streamer_headers["channel"] + streamer_headers = mock_streamer_headers[list(index_names)] chunksize = (4, 4, 8) new_headers, new_names, new_chunks = run_override( grid_overrides, index_names, - mock_streamer_headers, + streamer_headers, chunksize, ) - assert new_names == ("shot", "cable", "trace") + assert new_names == ("shot_point", "cable", "trace") assert new_chunks == (4, 4, 1, 8) dims = get_dims(new_headers) @@ -95,21 +105,21 @@ def test_duplicates(self, mock_streamer_headers: dict[str, npt.NDArray]) -> None def test_non_binned(self, mock_streamer_headers: dict[str, npt.NDArray]) -> None: """Test the NonBinned Grid Override command.""" - index_names = ("shot", "cable") + index_names = ("shot_point", "cable") grid_overrides = {"NonBinned": True, "chunksize": 4} # Remove channel header - del mock_streamer_headers["channel"] + streamer_headers = mock_streamer_headers[list(index_names)] chunksize = (4, 4, 8) new_headers, new_names, new_chunks = run_override( grid_overrides, index_names, - mock_streamer_headers, + streamer_headers, chunksize, ) - assert new_names == ("shot", "cable", "trace") + assert new_names == ("shot_point", "cable", "trace") assert new_chunks == (4, 4, 4, 8) dims = get_dims(new_headers) diff --git a/tests/unit/test_text_header.py b/tests/unit/test_text_header.py deleted file mode 100644 index 434a63aa..00000000 --- a/tests/unit/test_text_header.py +++ /dev/null @@ -1,136 +0,0 @@ -"""Tests for lower level text header modules.""" - -import random -import string -from binascii import hexlify -from binascii import unhexlify - -import pytest - -from mdio.segy.headers_text import ascii_to_ebcdic -from mdio.segy.headers_text import ebcdic_to_ascii -from mdio.segy.headers_text import unwrap_string -from mdio.segy.headers_text import wrap_strings - - -# fmt: off -@pytest.mark.parametrize( - "ascii_str, hex_stream", - [ - ("f", b"86"), ("~", b"a1"), - ("aA", b"81-c1"), ("zZ", b"a9-e9"), - ("@Ac5", b"7c-c1-83-f5"), - (["# 45", "13.2", "J|kX"], b"7b-40-f4-f5-f1-f3-4b-f2-d1-6a-92-e7"), - ], -) -class TestEbcdic: - """Test ASCII/EBCDIC coding.""" - - def test_encode(self, ascii_str, hex_stream): - """Encoding from ASCII to EBCDIC.""" - ebcdic_buffer = ascii_to_ebcdic(ascii_str) - ascii_to_hex = hexlify(ebcdic_buffer, sep="-") - assert ascii_to_hex == hex_stream - - def test_decode(self, ascii_str, hex_stream): - """Decoding from EBCDIC to ASCII.""" - ebcdic_buffer = unhexlify(hex_stream.replace(b"-", b"")) - - if isinstance(ascii_str, list): - rows = len(ascii_str) - cols = len(ascii_str[0]) - else: - rows, cols = 1, len(ascii_str) - - ascii_str = ebcdic_to_ascii(ebcdic_buffer, unwrap=True, rows=rows, cols=cols) - print(ascii_str) - - -@pytest.mark.parametrize( - "rows, cols, wrapped, unwrapped", - [ - (1, 1, 'a', ['a']), - (1, 2, '12', ['12']), - (2, 3, 'ab~|ef', ['ab~', '|ef']), - (4, 3, 'a1b2c3d4e5f6', ['a1b', '2c3', 'd4e', '5f6']), - ], -) -class TestWrapping: - """String wrappers and unwrappers.""" - - def test_wrap(self, rows, cols, wrapped, unwrapped): - """Test from list of strings to a flat string.""" - actual = wrap_strings(unwrapped) - assert wrapped == actual - assert len(wrapped) == rows * cols - - def test_unwrap(self, rows, cols, wrapped, unwrapped): - """Test flat string to list of strings.""" - actual = unwrap_string(wrapped, rows, cols) - assert unwrapped == actual - assert len(unwrapped) == rows - assert len(unwrapped[0]) == cols - - def test_wrong_length_exception(self, rows, cols, wrapped, unwrapped): - """Test if we raise the exception when rows/cols don't match size.""" - rows += 1 - cols += 1 - with pytest.raises(ValueError): - assert unwrapped == unwrap_string(wrapped, rows, cols) - - -# fmt: on -@pytest.mark.parametrize( - "rows, cols, upper_prob, lower_prob, digits_prob, symbol_prob, space_prob", - [ - (40, 80, 0.5, 1, 0.25, 0.05, 10), - (15, 25, 0.2, 1.5, 0.55, 0.1, 5), - (30, 60, 0.3, 1.2, 0.35, 0.15, 6), - ], -) -def test_roundtrip( - rows, - cols, - upper_prob, - lower_prob, - digits_prob, - symbol_prob, - space_prob, -): - """Test converting randomly generated ASCII / EBCDIC and back.""" - # Get all kinds of letters, numbers, and symbols - upper = string.ascii_uppercase - lower = string.ascii_lowercase - digits = string.digits - symbols = string.punctuation - whitespace = " " - - # Define probabilities (weights) for each character for random sampling - upper_prob = [upper_prob] * len(upper) - lower_prob = [lower_prob] * len(lower) - digits_prob = [digits_prob] * len(digits) - symbol_prob = [symbol_prob] * len(symbols) - space_prob = [space_prob] * len(whitespace) - - all_chars = upper + lower + digits + symbols + whitespace - all_probs = upper_prob + lower_prob + digits_prob + symbol_prob + space_prob - - # Generate an "unwrapped" text header in ASCII - text_header = [] - for idx in range(1, rows + 1): - line_header = r"C{line_no:02d}" - random_string = random.choices( # noqa: S311 - all_chars, weights=all_probs, k=cols - 4 - ) - random_string = r"".join(random_string) - line_data = r" ".join([line_header.format(line_no=idx), random_string]) - text_header.append(line_data) - - # Make EBCDIC, then come back to ASCII - ebcdic_buf = ascii_to_ebcdic(text_header) - round_ascii = ebcdic_to_ascii(ebcdic_buf, unwrap=False) - round_ascii_unwrap = ebcdic_to_ascii(ebcdic_buf, unwrap=True, rows=rows, cols=cols) - - # Testing both wrapped and unwrapped - assert wrap_strings(text_header) == round_ascii - assert text_header == round_ascii_unwrap