From 7605599720b41faf02c26e3b488744e7d0ddd3d1 Mon Sep 17 00:00:00 2001 From: mike-gangl Date: Thu, 16 Mar 2023 14:31:45 -0700 Subject: [PATCH 01/22] initial implementaiton of subset code --- poetry.lock | 379 +++++++++++++++++++++------ pyproject.toml | 3 + subscriber/podaac_access.py | 108 +++++++- subscriber/podaac_data_downloader.py | 95 +++++-- tests/.harmony-example-json | 1 + tests/test_subsetter_regression.py | 35 +++ 6 files changed, 510 insertions(+), 111 deletions(-) create mode 100644 tests/.harmony-example-json create mode 100644 tests/test_subsetter_regression.py diff --git a/poetry.lock b/poetry.lock index 72a359c..8661134 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,20 +1,22 @@ [[package]] name = "attrs" -version = "22.1.0" +version = "22.2.0" description = "Classes Without Boilerplate" category = "dev" optional = false -python-versions = ">=3.5" +python-versions = ">=3.6" [package.extras] -dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "mypy (>=0.900,!=0.940)", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"] -docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] -tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "mypy (>=0.900,!=0.940)", "pytest-mypy-plugins", "zope.interface", "cloudpickle"] -tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "mypy (>=0.900,!=0.940)", "pytest-mypy-plugins", "cloudpickle"] +cov = ["attrs", "coverage-enable-subprocess", "coverage[toml] (>=5.3)"] +dev = ["attrs"] +docs = ["furo", "sphinx", "myst-parser", "zope.interface", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier"] +tests = ["attrs", "zope.interface"] +tests-no-zope = ["hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist", "cloudpickle", "mypy (>=0.971,<0.990)", "pytest-mypy-plugins"] +tests_no_zope = ["hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist", "cloudpickle", "mypy (>=0.971,<0.990)", "pytest-mypy-plugins"] [[package]] name = "certifi" -version = "2022.9.24" +version = "2022.12.7" description = "Python package for providing Mozilla's CA Bundle." category = "main" optional = false @@ -22,22 +24,41 @@ python-versions = ">=3.6" [[package]] name = "charset-normalizer" -version = "2.1.1" +version = "3.1.0" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." category = "main" optional = false -python-versions = ">=3.6.0" - -[package.extras] -unicode_backport = ["unicodedata2"] +python-versions = ">=3.7.0" [[package]] name = "colorama" -version = "0.4.5" +version = "0.4.6" description = "Cross-platform colored terminal text." category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" + +[[package]] +name = "curlify" +version = "2.2.1" +description = "Library to convert python requests object to curl command." +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +requests = "*" + +[[package]] +name = "exceptiongroup" +version = "1.1.1" +description = "Backport of PEP 654 (exception groups)" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.extras] +test = ["pytest (>=6)"] [[package]] name = "flake8" @@ -53,6 +74,25 @@ mccabe = ">=0.6.0,<0.7.0" pycodestyle = ">=2.8.0,<2.9.0" pyflakes = ">=2.4.0,<2.5.0" +[[package]] +name = "harmony-py" +version = "0.4.5" +description = "The NASA Harmony Python library" +category = "main" +optional = false +python-versions = ">=3.6, <4" + +[package.dependencies] +curlify = ">=2.2,<3.0" +progressbar2 = ">=3.5,<4.0" +python-dateutil = ">=2.7.5,<2.8.0" +python-dotenv = ">=0.1,<1.0" +requests = ">=2.2,<3.0" +sphinxcontrib-napoleon = ">=0.7" + +[package.extras] +dev = ["autopep8 (>=1.4,<2.0)", "camel-case-switcher (>=2.0,<3.0)", "coverage (>=5.4,<6.0)", "flake8 (>=5.0.4,<5.1.0)", "hypothesis (>=6.2,<7.0)", "mypy (>=0.812,<1.0)", "m2r2 (>=0.2,<1.0)", "nose (>=1.3,<2.0)", "PyYAML (>=5.4,<6.0)", "pytest (>=6.2,<7.0)", "pytest-cov (>=2.11,<3.0)", "pytest-mock (>=3.5,<4.0)", "pytest-watch (>=4.2,<5.0)", "responses (>=0.12,<1.0)", "setuptools (>=54.2)", "sphinx (>=3.4,<4.0)", "wheel (>=0.36)"] + [[package]] name = "idna" version = "3.4" @@ -79,11 +119,11 @@ testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytes [[package]] name = "iniconfig" -version = "1.1.1" -description = "iniconfig: brain-dead simple config-ini parsing" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" category = "dev" optional = false -python-versions = "*" +python-versions = ">=3.7" [[package]] name = "mccabe" @@ -95,14 +135,11 @@ python-versions = "*" [[package]] name = "packaging" -version = "21.3" +version = "23.0" description = "Core utilities for Python packages" category = "dev" optional = false -python-versions = ">=3.6" - -[package.dependencies] -pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" +python-versions = ">=3.7" [[package]] name = "pluggy" @@ -120,12 +157,31 @@ testing = ["pytest-benchmark", "pytest"] dev = ["tox", "pre-commit"] [[package]] -name = "py" -version = "1.11.0" -description = "library with cross-python path, ini-parsing, io, code, log facilities" -category = "dev" +name = "pockets" +version = "0.9.1" +description = "A collection of helpful Python tools!" +category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = "*" + +[package.dependencies] +six = ">=1.5.2" + +[[package]] +name = "progressbar2" +version = "3.55.0" +description = "A Python Progressbar library to provide visual (yet text based) progress to long running operations." +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +python-utils = ">=2.3.0" +six = "*" + +[package.extras] +docs = ["sphinx (>=1.7.4)"] +tests = ["flake8 (>=3.7.7)", "pytest (>=4.6.9)", "pytest-cov (>=2.6.1)", "freezegun (>=0.3.11)", "sphinx (>=1.8.5)"] [[package]] name = "pycodestyle" @@ -143,20 +199,9 @@ category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -[[package]] -name = "pyparsing" -version = "3.0.9" -description = "pyparsing module - Classes and methods to define and execute parsing grammars" -category = "dev" -optional = false -python-versions = ">=3.6.8" - -[package.extras] -diagrams = ["railroad-diagrams", "jinja2"] - [[package]] name = "pytest" -version = "7.1.3" +version = "7.2.2" description = "pytest: simple powerful testing with Python" category = "dev" optional = false @@ -165,19 +210,19 @@ python-versions = ">=3.7" [package.dependencies] attrs = ">=19.2.0" colorama = {version = "*", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} iniconfig = "*" packaging = "*" pluggy = ">=0.12,<2.0" -py = ">=1.8.2" -tomli = ">=1.0.0" +tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} [package.extras] testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] [[package]] name = "pytest-mock" -version = "3.9.0" +version = "3.10.0" description = "Thin-wrapper around the mock package for easier use with pytest" category = "dev" optional = false @@ -189,9 +234,47 @@ pytest = ">=5.0" [package.extras] dev = ["pre-commit", "tox", "pytest-asyncio"] +[[package]] +name = "python-dateutil" +version = "2.7.5" +description = "Extensions to the standard Python datetime module" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "python-dotenv" +version = "0.21.1" +description = "Read key-value pairs from a .env file and set them as environment variables" +category = "main" +optional = false +python-versions = ">=3.7" + +[package.extras] +cli = ["click (>=5.0)"] + +[[package]] +name = "python-utils" +version = "3.5.2" +description = "Python Utils is a module with some convenient utilities not included with the standard Python install" +category = "main" +optional = false +python-versions = ">3.6.0" + +[package.dependencies] +typing-extensions = {version = "*", markers = "python_version < \"3.8\""} + +[package.extras] +docs = ["mock", "sphinx", "python-utils"] +loguru = ["loguru"] +tests = ["flake8", "pytest", "pytest-cov", "pytest-mypy", "pytest-asyncio", "sphinx", "types-setuptools", "loguru"] + [[package]] name = "requests" -version = "2.28.1" +version = "2.28.2" description = "Python HTTP for Humans." category = "main" optional = false @@ -199,7 +282,7 @@ python-versions = ">=3.7, <4" [package.dependencies] certifi = ">=2017.4.17" -charset-normalizer = ">=2,<3" +charset-normalizer = ">=2,<4" idna = ">=2.5,<4" urllib3 = ">=1.21.1,<1.27" @@ -207,9 +290,29 @@ urllib3 = ">=1.21.1,<1.27" socks = ["PySocks (>=1.5.6,!=1.5.7)"] use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"] +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" + +[[package]] +name = "sphinxcontrib-napoleon" +version = "0.7" +description = "Sphinx \"napoleon\" extension." +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +pockets = ">=0.3" +six = ">=1.5.2" + [[package]] name = "tenacity" -version = "8.1.0" +version = "8.2.2" description = "Retry code until it succeeds" category = "main" optional = false @@ -228,19 +331,19 @@ python-versions = ">=3.7" [[package]] name = "typing-extensions" -version = "4.3.0" +version = "4.5.0" description = "Backported and Experimental Type Hints for Python 3.7+" -category = "dev" +category = "main" optional = false python-versions = ">=3.7" [[package]] name = "urllib3" -version = "1.26.12" +version = "1.26.15" description = "HTTP library with thread-safe connection pooling, file post, and more." category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, <4" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" [package.extras] brotli = ["brotlicffi (>=0.8.0)", "brotli (>=1.0.9)", "brotlipy (>=0.6.0)"] @@ -249,42 +352,126 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [[package]] name = "zipp" -version = "3.8.1" +version = "3.15.0" description = "Backport of pathlib-compatible object wrapper for zip files" category = "dev" optional = false python-versions = ">=3.7" [package.extras] -docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)", "jaraco.tidelift (>=1.4)"] -testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.3)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)"] +docs = ["sphinx (>=3.5)", "jaraco.packaging (>=9)", "rst.linker (>=1.9)", "furo", "sphinx-lint", "jaraco.tidelift (>=1.4)"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "flake8 (<5)", "pytest-cov", "pytest-enabler (>=1.3)", "jaraco.itertools", "jaraco.functools", "more-itertools", "big-o", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)", "pytest-flake8"] [metadata] lock-version = "1.1" python-versions = "^3.7" -content-hash = "c5ece7741408cb266fe803842b66f646317dc3a384e9c54ecbe66a14ce895fed" +content-hash = "9d493b26dc378d841221aa3a93ccd4f98776152fcc0cb53f6a3921ffce014494" [metadata.files] attrs = [ - {file = "attrs-22.1.0-py2.py3-none-any.whl", hash = "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c"}, - {file = "attrs-22.1.0.tar.gz", hash = "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6"}, + {file = "attrs-22.2.0-py3-none-any.whl", hash = "sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836"}, + {file = "attrs-22.2.0.tar.gz", hash = "sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99"}, ] certifi = [ - {file = "certifi-2022.9.24-py3-none-any.whl", hash = "sha256:90c1a32f1d68f940488354e36370f6cca89f0f106db09518524c88d6ed83f382"}, - {file = "certifi-2022.9.24.tar.gz", hash = "sha256:0d9c601124e5a6ba9712dbc60d9c53c21e34f5f641fe83002317394311bdce14"}, + {file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"}, + {file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"}, ] charset-normalizer = [ - {file = "charset-normalizer-2.1.1.tar.gz", hash = "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845"}, - {file = "charset_normalizer-2.1.1-py3-none-any.whl", hash = "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f"}, + {file = "charset-normalizer-3.1.0.tar.gz", hash = "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-win32.whl", hash = "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-win32.whl", hash = "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-win32.whl", hash = "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-win32.whl", hash = "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b"}, + {file = "charset_normalizer-3.1.0-py3-none-any.whl", hash = "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d"}, ] colorama = [ - {file = "colorama-0.4.5-py2.py3-none-any.whl", hash = "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da"}, - {file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"}, + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] +curlify = [ + {file = "curlify-2.2.1.tar.gz", hash = "sha256:0d3f02e7235faf952de8ef45ef469845196d30632d5838bcd5aee217726ddd6d"}, +] +exceptiongroup = [ + {file = "exceptiongroup-1.1.1-py3-none-any.whl", hash = "sha256:232c37c63e4f682982c8b6459f33a8981039e5fb8756b2074364e5055c498c9e"}, + {file = "exceptiongroup-1.1.1.tar.gz", hash = "sha256:d484c3090ba2889ae2928419117447a14daf3c1231d5e30d0aae34f354f01785"}, ] flake8 = [ {file = "flake8-4.0.1-py2.py3-none-any.whl", hash = "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d"}, {file = "flake8-4.0.1.tar.gz", hash = "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d"}, ] +harmony-py = [ + {file = "harmony-py-0.4.5.tar.gz", hash = "sha256:0cf1a24cc7e29fe4b7338caf235e9116145fe6677d642ad839c8bd3ddc15d2ae"}, + {file = "harmony_py-0.4.5-py3-none-any.whl", hash = "sha256:1dd982e3475fc6d12025d89f04cab08fc5faf8d6d2369286e03368c8ce1762e5"}, +] idna = [ {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, @@ -294,24 +481,28 @@ importlib-metadata = [ {file = "importlib_metadata-4.2.0.tar.gz", hash = "sha256:b7e52a1f8dec14a75ea73e0891f3060099ca1d8e6a462a4dff11c3e119ea1b31"}, ] iniconfig = [ - {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, - {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] mccabe = [ {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, ] packaging = [ - {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, - {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, + {file = "packaging-23.0-py3-none-any.whl", hash = "sha256:714ac14496c3e68c99c29b00845f7a2b85f3bb6f1078fd9f72fd20f0570002b2"}, + {file = "packaging-23.0.tar.gz", hash = "sha256:b6ad297f8907de0fa2fe1ccbd26fdaf387f5f47c7275fedf8cce89f99446cf97"}, ] pluggy = [ {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, ] -py = [ - {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, - {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, +pockets = [ + {file = "pockets-0.9.1-py2.py3-none-any.whl", hash = "sha256:68597934193c08a08eb2bf6a1d85593f627c22f9b065cc727a4f03f669d96d86"}, + {file = "pockets-0.9.1.tar.gz", hash = "sha256:9320f1a3c6f7a9133fe3b571f283bcf3353cd70249025ae8d618e40e9f7e92b3"}, +] +progressbar2 = [ + {file = "progressbar2-3.55.0-py2.py3-none-any.whl", hash = "sha256:e98fee031da31ab9138fd8dd838ac80eafba82764eb75a43d25e3ca622f47d14"}, + {file = "progressbar2-3.55.0.tar.gz", hash = "sha256:86835d1f1a9317ab41aeb1da5e4184975e2306586839d66daf63067c102f8f04"}, ] pycodestyle = [ {file = "pycodestyle-2.8.0-py2.py3-none-any.whl", hash = "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20"}, @@ -321,39 +512,55 @@ pyflakes = [ {file = "pyflakes-2.4.0-py2.py3-none-any.whl", hash = "sha256:3bb3a3f256f4b7968c9c788781e4ff07dce46bdf12339dcda61053375426ee2e"}, {file = "pyflakes-2.4.0.tar.gz", hash = "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c"}, ] -pyparsing = [ - {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, - {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, -] pytest = [ - {file = "pytest-7.1.3-py3-none-any.whl", hash = "sha256:1377bda3466d70b55e3f5cecfa55bb7cfcf219c7964629b967c37cf0bda818b7"}, - {file = "pytest-7.1.3.tar.gz", hash = "sha256:4f365fec2dff9c1162f834d9f18af1ba13062db0c708bf7b946f8a5c76180c39"}, + {file = "pytest-7.2.2-py3-none-any.whl", hash = "sha256:130328f552dcfac0b1cec75c12e3f005619dc5f874f0a06e8ff7263f0ee6225e"}, + {file = "pytest-7.2.2.tar.gz", hash = "sha256:c99ab0c73aceb050f68929bc93af19ab6db0558791c6a0715723abe9d0ade9d4"}, ] pytest-mock = [ - {file = "pytest-mock-3.9.0.tar.gz", hash = "sha256:c899a0dcc8a5f22930acd020b500abd5f956911f326864a3b979e4866e14da82"}, - {file = "pytest_mock-3.9.0-py3-none-any.whl", hash = "sha256:1a1b9264224d026932d6685a0f9cef3b61d91563c3e74af9fe5afb2767e13812"}, + {file = "pytest-mock-3.10.0.tar.gz", hash = "sha256:fbbdb085ef7c252a326fd8cdcac0aa3b1333d8811f131bdcc701002e1be7ed4f"}, + {file = "pytest_mock-3.10.0-py3-none-any.whl", hash = "sha256:f4c973eeae0282963eb293eb173ce91b091a79c1334455acfac9ddee8a1c784b"}, +] +python-dateutil = [ + {file = "python-dateutil-2.7.5.tar.gz", hash = "sha256:88f9287c0174266bb0d8cedd395cfba9c58e87e5ad86b2ce58859bc11be3cf02"}, + {file = "python_dateutil-2.7.5-py2.py3-none-any.whl", hash = "sha256:063df5763652e21de43de7d9e00ccf239f953a832941e37be541614732cdfc93"}, +] +python-dotenv = [ + {file = "python-dotenv-0.21.1.tar.gz", hash = "sha256:1c93de8f636cde3ce377292818d0e440b6e45a82f215c3744979151fa8151c49"}, + {file = "python_dotenv-0.21.1-py3-none-any.whl", hash = "sha256:41e12e0318bebc859fcc4d97d4db8d20ad21721a6aa5047dd59f090391cb549a"}, +] +python-utils = [ + {file = "python-utils-3.5.2.tar.gz", hash = "sha256:68198854fc276bc4b2403b261703c218e01ef564dcb072a7096ed9ea7aa5130c"}, + {file = "python_utils-3.5.2-py2.py3-none-any.whl", hash = "sha256:8bfefc3430f1c48408fa0e5958eee51d39840a5a987c2181a579e99ab6fe5ca6"}, ] requests = [ - {file = "requests-2.28.1-py3-none-any.whl", hash = "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"}, - {file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"}, + {file = "requests-2.28.2-py3-none-any.whl", hash = "sha256:64299f4909223da747622c030b781c0d7811e359c37124b4bd368fb8c6518baa"}, + {file = "requests-2.28.2.tar.gz", hash = "sha256:98b1b2782e3c6c4904938b84c0eb932721069dfdb9134313beff7c83c2df24bf"}, +] +six = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] +sphinxcontrib-napoleon = [ + {file = "sphinxcontrib-napoleon-0.7.tar.gz", hash = "sha256:407382beed396e9f2d7f3043fad6afda95719204a1e1a231ac865f40abcbfcf8"}, + {file = "sphinxcontrib_napoleon-0.7-py2.py3-none-any.whl", hash = "sha256:711e41a3974bdf110a484aec4c1a556799eb0b3f3b897521a018ad7e2db13fef"}, ] tenacity = [ - {file = "tenacity-8.1.0-py3-none-any.whl", hash = "sha256:35525cd47f82830069f0d6b73f7eb83bc5b73ee2fff0437952cedf98b27653ac"}, - {file = "tenacity-8.1.0.tar.gz", hash = "sha256:e48c437fdf9340f5666b92cd7990e96bc5fc955e1298baf4a907e3972067a445"}, + {file = "tenacity-8.2.2-py3-none-any.whl", hash = "sha256:2f277afb21b851637e8f52e6a613ff08734c347dc19ade928e519d7d2d8569b0"}, + {file = "tenacity-8.2.2.tar.gz", hash = "sha256:43af037822bd0029025877f3b2d97cc4d7bb0c2991000a3d59d71517c5c969e0"}, ] tomli = [ {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] typing-extensions = [ - {file = "typing_extensions-4.3.0-py3-none-any.whl", hash = "sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02"}, - {file = "typing_extensions-4.3.0.tar.gz", hash = "sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6"}, + {file = "typing_extensions-4.5.0-py3-none-any.whl", hash = "sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4"}, + {file = "typing_extensions-4.5.0.tar.gz", hash = "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb"}, ] urllib3 = [ - {file = "urllib3-1.26.12-py2.py3-none-any.whl", hash = "sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997"}, - {file = "urllib3-1.26.12.tar.gz", hash = "sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e"}, + {file = "urllib3-1.26.15-py2.py3-none-any.whl", hash = "sha256:aa751d169e23c7479ce47a0cb0da579e3ede798f994f5816a74e4f4500dcea42"}, + {file = "urllib3-1.26.15.tar.gz", hash = "sha256:8a388717b9476f934a21484e8c8e61875ab60644d29b9b39e11e4b9dc1c6b305"}, ] zipp = [ - {file = "zipp-3.8.1-py3-none-any.whl", hash = "sha256:47c40d7fe183a6f21403a199b3e4192cca5774656965b0a4988ad2f8feb5f009"}, - {file = "zipp-3.8.1.tar.gz", hash = "sha256:05b45f1ee8f807d0cc928485ca40a07cb491cf092ff587c0df9cb1fd154848d2"}, + {file = "zipp-3.15.0-py3-none-any.whl", hash = "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556"}, + {file = "zipp-3.15.0.tar.gz", hash = "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b"}, ] diff --git a/pyproject.toml b/pyproject.toml index f1bbb6b..1f2b783 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,6 +15,9 @@ packages = [ python = "^3.7" requests = "^2.27.1" tenacity = "^8.0.1" +harmony-py = "^0.4.5" + + [tool.poetry.dev-dependencies] pytest = "^7.1.2" diff --git a/subscriber/podaac_access.py b/subscriber/podaac_access.py index 12c9e44..8de0a5b 100644 --- a/subscriber/podaac_access.py +++ b/subscriber/podaac_access.py @@ -6,7 +6,7 @@ from datetime import datetime from http.cookiejar import CookieJar from os import makedirs -from os.path import isdir, basename, join, splitext +from os.path import isdir, basename, join, splitext, isfile from urllib import request from typing import Dict from urllib import request @@ -19,8 +19,11 @@ from datetime import datetime import time from requests.auth import HTTPBasicAuth - - +import harmony +import datetime as dt +import os +import concurrent.futures +from dateutil.parser import * import requests @@ -32,6 +35,8 @@ extensions = ["\\.nc", "\\.h5", "\\.zip", "\\.tar.gz", "\\.tiff"] edl = "urs.earthdata.nasa.gov" cmr = "cmr.earthdata.nasa.gov" +graph = "graphql.earthdata.nasa.gov" +graph_url = "https://"+graph+"/api" token_url = "https://" + edl + "/api/users" @@ -558,3 +563,100 @@ def create_citation_file(short_name, provider, data_path, token=None, verbose=Fa with open(data_path + "/" + short_name + ".citation.txt", "w") as text_file: text_file.write(citation) + +# Function to determine if a collection has an applicable harmony subsetter +def is_collection_harmony_subsettable(concept_id, token=None): + graph_query_template = ''' + query Collection { + collection(conceptId: "$TEMPLATE_CONCEPT_ID") { + services{ + items { + name + serviceKeywords + type + } + } + } + } + ''' + query = graph_query_template.replace("$TEMPLATE_CONCEPT_ID",concept_id) + headers = {} + if token: + headers = {"Authorization" : "Bearer " + token} + r = requests.post(graph_url, json={'query': query}, headers=headers, timeout=(10,60)) + collection_services = r.json()['data']['collection']['services']['items'] + harmony_subsetter = False + if collection_services is None: + return False + for svc in collection_services: + if svc['type'] == "Harmony": + for kw in svc['serviceKeywords']: + if kw['serviceTerm'] == "SUBSETTING/SUPERSETTING": + harmony_subsetter = True + + return harmony_subsetter + +def get_harmony_file(data_dir): + if isfile(data_dir + "/.harmony"): + return data_dir + "/.harmony" + return None + +def find_harmony_runs(collection, bbox, starttime, endtime, output_dir, granules=None,): + harmony_file = get_harmony_file(output_dir) + if harmony_file is None: + return None + else: + try: + with open(harmony_file, "r") as f: + harmony_json = json.load(f) + for x in harmony_json: + if x["collection_id"] == collection and x['starttime'] == starttime and x['endtime'] == endtime and x['bbox'] == bbox: + return x['jobid'] + + except FileNotFoundError: + logging.warning("No .update in the data directory. (Is this the first run?)") + return None + +def save_harmony_run(collection, bbox, starttime, endtime, job_id, output_dir, granules=None,): + harmony_file = get_harmony_file(output_dir) + harmony_json = [] + if harmony_file: + f = open(harmony_file, "r") + harmony_json = json.load(f) + f.close() + harmony_run = {} + harmony_run["collection_id"] = collection + harmony_run['starttime'] = starttime + harmony_run['endtime'] = endtime + harmony_run['bbox'] = bbox + harmony_run['jobid'] = job_id + harmony_json.append(harmony_run) + + with open(output_dir + "/.harmony", "w") as outfile: + json.dump(harmony_json, outfile) + +# Function to utilize Harmony for subsetting a collection +def subset(concept_id, bbox, starttime, stoptime, output_dir, granules=None): + + harmony_client = harmony.Client() + bbox_ary = [float(x) for x in bbox.split(",")] + collection = harmony.Collection(id=concept_id) + request = harmony.Request( + collection=collection, + spatial=harmony.BBox(bbox_ary[0], bbox_ary[1], bbox_ary[2], bbox_ary[3]), + temporal={ + 'start': isoparse(starttime), + 'stop': isoparse(stoptime) + } + ) + request.is_valid() + job_id = harmony_client.submit(request) + return job_id + + +def download_subsetted_files(job_id, output_dir, force_download = False): + harmony_client = harmony.Client() + iter = harmony_client.iterator(job_id, output_dir, force_download) + os.environ['VERBOSE'] = 'true' + futures = list(map(lambda x: x['path'], iter)) + (done_futures, _) = concurrent.futures.wait(futures) diff --git a/subscriber/podaac_data_downloader.py b/subscriber/podaac_data_downloader.py index 11ab835..b8eda80 100755 --- a/subscriber/podaac_data_downloader.py +++ b/subscriber/podaac_data_downloader.py @@ -107,8 +107,8 @@ def create_parser(): parser.add_argument("--limit", dest="limit", default=None, type=int, help="Integer limit for number of granules to download. Useful in testing. Defaults to no limit.") # noqa E501 - parser.add_argument("--dry-run", dest="dry_run", action="store_true", help="Search and identify files to download, but do not actually download them") # noqa E501 - + parser.add_argument("--dry-run", dest="dry_run", action="store_true", help="Search and identify files to download, but do not actually download them.") # noqa E501 + parser.add_argument("--subset", dest="subset", action="store_true", help="Subset the data via Harmony calls.") # noqa E501 return parser @@ -120,7 +120,6 @@ def run(args=None): try: pa.validate(args) - # download specific validations # cannot specify all thre options (start, end, cycle) # must specify start/end togeher @@ -134,6 +133,51 @@ def run(args=None): pa.setup_earthdata_login_auth(edl) token = pa.get_token(token_url) + data_path = args.outputDirectory + if not isdir(data_path): + logging.info("NOTE: Making new data directory at " + data_path + "(This is the first run.)") + makedirs(data_path, exist_ok=True) + + + subsettable = False + if args.subset: + #get the collection info + params = [ + ('provider', args.provider), + ('ShortName', args.collection) + ] + if token is not None: + params.append(('token', token)) + + # handle errors here + collection_id = pa.get_cmr_collections(params, args.verbose)['items'][0]["meta"]["concept-id"] + subsettable = pa.is_collection_harmony_subsettable(collection_id) + if not subsettable: + logging.info("Collection is not harmony subsettable, proceeding with traditional download") + subsettable = False #i'll set it a 3rd time if it makes me comfortable... + else: + subsettable = True + + + # Traditional downloader + if not subsettable: + success_cnt = cmr_downloader(args, token, data_path) + else: + success_cnt = subset(collection_id, args, token, data_path) + + logging.info("Success Count: " + str(success_cnt)) + + #create citation file if success > 0 + if success_cnt > 0: + try: + logging.debug("Creating citation file.") + pa.create_citation_file(args.collection, args.provider, data_path, token, args.verbose) + except: + logging.debug("Error generating citation",exc_info=True) + logging.info("END\n\n") + + +def cmr_downloader(args, token, data_path): provider = args.provider start_date_time = args.startDate end_date_time = args.endDate @@ -142,14 +186,11 @@ def run(args=None): extensions = args.extensions process_cmd = args.process_cmd granule=args.granulename - data_path = args.outputDirectory download_limit = None if args.limit is not None and args.limit > 0: download_limit = args.limit - if args.offset: - ts_shift = timedelta(hours=int(args.offset)) # Error catching for output directory specifications # Must specify -d output path or one time-based output directory flag @@ -159,11 +200,8 @@ def run(args=None): 'Please specify exactly one flag ' 'from -dc, -dy, -dydoy, or -dymd') - # This cell will replace the timestamp above with the one read from the `.update` file in the data directory, if it exists. - - if not isdir(data_path): - logging.info("NOTE: Making new data directory at " + data_path + "(This is the first run.)") - makedirs(data_path, exist_ok=True) + if args.offset: + ts_shift = timedelta(hours=int(args.offset)) if search_cycles is not None: cmr_cycles = search_cycles @@ -275,9 +313,7 @@ def run(args=None): for download in downloads[:download_limit]: logging.info(download) logging.info("Dry-run option specific. Exiting.") - return - - + return 0 # NEED TO REFACTOR THIS, A LOT OF STUFF in here # Finish by downloading the files to the data directory in a loop. @@ -320,17 +356,32 @@ def run(args=None): logging.info("Downloaded Files: " + str(success_cnt)) logging.info("Failed Files: " + str(failure_cnt)) logging.info("Skipped Files: " + str(skip_cnt)) + return success_cnt - #create citation file if success > 0 - if success_cnt > 0: - try: - pa.create_citation_file(short_name, provider, data_path, token, args.verbose) - except: - logging.debug("Error generating citation",exc_info=True) - logging.info("END\n\n") - +def subset(collection_id, args, token, data_path): + provider = args.provider + start_date_time = args.startDate + end_date_time = args.endDate + search_cycles = args.search_cycles + short_name = args.collection + extensions = args.extensions + process_cmd = args.process_cmd + granule=args.granulename + download_limit = None + if args.limit is not None and args.limit > 0: + download_limit = args.limit + success_cnt = 0 + job_id = pa.find_harmony_runs(collection_id, args.bbox, start_date_time, end_date_time, data_path, None) + if not job_id: + job_id = pa.subset(collection_id, args.bbox, start_date_time, end_date_time, data_path) + pa.save_harmony_run(collection_id, args.bbox, start_date_time, end_date_time, job_id, data_path, None) + else: + logging.info("Resuming existing harmony job id...") + pa.download_subsetted_files(job_id,data_path, args.force) + success_cnt = 1 + return success_cnt def main(): log_level = os.environ.get('PODAAC_LOGLEVEL', 'INFO').upper() diff --git a/tests/.harmony-example-json b/tests/.harmony-example-json new file mode 100644 index 0000000..a6ed219 --- /dev/null +++ b/tests/.harmony-example-json @@ -0,0 +1 @@ +[{"collection_id": "C1940473819-POCLOUD", "starttime": "2020-06-01T00:46:02Z", "endtime": "2020-06-01T10:46:02Z", "bbox": "-165,52,-140,77", "jobid": "5d759b99-822d-4eaa-a692-20c5ec66c8ec"}, {"collection_id": "C1940473819-POCLOUD", "starttime": "2020-06-01T00:46:02Z", "endtime": "2020-06-01T10:46:02Z", "bbox": "-165,52,-140,77", "jobid": "5d759b99-822d-4eaa-a692-20c5ec66c8"}, {"collection_id": "C1940473819-POCLOUD", "starttime": "2020-06-01T00:46:02Z", "endtime": "2020-06-01T10:46:02Z", "bbox": "-165,52,-140,77", "jobid": "5d759b99-822d-4eaa-a692-20c5ec66c8"}] \ No newline at end of file diff --git a/tests/test_subsetter_regression.py b/tests/test_subsetter_regression.py new file mode 100644 index 0000000..793bd64 --- /dev/null +++ b/tests/test_subsetter_regression.py @@ -0,0 +1,35 @@ +import pytest +import os +from os.path import exists +from subscriber import podaac_data_downloader as pdd +import shutil +from pathlib import Path + +# REGRESSION TEST CURRENTLY REQUIRES A .NETRC file for CMR/Data Download + +def create_downloader_args(args): + parser = pdd.create_parser() + args2 = parser.parse_args(args) + return args2 + + +# No subsetter +# -c VIIRS_N20-STAR-L2P-v2.80 -d ./data -b="52,52,55,55" -sd 2020-06-01T00:46:02Z -ed 2020-06-02T00:46:02Z --verbose --subset --limit 1 + +# Valid Subsetters +# -c MODIS_A-JPL-L2P-v2019.0 -d ./data -b="52,52,55,55" -sd 2020-06-01T00:46:02Z -ed 2020-06-02T00:46:02Z --verbose --subset --limit 1 +# -c AMSR2-REMSS-L2P-v8.2 -d ./data -b="52,52,55,55" -sd 2020-06-01T00:46:02Z -ed 2020-06-02T00:46:02Z --verbose --subset --limit 1 + + +#Test the downlaoder on MUR25 data for start/stop/, yyyy/mmm/dd dir structure, +# and offset. Running it a second time to ensure it downlaods the files again- +# the downloader doesn't care about updates. +@pytest.mark.regression +def test_subset_MUR_by_name(): + shutil.rmtree('./MUR25-JPL-L4-GLOB-v04.2', ignore_errors=True) + args2 = create_downloader_args('-c MUR25-JPL-L4-GLOB-v04.2 -d ./MUR25-JPL-L4-GLOB-v04.2 -gr 20221206090000-JPL-L4_GHRSST-SSTfnd-MUR25-GLOB-v02.0-fv04.2.nc --verbose'.split()) + pdd.run(args2) + # So running the test in parallel, sometimes we get a 401 on the token... + # Let's ensure we're only looking for data files here + assert len([name for name in os.listdir('./MUR25-JPL-L4-GLOB-v04.2') if os.path.isfile('./MUR25-JPL-L4-GLOB-v04.2/' + name) and "citation.txt" not in name ])==1 + shutil.rmtree('./MUR25-JPL-L4-GLOB-v04.2') From c69ed980446da70b68cacb99ee989d87f1be2790 Mon Sep 17 00:00:00 2001 From: mike-gangl Date: Wed, 22 Mar 2023 08:27:23 -0700 Subject: [PATCH 02/22] added tests, more updates --- subscriber/podaac_access.py | 39 ++++++++++++++++++++++++++---- tests/test_subsetter_regression.py | 4 ++- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/subscriber/podaac_access.py b/subscriber/podaac_access.py index 8de0a5b..3d4cbe2 100644 --- a/subscriber/podaac_access.py +++ b/subscriber/podaac_access.py @@ -617,6 +617,22 @@ def find_harmony_runs(collection, bbox, starttime, endtime, output_dir, granules logging.warning("No .update in the data directory. (Is this the first run?)") return None +#In the event we need to delete a harmony run from the save file, this method can do that using a jobID +def remove_harmony_run(job_id, output_dir): + harmony_file = get_harmony_file(output_dir) + harmony_json = [] + if harmony_file: + f = open(harmony_file, "r") + harmony_json = json.load(f) + f.close() + #should create a new array of non-mathcing jobids + harmony_json = [x for x in harmony_json if x['jobid'] != job_id] + + with open(output_dir + "/.harmony", "w") as outfile: + json.dump(harmony_json, outfile) + + + def save_harmony_run(collection, bbox, starttime, endtime, job_id, output_dir, granules=None,): harmony_file = get_harmony_file(output_dir) harmony_json = [] @@ -655,8 +671,21 @@ def subset(concept_id, bbox, starttime, stoptime, output_dir, granules=None): def download_subsetted_files(job_id, output_dir, force_download = False): - harmony_client = harmony.Client() - iter = harmony_client.iterator(job_id, output_dir, force_download) - os.environ['VERBOSE'] = 'true' - futures = list(map(lambda x: x['path'], iter)) - (done_futures, _) = concurrent.futures.wait(futures) + + # Need to catch various exceptions here... + # + # WorkItem Duration + # File "/Users/gangl/miniconda3/lib/python3.8/site-packages/harmony/harmony.py", line 1124, in iterator + # raise Exception(response.get('message')) + # Exception: WorkItem [4928744] failed with error: Work item 4928744 has exceeded the 1095020 ms duration threshold. + try: + harmony_client = harmony.Client() + iter = harmony_client.iterator(job_id, output_dir, force_download) + os.environ['VERBOSE'] = 'true' + futures = list(map(lambda x: x['path'], iter)) + (done_futures, _) = concurrent.futures.wait(futures) + except Exception as e: + logging.error("Error processing harmony subsetting request: {}".format(str(e))) + logging.error("Removing job id [{0}] from harmony statefile {1}".format(job_id, output_dir+"/.harmony")) + remove_harmony_run(job_id, output_dir) + # If an error occurs, should we "retry" it? Should we remove this from the .harmony file? diff --git a/tests/test_subsetter_regression.py b/tests/test_subsetter_regression.py index 793bd64..180d7cc 100644 --- a/tests/test_subsetter_regression.py +++ b/tests/test_subsetter_regression.py @@ -17,8 +17,10 @@ def create_downloader_args(args): # -c VIIRS_N20-STAR-L2P-v2.80 -d ./data -b="52,52,55,55" -sd 2020-06-01T00:46:02Z -ed 2020-06-02T00:46:02Z --verbose --subset --limit 1 # Valid Subsetters -# -c MODIS_A-JPL-L2P-v2019.0 -d ./data -b="52,52,55,55" -sd 2020-06-01T00:46:02Z -ed 2020-06-02T00:46:02Z --verbose --subset --limit 1 +# -c MODIS_A-JPL-L2P-v2019.0 -d ./data -b="52,52,55,55" -sd 2020-06-01T00:46:02Z -ed 2020-06-02T00:46:02Z --verbose --subset --limit 1 --verbose --force # -c AMSR2-REMSS-L2P-v8.2 -d ./data -b="52,52,55,55" -sd 2020-06-01T00:46:02Z -ed 2020-06-02T00:46:02Z --verbose --subset --limit 1 +# -c SWOT_SIMULATED_L2_KARIN_SSH_GLORYS_SCIENCE_V1 -d ./data -b="-125.469,15.820,-99.453,35.859" -sd 2014-03-10T00:46:02Z -ed 2014-05-16T00:46:02Z --verbose --subset +# -c JASON_CS_S6A_L2_ALT_LR_STD_OST_NRT_F -d ./data -b="-125.469,15.820,-99.453,35.859" -sd 2023-03-10T00:46:02Z -ed 2023-03-16T00:46:02Z --verbose --subset #Test the downlaoder on MUR25 data for start/stop/, yyyy/mmm/dd dir structure, From 65737b93257bd8dc366a9dec96eb8fc6bf0069f9 Mon Sep 17 00:00:00 2001 From: mike-gangl Date: Thu, 30 Mar 2023 06:02:56 -0700 Subject: [PATCH 03/22] removed skip_errors (not implemented yet) --- subscriber/podaac_access.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/subscriber/podaac_access.py b/subscriber/podaac_access.py index 3d4cbe2..ca5e734 100644 --- a/subscriber/podaac_access.py +++ b/subscriber/podaac_access.py @@ -663,7 +663,9 @@ def subset(concept_id, bbox, starttime, stoptime, output_dir, granules=None): temporal={ 'start': isoparse(starttime), 'stop': isoparse(stoptime) - } + }, + skip_preview = True, + # ignoreErrors = True ) request.is_valid() job_id = harmony_client.submit(request) From ba90bd1b4175331709c1a188816a9b714a70c776 Mon Sep 17 00:00:00 2001 From: skperez Date: Fri, 4 Aug 2023 15:49:48 -0700 Subject: [PATCH 04/22] Upgrade to harmony-py 0.4.9 --- poetry.lock | 494 ++++++++++++++++++++++++------------------------- pyproject.toml | 2 +- 2 files changed, 238 insertions(+), 258 deletions(-) diff --git a/poetry.lock b/poetry.lock index 8661134..3c20f24 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,34 +1,101 @@ -[[package]] -name = "attrs" -version = "22.2.0" -description = "Classes Without Boilerplate" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.extras] -cov = ["attrs", "coverage-enable-subprocess", "coverage[toml] (>=5.3)"] -dev = ["attrs"] -docs = ["furo", "sphinx", "myst-parser", "zope.interface", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier"] -tests = ["attrs", "zope.interface"] -tests-no-zope = ["hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist", "cloudpickle", "mypy (>=0.971,<0.990)", "pytest-mypy-plugins"] -tests_no_zope = ["hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist", "cloudpickle", "mypy (>=0.971,<0.990)", "pytest-mypy-plugins"] +# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand. [[package]] name = "certifi" -version = "2022.12.7" +version = "2023.7.22" description = "Python package for providing Mozilla's CA Bundle." category = "main" optional = false python-versions = ">=3.6" +files = [ + {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"}, + {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"}, +] [[package]] name = "charset-normalizer" -version = "3.1.0" +version = "3.2.0" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." category = "main" optional = false python-versions = ">=3.7.0" +files = [ + {file = "charset-normalizer-3.2.0.tar.gz", hash = "sha256:3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b87549028f680ca955556e3bd57013ab47474c3124dc069faa0b6545b6c9710"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7c70087bfee18a42b4040bb9ec1ca15a08242cf5867c58726530bdf3945672ed"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a103b3a7069b62f5d4890ae1b8f0597618f628b286b03d4bc9195230b154bfa9"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94aea8eff76ee6d1cdacb07dd2123a68283cb5569e0250feab1240058f53b623"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db901e2ac34c931d73054d9797383d0f8009991e723dab15109740a63e7f902a"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b0dac0ff919ba34d4df1b6131f59ce95b08b9065233446be7e459f95554c0dc8"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:193cbc708ea3aca45e7221ae58f0fd63f933753a9bfb498a3b474878f12caaad"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09393e1b2a9461950b1c9a45d5fd251dc7c6f228acab64da1c9c0165d9c7765c"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:baacc6aee0b2ef6f3d308e197b5d7a81c0e70b06beae1f1fcacffdbd124fe0e3"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:bf420121d4c8dce6b889f0e8e4ec0ca34b7f40186203f06a946fa0276ba54029"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c04a46716adde8d927adb9457bbe39cf473e1e2c2f5d0a16ceb837e5d841ad4f"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:aaf63899c94de41fe3cf934601b0f7ccb6b428c6e4eeb80da72c58eab077b19a"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62e51710986674142526ab9f78663ca2b0726066ae26b78b22e0f5e571238dd"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-win32.whl", hash = "sha256:04e57ab9fbf9607b77f7d057974694b4f6b142da9ed4a199859d9d4d5c63fe96"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:48021783bdf96e3d6de03a6e39a1171ed5bd7e8bb93fc84cc649d11490f87cea"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4957669ef390f0e6719db3613ab3a7631e68424604a7b448f079bee145da6e09"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:46fb8c61d794b78ec7134a715a3e564aafc8f6b5e338417cb19fe9f57a5a9bf2"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f25c229a6ba38a35ae6e25ca1264621cc25d4d38dca2942a7fce0b67a4efe918"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2efb1bd13885392adfda4614c33d3b68dee4921fd0ac1d3988f8cbb7d589e72a"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f30b48dd7fa1474554b0b0f3fdfdd4c13b5c737a3c6284d3cdc424ec0ffff3a"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:246de67b99b6851627d945db38147d1b209a899311b1305dd84916f2b88526c6"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bd9b3b31adcb054116447ea22caa61a285d92e94d710aa5ec97992ff5eb7cf3"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8c2f5e83493748286002f9369f3e6607c565a6a90425a3a1fef5ae32a36d749d"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3170c9399da12c9dc66366e9d14da8bf7147e1e9d9ea566067bbce7bb74bd9c2"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7a4826ad2bd6b07ca615c74ab91f32f6c96d08f6fcc3902ceeedaec8cdc3bcd6"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:3b1613dd5aee995ec6d4c69f00378bbd07614702a315a2cf6c1d21461fe17c23"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9e608aafdb55eb9f255034709e20d5a83b6d60c054df0802fa9c9883d0a937aa"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-win32.whl", hash = "sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:681eb3d7e02e3c3655d1b16059fbfb605ac464c834a0c629048a30fad2b27489"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c57921cda3a80d0f2b8aec7e25c8aa14479ea92b5b51b6876d975d925a2ea346"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41b25eaa7d15909cf3ac4c96088c1f266a9a93ec44f87f1d13d4a0e86c81b982"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f058f6963fd82eb143c692cecdc89e075fa0828db2e5b291070485390b2f1c9c"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7647ebdfb9682b7bb97e2a5e7cb6ae735b1c25008a70b906aecca294ee96cf4"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eef9df1eefada2c09a5e7a40991b9fc6ac6ef20b1372abd48d2794a316dc0449"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e03b8895a6990c9ab2cdcd0f2fe44088ca1c65ae592b8f795c3294af00a461c3"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ee4006268ed33370957f55bf2e6f4d263eaf4dc3cfc473d1d90baff6ed36ce4a"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c4983bf937209c57240cff65906b18bb35e64ae872da6a0db937d7b4af845dd7"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:3bb7fda7260735efe66d5107fb7e6af6a7c04c7fce9b2514e04b7a74b06bf5dd"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:72814c01533f51d68702802d74f77ea026b5ec52793c791e2da806a3844a46c3"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:70c610f6cbe4b9fce272c407dd9d07e33e6bf7b4aa1b7ffb6f6ded8e634e3592"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-win32.whl", hash = "sha256:a401b4598e5d3f4a9a811f3daf42ee2291790c7f9d74b18d75d6e21dda98a1a1"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:c0b21078a4b56965e2b12f247467b234734491897e99c1d51cee628da9786959"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:95eb302ff792e12aba9a8b8f8474ab229a83c103d74a750ec0bd1c1eea32e669"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1a100c6d595a7f316f1b6f01d20815d916e75ff98c27a01ae817439ea7726329"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6339d047dab2780cc6220f46306628e04d9750f02f983ddb37439ca47ced7149"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4b749b9cc6ee664a3300bb3a273c1ca8068c46be705b6c31cf5d276f8628a94"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a38856a971c602f98472050165cea2cdc97709240373041b69030be15047691f"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89f1b185a01fe560bc8ae5f619e924407efca2191b56ce749ec84982fc59a32a"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e1c8a2f4c69e08e89632defbfabec2feb8a8d99edc9f89ce33c4b9e36ab63037"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2f4ac36d8e2b4cc1aa71df3dd84ff8efbe3bfb97ac41242fbcfc053c67434f46"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a386ebe437176aab38c041de1260cd3ea459c6ce5263594399880bbc398225b2"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ccd16eb18a849fd8dcb23e23380e2f0a354e8daa0c984b8a732d9cfaba3a776d"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:e6a5bf2cba5ae1bb80b154ed68a3cfa2fa00fde979a7f50d6598d3e17d9ac20c"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:45de3f87179c1823e6d9e32156fb14c1927fcc9aba21433f088fdfb555b77c10"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-win32.whl", hash = "sha256:1000fba1057b92a65daec275aec30586c3de2401ccdcd41f8a5c1e2c87078706"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:8b2c760cfc7042b27ebdb4a43a4453bd829a5742503599144d54a032c5dc7e9e"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:855eafa5d5a2034b4621c74925d89c5efef61418570e5ef9b37717d9c796419c"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:203f0c8871d5a7987be20c72442488a0b8cfd0f43b7973771640fc593f56321f"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e857a2232ba53ae940d3456f7533ce6ca98b81917d47adc3c7fd55dad8fab858"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e86d77b090dbddbe78867a0275cb4df08ea195e660f1f7f13435a4649e954e5"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4fb39a81950ec280984b3a44f5bd12819953dc5fa3a7e6fa7a80db5ee853952"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2dee8e57f052ef5353cf608e0b4c871aee320dd1b87d351c28764fc0ca55f9f4"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8700f06d0ce6f128de3ccdbc1acaea1ee264d2caa9ca05daaf492fde7c2a7200"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1920d4ff15ce893210c1f0c0e9d19bfbecb7983c76b33f046c13a8ffbd570252"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c1c76a1743432b4b60ab3358c937a3fe1341c828ae6194108a94c69028247f22"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f7560358a6811e52e9c4d142d497f1a6e10103d3a6881f18d04dbce3729c0e2c"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:c8063cf17b19661471ecbdb3df1c84f24ad2e389e326ccaf89e3fb2484d8dd7e"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:cd6dbe0238f7743d0efe563ab46294f54f9bc8f4b9bcf57c3c666cc5bc9d1299"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1249cbbf3d3b04902ff081ffbb33ce3377fa6e4c7356f759f3cd076cc138d020"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-win32.whl", hash = "sha256:6c409c0deba34f147f77efaa67b8e4bb83d2f11c8806405f76397ae5b8c0d1c9"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:7095f6fbfaa55defb6b733cfeb14efaae7a29f0b59d8cf213be4e7ca0b857b80"}, + {file = "charset_normalizer-3.2.0-py3-none-any.whl", hash = "sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6"}, +] [[package]] name = "colorama" @@ -37,6 +104,10 @@ description = "Cross-platform colored terminal text." category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] [[package]] name = "curlify" @@ -45,17 +116,24 @@ description = "Library to convert python requests object to curl command." category = "main" optional = false python-versions = "*" +files = [ + {file = "curlify-2.2.1.tar.gz", hash = "sha256:0d3f02e7235faf952de8ef45ef469845196d30632d5838bcd5aee217726ddd6d"}, +] [package.dependencies] requests = "*" [[package]] name = "exceptiongroup" -version = "1.1.1" +version = "1.1.2" description = "Backport of PEP 654 (exception groups)" category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.1.2-py3-none-any.whl", hash = "sha256:e346e69d186172ca7cf029c8c1d16235aa0e04035e5750b4b95039e65204328f"}, + {file = "exceptiongroup-1.1.2.tar.gz", hash = "sha256:12c3e887d6485d16943a309616de20ae5582633e0a2eda17f4e10fd61c1e8af5"}, +] [package.extras] test = ["pytest (>=6)"] @@ -67,6 +145,10 @@ description = "the modular source code checker: pep8 pyflakes and co" category = "dev" optional = false python-versions = ">=3.6" +files = [ + {file = "flake8-4.0.1-py2.py3-none-any.whl", hash = "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d"}, + {file = "flake8-4.0.1.tar.gz", hash = "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d"}, +] [package.dependencies] importlib-metadata = {version = "<4.3", markers = "python_version < \"3.8\""} @@ -76,22 +158,26 @@ pyflakes = ">=2.4.0,<2.5.0" [[package]] name = "harmony-py" -version = "0.4.5" +version = "0.4.9" description = "The NASA Harmony Python library" category = "main" optional = false python-versions = ">=3.6, <4" +files = [ + {file = "harmony-py-0.4.9.tar.gz", hash = "sha256:9e72d80029e2e1708ecd40c30a2498bbdcbf406d659da8073da29c5c64fd34cd"}, + {file = "harmony_py-0.4.9-py3-none-any.whl", hash = "sha256:a37d2226732c937c5599d5ba7e669aebc024a824bccef0cf8625346c340716b1"}, +] [package.dependencies] -curlify = ">=2.2,<3.0" -progressbar2 = ">=3.5,<4.0" -python-dateutil = ">=2.7.5,<2.8.0" -python-dotenv = ">=0.1,<1.0" -requests = ">=2.2,<3.0" -sphinxcontrib-napoleon = ">=0.7" +curlify = ">=2.2.1,<2.3.0" +progressbar2 = ">=3.55.0,<3.56.0" +python-dateutil = ">=2.8.2,<2.9.0" +python-dotenv = ">=0.20.0,<0.21.0" +requests = ">=2.28,<3.0" +sphinxcontrib-napoleon = ">=0.7,<1.0" [package.extras] -dev = ["autopep8 (>=1.4,<2.0)", "camel-case-switcher (>=2.0,<3.0)", "coverage (>=5.4,<6.0)", "flake8 (>=5.0.4,<5.1.0)", "hypothesis (>=6.2,<7.0)", "mypy (>=0.812,<1.0)", "m2r2 (>=0.2,<1.0)", "nose (>=1.3,<2.0)", "PyYAML (>=5.4,<6.0)", "pytest (>=6.2,<7.0)", "pytest-cov (>=2.11,<3.0)", "pytest-mock (>=3.5,<4.0)", "pytest-watch (>=4.2,<5.0)", "responses (>=0.12,<1.0)", "setuptools (>=54.2)", "sphinx (>=3.4,<4.0)", "wheel (>=0.36)"] +dev = ["PyYAML (>=5.4,<6.0)", "autopep8 (>=1.4,<2.0)", "camel-case-switcher (>=2.0,<3.0)", "coverage (>=5.4,<6.0)", "flake8 (>=3.8,<4.0)", "hypothesis (>=6.2,<7.0)", "importlib-metadata (<5.0)", "mypy (>=0.812,<1.0)", "nose (>=1.3,<2.0)", "pytest (>=6.2,<7.0)", "pytest-cov (>=2.11,<3.0)", "pytest-mock (>=3.5,<4.0)", "pytest-watch (>=4.2,<5.0)", "responses (>=0.12,<1.0)", "setuptools (>=54.2)", "sphinx (>=5.3.0,<5.4.0)", "wheel (>=0.36)"] [[package]] name = "idna" @@ -100,6 +186,10 @@ description = "Internationalized Domain Names in Applications (IDNA)" category = "main" optional = false python-versions = ">=3.5" +files = [ + {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, + {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, +] [[package]] name = "importlib-metadata" @@ -108,14 +198,18 @@ description = "Read metadata from Python packages" category = "dev" optional = false python-versions = ">=3.6" +files = [ + {file = "importlib_metadata-4.2.0-py3-none-any.whl", hash = "sha256:057e92c15bc8d9e8109738a48db0ccb31b4d9d5cfbee5a8670879a30be66304b"}, + {file = "importlib_metadata-4.2.0.tar.gz", hash = "sha256:b7e52a1f8dec14a75ea73e0891f3060099ca1d8e6a462a4dff11c3e119ea1b31"}, +] [package.dependencies] typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""} zipp = ">=0.5" [package.extras] -docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] -testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"] +docs = ["jaraco.packaging (>=8.2)", "rst.linker (>=1.9)", "sphinx"] +testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pep517", "pyfakefs", "pytest (>=4.6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-flake8", "pytest-mypy"] [[package]] name = "iniconfig" @@ -124,6 +218,10 @@ description = "brain-dead simple config-ini parsing" category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, +] [[package]] name = "mccabe" @@ -132,29 +230,41 @@ description = "McCabe checker, plugin for flake8" category = "dev" optional = false python-versions = "*" +files = [ + {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, + {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, +] [[package]] name = "packaging" -version = "23.0" +version = "23.1" description = "Core utilities for Python packages" category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"}, + {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"}, +] [[package]] name = "pluggy" -version = "1.0.0" +version = "1.2.0" description = "plugin and hook calling mechanisms for python" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" +files = [ + {file = "pluggy-1.2.0-py3-none-any.whl", hash = "sha256:c2fd55a7d7a3863cba1a013e4e2414658b1d07b6bc57b3919e0c63c9abb99849"}, + {file = "pluggy-1.2.0.tar.gz", hash = "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3"}, +] [package.dependencies] importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} [package.extras] -testing = ["pytest-benchmark", "pytest"] -dev = ["tox", "pre-commit"] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] [[package]] name = "pockets" @@ -163,6 +273,10 @@ description = "A collection of helpful Python tools!" category = "main" optional = false python-versions = "*" +files = [ + {file = "pockets-0.9.1-py2.py3-none-any.whl", hash = "sha256:68597934193c08a08eb2bf6a1d85593f627c22f9b065cc727a4f03f669d96d86"}, + {file = "pockets-0.9.1.tar.gz", hash = "sha256:9320f1a3c6f7a9133fe3b571f283bcf3353cd70249025ae8d618e40e9f7e92b3"}, +] [package.dependencies] six = ">=1.5.2" @@ -174,6 +288,10 @@ description = "A Python Progressbar library to provide visual (yet text based) p category = "main" optional = false python-versions = "*" +files = [ + {file = "progressbar2-3.55.0-py2.py3-none-any.whl", hash = "sha256:e98fee031da31ab9138fd8dd838ac80eafba82764eb75a43d25e3ca622f47d14"}, + {file = "progressbar2-3.55.0.tar.gz", hash = "sha256:86835d1f1a9317ab41aeb1da5e4184975e2306586839d66daf63067c102f8f04"}, +] [package.dependencies] python-utils = ">=2.3.0" @@ -181,7 +299,7 @@ six = "*" [package.extras] docs = ["sphinx (>=1.7.4)"] -tests = ["flake8 (>=3.7.7)", "pytest (>=4.6.9)", "pytest-cov (>=2.6.1)", "freezegun (>=0.3.11)", "sphinx (>=1.8.5)"] +tests = ["flake8 (>=3.7.7)", "freezegun (>=0.3.11)", "pytest (>=4.6.9)", "pytest-cov (>=2.6.1)", "sphinx (>=1.8.5)"] [[package]] name = "pycodestyle" @@ -190,6 +308,10 @@ description = "Python style guide checker" category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "pycodestyle-2.8.0-py2.py3-none-any.whl", hash = "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20"}, + {file = "pycodestyle-2.8.0.tar.gz", hash = "sha256:eddd5847ef438ea1c7870ca7eb78a9d47ce0cdb4851a5523949f2601d0cbbe7f"}, +] [[package]] name = "pyflakes" @@ -198,17 +320,24 @@ description = "passive checker of Python programs" category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "pyflakes-2.4.0-py2.py3-none-any.whl", hash = "sha256:3bb3a3f256f4b7968c9c788781e4ff07dce46bdf12339dcda61053375426ee2e"}, + {file = "pyflakes-2.4.0.tar.gz", hash = "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c"}, +] [[package]] name = "pytest" -version = "7.2.2" +version = "7.4.0" description = "pytest: simple powerful testing with Python" category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "pytest-7.4.0-py3-none-any.whl", hash = "sha256:78bf16451a2eb8c7a2ea98e32dc119fd2aa758f1d5d66dbf0a59d69a3969df32"}, + {file = "pytest-7.4.0.tar.gz", hash = "sha256:b4bf8c45bd59934ed84001ad51e11b4ee40d40a1229d2c79f9c592b0a3f6bd8a"}, +] [package.dependencies] -attrs = ">=19.2.0" colorama = {version = "*", markers = "sys_platform == \"win32\""} exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} @@ -218,40 +347,52 @@ pluggy = ">=0.12,<2.0" tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} [package.extras] -testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] +testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] [[package]] name = "pytest-mock" -version = "3.10.0" +version = "3.11.1" description = "Thin-wrapper around the mock package for easier use with pytest" category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "pytest-mock-3.11.1.tar.gz", hash = "sha256:7f6b125602ac6d743e523ae0bfa71e1a697a2f5534064528c6ff84c2f7c2fc7f"}, + {file = "pytest_mock-3.11.1-py3-none-any.whl", hash = "sha256:21c279fff83d70763b05f8874cc9cfb3fcacd6d354247a976f9529d19f9acf39"}, +] [package.dependencies] pytest = ">=5.0" [package.extras] -dev = ["pre-commit", "tox", "pytest-asyncio"] +dev = ["pre-commit", "pytest-asyncio", "tox"] [[package]] name = "python-dateutil" -version = "2.7.5" +version = "2.8.2" description = "Extensions to the standard Python datetime module" category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, + {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, +] [package.dependencies] six = ">=1.5" [[package]] name = "python-dotenv" -version = "0.21.1" +version = "0.20.0" description = "Read key-value pairs from a .env file and set them as environment variables" category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.5" +files = [ + {file = "python-dotenv-0.20.0.tar.gz", hash = "sha256:b7e3b04a59693c42c36f9ab1cc2acc46fa5df8c78e178fc33a8d4cd05c8d498f"}, + {file = "python_dotenv-0.20.0-py3-none-any.whl", hash = "sha256:d92a187be61fe482e4fd675b6d52200e7be63a12b724abbf931a40ce4fa92938"}, +] [package.extras] cli = ["click (>=5.0)"] @@ -263,32 +404,40 @@ description = "Python Utils is a module with some convenient utilities not inclu category = "main" optional = false python-versions = ">3.6.0" +files = [ + {file = "python-utils-3.5.2.tar.gz", hash = "sha256:68198854fc276bc4b2403b261703c218e01ef564dcb072a7096ed9ea7aa5130c"}, + {file = "python_utils-3.5.2-py2.py3-none-any.whl", hash = "sha256:8bfefc3430f1c48408fa0e5958eee51d39840a5a987c2181a579e99ab6fe5ca6"}, +] [package.dependencies] typing-extensions = {version = "*", markers = "python_version < \"3.8\""} [package.extras] -docs = ["mock", "sphinx", "python-utils"] +docs = ["mock", "python-utils", "sphinx"] loguru = ["loguru"] -tests = ["flake8", "pytest", "pytest-cov", "pytest-mypy", "pytest-asyncio", "sphinx", "types-setuptools", "loguru"] +tests = ["flake8", "loguru", "pytest", "pytest-asyncio", "pytest-cov", "pytest-mypy", "sphinx", "types-setuptools"] [[package]] name = "requests" -version = "2.28.2" +version = "2.31.0" description = "Python HTTP for Humans." category = "main" optional = false -python-versions = ">=3.7, <4" +python-versions = ">=3.7" +files = [ + {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, + {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, +] [package.dependencies] certifi = ">=2017.4.17" charset-normalizer = ">=2,<4" idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<1.27" +urllib3 = ">=1.21.1,<3" [package.extras] socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "six" @@ -297,6 +446,10 @@ description = "Python 2 and 3 compatibility utilities" category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] [[package]] name = "sphinxcontrib-napoleon" @@ -305,6 +458,10 @@ description = "Sphinx \"napoleon\" extension." category = "main" optional = false python-versions = "*" +files = [ + {file = "sphinxcontrib-napoleon-0.7.tar.gz", hash = "sha256:407382beed396e9f2d7f3043fad6afda95719204a1e1a231ac865f40abcbfcf8"}, + {file = "sphinxcontrib_napoleon-0.7-py2.py3-none-any.whl", hash = "sha256:711e41a3974bdf110a484aec4c1a556799eb0b3f3b897521a018ad7e2db13fef"}, +] [package.dependencies] pockets = ">=0.3" @@ -317,6 +474,10 @@ description = "Retry code until it succeeds" category = "main" optional = false python-versions = ">=3.6" +files = [ + {file = "tenacity-8.2.2-py3-none-any.whl", hash = "sha256:2f277afb21b851637e8f52e6a613ff08734c347dc19ade928e519d7d2d8569b0"}, + {file = "tenacity-8.2.2.tar.gz", hash = "sha256:43af037822bd0029025877f3b2d97cc4d7bb0c2991000a3d59d71517c5c969e0"}, +] [package.extras] doc = ["reno", "sphinx", "tornado (>=4.5)"] @@ -328,27 +489,40 @@ description = "A lil' TOML parser" category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] [[package]] name = "typing-extensions" -version = "4.5.0" +version = "4.7.1" description = "Backported and Experimental Type Hints for Python 3.7+" category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"}, + {file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"}, +] [[package]] name = "urllib3" -version = "1.26.15" +version = "2.0.4" description = "HTTP library with thread-safe connection pooling, file post, and more." category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +python-versions = ">=3.7" +files = [ + {file = "urllib3-2.0.4-py3-none-any.whl", hash = "sha256:de7df1803967d2c2a98e4b11bb7d6bd9210474c46e8a0401514e3a42a75ebde4"}, + {file = "urllib3-2.0.4.tar.gz", hash = "sha256:8d22f86aae8ef5e410d4f539fde9ce6b2113a001bb4d189e0aed70642d602b11"}, +] [package.extras] -brotli = ["brotlicffi (>=0.8.0)", "brotli (>=1.0.9)", "brotlipy (>=0.6.0)"] -secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "urllib3-secure-extra", "ipaddress"] -socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] [[package]] name = "zipp" @@ -357,210 +531,16 @@ description = "Backport of pathlib-compatible object wrapper for zip files" category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "zipp-3.15.0-py3-none-any.whl", hash = "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556"}, + {file = "zipp-3.15.0.tar.gz", hash = "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b"}, +] [package.extras] -docs = ["sphinx (>=3.5)", "jaraco.packaging (>=9)", "rst.linker (>=1.9)", "furo", "sphinx-lint", "jaraco.tidelift (>=1.4)"] -testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "flake8 (<5)", "pytest-cov", "pytest-enabler (>=1.3)", "jaraco.itertools", "jaraco.functools", "more-itertools", "big-o", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)", "pytest-flake8"] +docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] [metadata] -lock-version = "1.1" +lock-version = "2.0" python-versions = "^3.7" -content-hash = "9d493b26dc378d841221aa3a93ccd4f98776152fcc0cb53f6a3921ffce014494" - -[metadata.files] -attrs = [ - {file = "attrs-22.2.0-py3-none-any.whl", hash = "sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836"}, - {file = "attrs-22.2.0.tar.gz", hash = "sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99"}, -] -certifi = [ - {file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"}, - {file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"}, -] -charset-normalizer = [ - {file = "charset-normalizer-3.1.0.tar.gz", hash = "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-win32.whl", hash = "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-win32.whl", hash = "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-win32.whl", hash = "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-win32.whl", hash = "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b"}, - {file = "charset_normalizer-3.1.0-py3-none-any.whl", hash = "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d"}, -] -colorama = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] -curlify = [ - {file = "curlify-2.2.1.tar.gz", hash = "sha256:0d3f02e7235faf952de8ef45ef469845196d30632d5838bcd5aee217726ddd6d"}, -] -exceptiongroup = [ - {file = "exceptiongroup-1.1.1-py3-none-any.whl", hash = "sha256:232c37c63e4f682982c8b6459f33a8981039e5fb8756b2074364e5055c498c9e"}, - {file = "exceptiongroup-1.1.1.tar.gz", hash = "sha256:d484c3090ba2889ae2928419117447a14daf3c1231d5e30d0aae34f354f01785"}, -] -flake8 = [ - {file = "flake8-4.0.1-py2.py3-none-any.whl", hash = "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d"}, - {file = "flake8-4.0.1.tar.gz", hash = "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d"}, -] -harmony-py = [ - {file = "harmony-py-0.4.5.tar.gz", hash = "sha256:0cf1a24cc7e29fe4b7338caf235e9116145fe6677d642ad839c8bd3ddc15d2ae"}, - {file = "harmony_py-0.4.5-py3-none-any.whl", hash = "sha256:1dd982e3475fc6d12025d89f04cab08fc5faf8d6d2369286e03368c8ce1762e5"}, -] -idna = [ - {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, - {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, -] -importlib-metadata = [ - {file = "importlib_metadata-4.2.0-py3-none-any.whl", hash = "sha256:057e92c15bc8d9e8109738a48db0ccb31b4d9d5cfbee5a8670879a30be66304b"}, - {file = "importlib_metadata-4.2.0.tar.gz", hash = "sha256:b7e52a1f8dec14a75ea73e0891f3060099ca1d8e6a462a4dff11c3e119ea1b31"}, -] -iniconfig = [ - {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, - {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, -] -mccabe = [ - {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, - {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, -] -packaging = [ - {file = "packaging-23.0-py3-none-any.whl", hash = "sha256:714ac14496c3e68c99c29b00845f7a2b85f3bb6f1078fd9f72fd20f0570002b2"}, - {file = "packaging-23.0.tar.gz", hash = "sha256:b6ad297f8907de0fa2fe1ccbd26fdaf387f5f47c7275fedf8cce89f99446cf97"}, -] -pluggy = [ - {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, - {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, -] -pockets = [ - {file = "pockets-0.9.1-py2.py3-none-any.whl", hash = "sha256:68597934193c08a08eb2bf6a1d85593f627c22f9b065cc727a4f03f669d96d86"}, - {file = "pockets-0.9.1.tar.gz", hash = "sha256:9320f1a3c6f7a9133fe3b571f283bcf3353cd70249025ae8d618e40e9f7e92b3"}, -] -progressbar2 = [ - {file = "progressbar2-3.55.0-py2.py3-none-any.whl", hash = "sha256:e98fee031da31ab9138fd8dd838ac80eafba82764eb75a43d25e3ca622f47d14"}, - {file = "progressbar2-3.55.0.tar.gz", hash = "sha256:86835d1f1a9317ab41aeb1da5e4184975e2306586839d66daf63067c102f8f04"}, -] -pycodestyle = [ - {file = "pycodestyle-2.8.0-py2.py3-none-any.whl", hash = "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20"}, - {file = "pycodestyle-2.8.0.tar.gz", hash = "sha256:eddd5847ef438ea1c7870ca7eb78a9d47ce0cdb4851a5523949f2601d0cbbe7f"}, -] -pyflakes = [ - {file = "pyflakes-2.4.0-py2.py3-none-any.whl", hash = "sha256:3bb3a3f256f4b7968c9c788781e4ff07dce46bdf12339dcda61053375426ee2e"}, - {file = "pyflakes-2.4.0.tar.gz", hash = "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c"}, -] -pytest = [ - {file = "pytest-7.2.2-py3-none-any.whl", hash = "sha256:130328f552dcfac0b1cec75c12e3f005619dc5f874f0a06e8ff7263f0ee6225e"}, - {file = "pytest-7.2.2.tar.gz", hash = "sha256:c99ab0c73aceb050f68929bc93af19ab6db0558791c6a0715723abe9d0ade9d4"}, -] -pytest-mock = [ - {file = "pytest-mock-3.10.0.tar.gz", hash = "sha256:fbbdb085ef7c252a326fd8cdcac0aa3b1333d8811f131bdcc701002e1be7ed4f"}, - {file = "pytest_mock-3.10.0-py3-none-any.whl", hash = "sha256:f4c973eeae0282963eb293eb173ce91b091a79c1334455acfac9ddee8a1c784b"}, -] -python-dateutil = [ - {file = "python-dateutil-2.7.5.tar.gz", hash = "sha256:88f9287c0174266bb0d8cedd395cfba9c58e87e5ad86b2ce58859bc11be3cf02"}, - {file = "python_dateutil-2.7.5-py2.py3-none-any.whl", hash = "sha256:063df5763652e21de43de7d9e00ccf239f953a832941e37be541614732cdfc93"}, -] -python-dotenv = [ - {file = "python-dotenv-0.21.1.tar.gz", hash = "sha256:1c93de8f636cde3ce377292818d0e440b6e45a82f215c3744979151fa8151c49"}, - {file = "python_dotenv-0.21.1-py3-none-any.whl", hash = "sha256:41e12e0318bebc859fcc4d97d4db8d20ad21721a6aa5047dd59f090391cb549a"}, -] -python-utils = [ - {file = "python-utils-3.5.2.tar.gz", hash = "sha256:68198854fc276bc4b2403b261703c218e01ef564dcb072a7096ed9ea7aa5130c"}, - {file = "python_utils-3.5.2-py2.py3-none-any.whl", hash = "sha256:8bfefc3430f1c48408fa0e5958eee51d39840a5a987c2181a579e99ab6fe5ca6"}, -] -requests = [ - {file = "requests-2.28.2-py3-none-any.whl", hash = "sha256:64299f4909223da747622c030b781c0d7811e359c37124b4bd368fb8c6518baa"}, - {file = "requests-2.28.2.tar.gz", hash = "sha256:98b1b2782e3c6c4904938b84c0eb932721069dfdb9134313beff7c83c2df24bf"}, -] -six = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, -] -sphinxcontrib-napoleon = [ - {file = "sphinxcontrib-napoleon-0.7.tar.gz", hash = "sha256:407382beed396e9f2d7f3043fad6afda95719204a1e1a231ac865f40abcbfcf8"}, - {file = "sphinxcontrib_napoleon-0.7-py2.py3-none-any.whl", hash = "sha256:711e41a3974bdf110a484aec4c1a556799eb0b3f3b897521a018ad7e2db13fef"}, -] -tenacity = [ - {file = "tenacity-8.2.2-py3-none-any.whl", hash = "sha256:2f277afb21b851637e8f52e6a613ff08734c347dc19ade928e519d7d2d8569b0"}, - {file = "tenacity-8.2.2.tar.gz", hash = "sha256:43af037822bd0029025877f3b2d97cc4d7bb0c2991000a3d59d71517c5c969e0"}, -] -tomli = [ - {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, - {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, -] -typing-extensions = [ - {file = "typing_extensions-4.5.0-py3-none-any.whl", hash = "sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4"}, - {file = "typing_extensions-4.5.0.tar.gz", hash = "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb"}, -] -urllib3 = [ - {file = "urllib3-1.26.15-py2.py3-none-any.whl", hash = "sha256:aa751d169e23c7479ce47a0cb0da579e3ede798f994f5816a74e4f4500dcea42"}, - {file = "urllib3-1.26.15.tar.gz", hash = "sha256:8a388717b9476f934a21484e8c8e61875ab60644d29b9b39e11e4b9dc1c6b305"}, -] -zipp = [ - {file = "zipp-3.15.0-py3-none-any.whl", hash = "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556"}, - {file = "zipp-3.15.0.tar.gz", hash = "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b"}, -] +content-hash = "408b1292a8478f6220f742eecfaa1a55acc7e7584eaeb60292962af4fef3fa59" diff --git a/pyproject.toml b/pyproject.toml index 1f2b783..5b2e046 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,7 +15,7 @@ packages = [ python = "^3.7" requests = "^2.27.1" tenacity = "^8.0.1" -harmony-py = "^0.4.5" +harmony-py = "^0.4.9" From 13b9ecee9ca59f2faacd4f4757d8b23098f9d5d3 Mon Sep 17 00:00:00 2001 From: skperez Date: Fri, 4 Aug 2023 16:30:48 -0700 Subject: [PATCH 05/22] subsetting capability initial commit --- subscriber/podaac_access.py | 327 +++++++++++++++++++++------ subscriber/podaac_data_downloader.py | 84 +++---- subscriber/podaac_data_subscriber.py | 110 ++++++--- subscriber/subsetting.py | 93 ++++++++ 4 files changed, 458 insertions(+), 156 deletions(-) create mode 100644 subscriber/subsetting.py diff --git a/subscriber/podaac_access.py b/subscriber/podaac_access.py index ca5e734..313f82e 100644 --- a/subscriber/podaac_access.py +++ b/subscriber/podaac_access.py @@ -1,13 +1,10 @@ import json import logging import netrc -import subprocess import re -from datetime import datetime from http.cookiejar import CookieJar from os import makedirs from os.path import isdir, basename, join, splitext, isfile -from urllib import request from typing import Dict from urllib import request from urllib.error import HTTPError @@ -16,16 +13,12 @@ from urllib.parse import urlencode from urllib.request import Request, urlopen import hashlib -from datetime import datetime import time from requests.auth import HTTPBasicAuth import harmony -import datetime as dt -import os import concurrent.futures from dateutil.parser import * - -import requests +import functools import requests import tenacity @@ -187,12 +180,18 @@ def validate(args): if len(bounds) != 4: raise ValueError( "Error parsing '--bounds': " + args.bbox + ". Format is W Longitude,S Latitude,E Longitude,N Latitude without spaces ") # noqa E501 - for b in bounds: - try: - float(b) - except ValueError: - raise ValueError( - "Error parsing '--bounds': " + args.bbox + ". Format is W Longitude,S Latitude,E Longitude,N Latitude without spaces ") # noqa E501 + try: + num_bounds = [float(b) for b in bounds] + except ValueError: + raise ValueError( + "Error parsing '--bounds': " + args.bbox + ". Format is W Longitude,S Latitude,E Longitude,N Latitude without spaces ") # noqa E501 + + if num_bounds[0] > num_bounds[2]: + raise ValueError('Error parsing "--bounds": W Longitude must be <= E Longitude') + + if num_bounds[1] > num_bounds[2]: + raise ValueError('Error parsing "--bounds": S Latitude must be <= N Latitude') + if args.startDate: try: @@ -427,7 +426,7 @@ def parse_cycles(results): return cycles -def extract_checksums(granule_results): +def extract_checksums(granules): """ Create a dictionary containing checksum information from files. @@ -455,7 +454,7 @@ def extract_checksums(granule_results): } """ checksums = {} - for granule in granule_results["items"]: + for granule in granules: try: items = granule["umm"]["DataGranule"]["ArchiveAndDistributionInformation"] for item in items: @@ -525,6 +524,43 @@ def get_cmr_collections(params, verbose=False): return result +def get_cmr_collection_id(collection_short_name, provider, token, verbose): + """ + Retrieve collection ID from CMR given the collection short name and provider + + Parameters + ---------- + collection_short_name: str + The name of the collection + provider: str + The collection provider + token: str + The EDL token used to query CMR + verbose: bool + If true, print extra messages to stdout + + Returns + ------- + str + CMR collection concept ID + + Raises + ------ + ValueError + If no collection in CMR match the given short name and provider + """ + params = { + 'provider': provider, + 'ShortName': collection_short_name, + 'token': token + } + collections = get_cmr_collections(params, verbose)['items'] + + if not collections: + raise ValueError(f'No collections found in CMR for {collection_short_name}/{provider}') + return collections[0]['meta']['concept-id'] + + def create_citation(collection_json, access_date): citation_template = "{creator}. {year}. {title}. Ver. {version}. PO.DAAC, CA, USA. Dataset accessed {access_date} at {doi_authority}/{doi}" @@ -564,8 +600,25 @@ def create_citation_file(short_name, provider, data_path, token=None, verbose=Fa with open(data_path + "/" + short_name + ".citation.txt", "w") as text_file: text_file.write(citation) -# Function to determine if a collection has an applicable harmony subsetter + def is_collection_harmony_subsettable(concept_id, token=None): + """ + Function to determine if a collection has an applicable harmony + subsetter. This is accomplished by querying the CMR GraphQL API and + looking for the expected UMM-S association. + + Parameters + ---------- + concept_id: str + The CMR collection concept ID to search for + token: str + EDL token used to query CMR + + Returns + ------- + bool + True if the collection is Harmony subsettable + """ graph_query_template = ''' query Collection { collection(conceptId: "$TEMPLATE_CONCEPT_ID") { @@ -579,115 +632,245 @@ def is_collection_harmony_subsettable(concept_id, token=None): } } ''' - query = graph_query_template.replace("$TEMPLATE_CONCEPT_ID",concept_id) + query = graph_query_template.replace('$TEMPLATE_CONCEPT_ID', concept_id) headers = {} if token: - headers = {"Authorization" : "Bearer " + token} - r = requests.post(graph_url, json={'query': query}, headers=headers, timeout=(10,60)) + headers = {'Authorization': 'Bearer ' + token} + r = requests.post(graph_url, json={'query': query}, headers=headers, timeout=(10, 60)) collection_services = r.json()['data']['collection']['services']['items'] harmony_subsetter = False if collection_services is None: return False for svc in collection_services: - if svc['type'] == "Harmony": + if svc['type'] == 'Harmony': for kw in svc['serviceKeywords']: - if kw['serviceTerm'] == "SUBSETTING/SUPERSETTING": + if kw['serviceTerm'] == 'SUBSETTING/SUPERSETTING': harmony_subsetter = True return harmony_subsetter + def get_harmony_file(data_dir): - if isfile(data_dir + "/.harmony"): - return data_dir + "/.harmony" + """ + Get Harmony statefile absolute path + + Parameters + ---------- + data_dir: str + Path to data download location + Returns + ------- + str or None + If there is a Harmony statefile in the provided location, + return the path to the file. Otherwise, return None. + """ + if isfile(data_dir + '/.harmony'): + return data_dir + '/.harmony' return None -def find_harmony_runs(collection, bbox, starttime, endtime, output_dir, granules=None,): + +def find_harmony_runs(collection, bbox, starttime, endtime, output_dir, granules=None): + """ + Look for run in Harmony statefile + + Parameters + ---------- + collection: str + CMR collection ID + bbox: str + bbox string + starttime: str + Harmony request start time + endtime: str + Harmony request end time + output_dir: str + Where to download files + granules: list + Optional. List of granules provided in Harmony request + + Returns + -------- + str or None + If an existing job is found, the job ID will be returned. + Otherwise, return None. + """ harmony_file = get_harmony_file(output_dir) if harmony_file is None: return None - else: - try: - with open(harmony_file, "r") as f: - harmony_json = json.load(f) - for x in harmony_json: - if x["collection_id"] == collection and x['starttime'] == starttime and x['endtime'] == endtime and x['bbox'] == bbox: - return x['jobid'] - - except FileNotFoundError: - logging.warning("No .update in the data directory. (Is this the first run?)") + try: + with open(harmony_file, 'r') as f: + harmony_json = json.load(f) + for x in harmony_json: + if x['collection_id'] == collection and x['starttime'] == starttime and x[ + 'endtime'] == endtime and x['bbox'] == bbox and x['granules'] == granules: + return x['jobid'] + except FileNotFoundError: + logging.warning('No .harmony file in the data directory. (Is this the first run?)') return None -#In the event we need to delete a harmony run from the save file, this method can do that using a jobID + def remove_harmony_run(job_id, output_dir): + """ + In the event we need to delete a Harmony run from the save file, + this method can do that using a jobID. This might be used in the + case of Harmony failures. + + Parameters + ---------- + job_id: str + Harmony job ID + output_dir: str + Location of downloaded Harmony statefile + """ harmony_file = get_harmony_file(output_dir) harmony_json = [] if harmony_file: - f = open(harmony_file, "r") - harmony_json = json.load(f) - f.close() - #should create a new array of non-mathcing jobids + with open(harmony_file, 'r') as f: + harmony_json = json.load(f) harmony_json = [x for x in harmony_json if x['jobid'] != job_id] - with open(output_dir + "/.harmony", "w") as outfile: + with open(output_dir + '/.harmony', 'w') as outfile: json.dump(harmony_json, outfile) +def save_harmony_run(collection, bbox, starttime, endtime, job_id, output_dir, granule_ids=None): + """ + Save Harmony run to Harmony statefile -def save_harmony_run(collection, bbox, starttime, endtime, job_id, output_dir, granules=None,): + Parameters + ---------- + collection: str + CMR collection ID + bbox: str + Harmony request bbox + starttime: str + Harmony request start time + endtime: str + Harmony request end time + job_id: str + Harmony job ID + output_dir: str + Harmony statefile location + granule_ids: list or None + None or list of granule IDs used in Harmony request + """ harmony_file = get_harmony_file(output_dir) harmony_json = [] if harmony_file: - f = open(harmony_file, "r") + f = open(harmony_file, 'r') harmony_json = json.load(f) f.close() - harmony_run = {} - harmony_run["collection_id"] = collection - harmony_run['starttime'] = starttime - harmony_run['endtime'] = endtime - harmony_run['bbox'] = bbox - harmony_run['jobid'] = job_id + harmony_run = { + 'collection_id': collection, + 'starttime': starttime, + 'endtime': endtime, + 'bbox': bbox, + 'jobid': job_id, + 'granules': granule_ids + } harmony_json.append(harmony_run) - with open(output_dir + "/.harmony", "w") as outfile: + with open(output_dir + '/.harmony', 'w') as outfile: json.dump(harmony_json, outfile) + # Function to utilize Harmony for subsetting a collection -def subset(concept_id, bbox, starttime, stoptime, output_dir, granules=None): +def subset(concept_id, bbox, start_time, stop_time, granules=None): + """ + Submit Harmony subset request + + Parameters + ---------- + concept_id: str + CMR collection concept ID + bbox: str + Spatial bounds to use in Harmony subset request + start_time: str + Lower temporal bound to use in Harmony subset request + stop_time: str + Upper temporal bound to use in Harmony subset request + granules: list or None + Optional. List of granules to explicitly provide to Harmony. + If no list is provided, spatiotemporal bounds will be used to + find valid granules in collection. + + Returns + ------- + str + Harmony job ID (uuid) + """ harmony_client = harmony.Client() - bbox_ary = [float(x) for x in bbox.split(",")] + bbox_ary = [float(x) for x in bbox.split(',')] collection = harmony.Collection(id=concept_id) - request = harmony.Request( + harmony_request = harmony.Request( collection=collection, spatial=harmony.BBox(bbox_ary[0], bbox_ary[1], bbox_ary[2], bbox_ary[3]), temporal={ - 'start': isoparse(starttime), - 'stop': isoparse(stoptime) + 'start': isoparse(start_time), + 'stop': isoparse(stop_time) }, - skip_preview = True, - # ignoreErrors = True + skip_preview=True, + granule_id=granules, + ignore_errors=True ) - request.is_valid() - job_id = harmony_client.submit(request) + harmony_request.is_valid() + job_id = harmony_client.submit(harmony_request) return job_id -def download_subsetted_files(job_id, output_dir, force_download = False): +def download_callback(process_cmd, args, future): + """ + Callback which is called upon each granule after successfully + downloaded - # Need to catch various exceptions here... - # - # WorkItem Duration - # File "/Users/gangl/miniconda3/lib/python3.8/site-packages/harmony/harmony.py", line 1124, in iterator - # raise Exception(response.get('message')) - # Exception: WorkItem [4928744] failed with error: Work item 4928744 has exceeded the 1095020 ms duration threshold. + Parameters + ---------- + process_cmd: str + Command to run on each granule after successful download + args: argparse.Namespace + Script args + future: asyncio.Future + Future to extract result (download location) from when complete + """ + process_file(process_cmd, future.result(), args) + + +def download_subsetted_files(job_id, output_dir, args, force_download=False, process_cmd=None): + """ + Download Harmony results locally + + Parameters + ---------- + job_id: str + output_dir: str + args: argparse.Namespace + force_download: bool + process_cmd: str + + Returns + ------- + str + Harmony job status. Will be one of: + - failed + - canceled + - paused + - complete_with_errors + - successful + - running_with_errors + """ + harmony_client = harmony.Client() try: - harmony_client = harmony.Client() - iter = harmony_client.iterator(job_id, output_dir, force_download) - os.environ['VERBOSE'] = 'true' - futures = list(map(lambda x: x['path'], iter)) + harmony_iterator = harmony_client.iterator(job_id, output_dir, force_download) + futures = list(map(lambda x: x['path'], harmony_iterator)) + for future in futures: + future.add_done_callback( + functools.partial(download_callback, process_cmd, args) + ) (done_futures, _) = concurrent.futures.wait(futures) except Exception as e: - logging.error("Error processing harmony subsetting request: {}".format(str(e))) - logging.error("Removing job id [{0}] from harmony statefile {1}".format(job_id, output_dir+"/.harmony")) + logging.error(f'Error processing harmony subsetting request: {e}') + logging.error(f'Removing job id [{job_id}] from harmony statefile {output_dir}/.harmony') remove_harmony_run(job_id, output_dir) + return harmony_client.status(job_id) # If an error occurs, should we "retry" it? Should we remove this from the .harmony file? diff --git a/subscriber/podaac_data_downloader.py b/subscriber/podaac_data_downloader.py index b8eda80..e12609a 100755 --- a/subscriber/podaac_data_downloader.py +++ b/subscriber/podaac_data_downloader.py @@ -1,15 +1,15 @@ #!/usr/bin/env python3 import argparse import logging -import os, re +import os import sys from datetime import datetime, timedelta from os import makedirs from os.path import isdir, basename, join, exists from urllib.error import HTTPError -from urllib.request import urlretrieve from subscriber import podaac_access as pa +from subscriber import subsetting __version__ = pa.__version__ @@ -138,32 +138,33 @@ def run(args=None): logging.info("NOTE: Making new data directory at " + data_path + "(This is the first run.)") makedirs(data_path, exist_ok=True) + collection_id = pa.get_cmr_collection_id( + collection_short_name=args.collection, + provider=args.provider, + token=token, + verbose=args.verbose + ) subsettable = False if args.subset: - #get the collection info - params = [ - ('provider', args.provider), - ('ShortName', args.collection) - ] - if token is not None: - params.append(('token', token)) - - # handle errors here - collection_id = pa.get_cmr_collections(params, args.verbose)['items'][0]["meta"]["concept-id"] - subsettable = pa.is_collection_harmony_subsettable(collection_id) - if not subsettable: - logging.info("Collection is not harmony subsettable, proceeding with traditional download") - subsettable = False #i'll set it a 3rd time if it makes me comfortable... - else: - subsettable = True - - - # Traditional downloader - if not subsettable: - success_cnt = cmr_downloader(args, token, data_path) + subsettable = subsetting.is_subsettable( + collection_id=collection_id, + token=token, + ) + + if subsettable: + success_cnt, _ = subsetting.subset( + collection_id=collection_id, + start_date_time=args.startDate, + end_date_time=args.endDate, + bbox=args.bbox, + force=args.force, + data_path=data_path, + args=args, + process_cmd=args.process_cmd, + ) else: - success_cnt = subset(collection_id, args, token, data_path) + success_cnt = cmr_downloader(args, token, data_path) logging.info("Success Count: " + str(success_cnt)) @@ -185,7 +186,7 @@ def cmr_downloader(args, token, data_path): short_name = args.collection extensions = args.extensions process_cmd = args.process_cmd - granule=args.granulename + granule = args.granulename download_limit = None if args.limit is not None and args.limit > 0: @@ -194,11 +195,12 @@ def cmr_downloader(args, token, data_path): # Error catching for output directory specifications # Must specify -d output path or one time-based output directory flag - if sum([args.cycle, args.dydoy, args.dymd, args.dy]) > 1: - parser.error('Too many output directory flags specified, ' - 'Please specify exactly one flag ' - 'from -dc, -dy, -dydoy, or -dymd') + raise ValueError( + 'Too many output directory flags specified, ' + 'Please specify exactly one flag ' + 'from -dc, -dy, -dydoy, or -dymd' + ) if args.offset: ts_shift = timedelta(hours=int(args.offset)) @@ -358,30 +360,6 @@ def cmr_downloader(args, token, data_path): logging.info("Skipped Files: " + str(skip_cnt)) return success_cnt -def subset(collection_id, args, token, data_path): - provider = args.provider - start_date_time = args.startDate - end_date_time = args.endDate - search_cycles = args.search_cycles - short_name = args.collection - extensions = args.extensions - process_cmd = args.process_cmd - granule=args.granulename - - download_limit = None - if args.limit is not None and args.limit > 0: - download_limit = args.limit - success_cnt = 0 - job_id = pa.find_harmony_runs(collection_id, args.bbox, start_date_time, end_date_time, data_path, None) - if not job_id: - job_id = pa.subset(collection_id, args.bbox, start_date_time, end_date_time, data_path) - pa.save_harmony_run(collection_id, args.bbox, start_date_time, end_date_time, job_id, data_path, None) - else: - logging.info("Resuming existing harmony job id...") - - pa.download_subsetted_files(job_id,data_path, args.force) - success_cnt = 1 - return success_cnt def main(): log_level = os.environ.get('PODAAC_LOGLEVEL', 'INFO').upper() diff --git a/subscriber/podaac_data_subscriber.py b/subscriber/podaac_data_subscriber.py index 5f7fd09..52289e8 100755 --- a/subscriber/podaac_data_subscriber.py +++ b/subscriber/podaac_data_subscriber.py @@ -14,15 +14,15 @@ # Accounts are free to create and take just a moment to set up. import argparse import logging -import os, re +import os import sys from datetime import datetime, timedelta from os import makedirs from os.path import isdir, basename, join, isfile, exists from urllib.error import HTTPError -from urllib.request import urlretrieve from subscriber import podaac_access as pa +from subscriber import subsetting __version__ = pa.__version__ @@ -105,6 +105,7 @@ def create_parser(): parser.add_argument("-p", "--provider", dest="provider", default='POCLOUD', help="Specify a provider for collection search. Default is POCLOUD.") # noqa E501 parser.add_argument("--dry-run", dest="dry_run", action="store_true", help="Search and identify files to download, but do not actually download them") # noqa E501 + parser.add_argument("--subset", dest="subset", action="store_true", help="Subset the data via Harmony calls.") # noqa E501 return parser @@ -234,20 +235,85 @@ def run(args=None): logging.info(str(results[ 'hits']) + " new granules found for " + short_name + " since " + data_within_last_timestamp) # noqa E501 + file_start_times = None + cycles = None if any([args.dy, args.dydoy, args.dymd]): file_start_times = pa.parse_start_times(results) elif args.cycle: cycles = pa.parse_cycles(results) - timestamp = datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ") + granules = results['items'] + granules = list(map(lambda granule: granule['meta']['concept-id'], granules)) + + collection_id = pa.get_cmr_collection_id( + collection_short_name=args.collection, + provider=args.provider, + token=token, + verbose=args.verbose + ) + + subsettable = False + if args.subset: + subsettable = subsetting.is_subsettable( + collection_id=collection_id, + token=token, + ) + + if subsettable: + success_cnt, failure_cnt = subsetting.subset( + collection_id=collection_id, + start_date_time=args.startDate, + end_date_time=args.endDate, + bbox=args.bbox, + force=args.force, + data_path=data_path, + args=args, + process_cmd=process_cmd, + granules=granules + ) + else: + success_cnt, failure_cnt, skip_cnt = cmr_downloader( + granules=results['items'], + extensions=extensions, + args=args, + data_path=data_path, + file_start_times=file_start_times, + ts_shift=ts_shift, + cycles=cycles, + process_cmd=process_cmd + ) + + if len(granules) > 0: + if not failure_cnt > 0: + with open(f'{data_path}/.update__{collection_id}', 'w') as f: + f.write(datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ")) + if success_cnt > 0: + try: + pa.create_citation_file(short_name, provider, data_path, token, args.verbose) + except: + logging.debug('Error generating citation', exc_info=True) + + logging.info('END\n\n') + + +def cmr_downloader(granules, extensions, args, data_path, file_start_times, ts_shift, cycles, process_cmd): downloads_all = [] - downloads_data = [[u['URL'] for u in r['umm']['RelatedUrls'] if - u['Type'] == "GET DATA" and ('Subtype' not in u or u['Subtype'] != "OPENDAP DATA")] for r in - results['items']] - downloads_metadata = [[u['URL'] for u in r['umm']['RelatedUrls'] if u['Type'] == "EXTENDED METADATA"] for r in - results['items']] - checksums = pa.extract_checksums(results) + + downloads_data = [ + [ + u['URL'] for u in r['umm']['RelatedUrls'] + if u['Type'] == "GET DATA" + and ('Subtype' not in u or u['Subtype'] != 'OPENDAP DATA') + ] for r in granules + ] + downloads_metadata = [ + [ + u['URL'] for u in r['umm']['RelatedUrls'] + if u['Type'] == 'EXTENDED METADATA' + ] for r in granules + ] + checksums = pa.extract_checksums(granules) for f in downloads_data: downloads_all.append(f) @@ -281,7 +347,6 @@ def run(args=None): logging.info("Dry-run option specific. Exiting.") return - # NEED TO REFACTOR THIS, A LOT OF STUFF in here # Finish by downloading the files to the data directory in a loop. # Overwrite `.update` with a new timestamp on success. @@ -300,14 +365,13 @@ def run(args=None): cycles, data_path, f) # decide if we should actually download this file (e.g. we may already have the latest version) - if(exists(output_path) and not args.force and pa.checksum_does_match(output_path, checksums)): + if (exists(output_path) and not args.force and pa.checksum_does_match( + output_path, checksums)): logging.info(str(datetime.now()) + " SKIPPED: " + f) skip_cnt += 1 continue - #urlretrieve(f, output_path) - pa.download_file(f,output_path) - + pa.download_file(f, output_path) pa.process_file(process_cmd, output_path, args) logging.info(str(datetime.now()) + " SUCCESS: " + f) success_cnt = success_cnt + 1 @@ -315,27 +379,11 @@ def run(args=None): logging.warning(str(datetime.now()) + " FAILURE: " + f, exc_info=True) failure_cnt = failure_cnt + 1 - # If there were updates to the local time series during this run and no - # exceptions were raised during the download loop, then overwrite the - # timestamp file that tracks updates to the data folder - # (`resources/nrt/.update`): - if len(results['items']) > 0: - if not failure_cnt > 0: - with open(data_path + "/.update__" + short_name, "w") as f: - f.write(timestamp) - logging.info("Downloaded Files: " + str(success_cnt)) logging.info("Failed Files: " + str(failure_cnt)) logging.info("Skipped Files: " + str(skip_cnt)) - if success_cnt > 0: - try: - pa.create_citation_file(short_name, provider, data_path, token, args.verbose) - except: - logging.debug("Error generating citation", exc_info=True) - - logging.info("END\n\n") - + return success_cnt, failure_cnt, skip_cnt def main(): log_level = os.environ.get('PODAAC_LOGLEVEL', 'INFO').upper() diff --git a/subscriber/subsetting.py b/subscriber/subsetting.py new file mode 100644 index 0000000..a9b6a5a --- /dev/null +++ b/subscriber/subsetting.py @@ -0,0 +1,93 @@ +import logging +from subscriber import podaac_access as pa + + +def is_subsettable(collection_id, token): + """ + Query CMR to determine if the provided collection is subsettable by + Harmony. In order to be subsettable, an appropriate UMM-S association + needs to be in place. + + Parameters + ---------- + collection_id: str + The CMR collection ID + token: str + EDL token used to query CMR + + Returns + ------- + bool + True if the collection is Harmony subsettable. False if the + collection is not Harmony subsettable. + """ + subsettable = pa.is_collection_harmony_subsettable(collection_id, token) + if not subsettable: + logging.info('Collection is not harmony subsettable, proceeding with traditional download') + return subsettable + + +def subset(collection_id, start_date_time, end_date_time, bbox, force, data_path, args, + process_cmd, granules=None): + """ + Submit Harmony subsetting request and download the results + + Parameters + ---------- + collection_id: str + The CMR collection ID to Harmony subset + start_date_time: str + ISO formatted start time. Used to subset granules in collection + end_date_time: str + ISO formatted end time. Used to subset granules in collection + bbox: str + String in format W,S,E,N + force: bool + If true, overwrite files on download of results + data_path: str + Local path to where results should be downloaded + args: argparse.Namespace + Script args + process_cmd: str + Command to run on each granule upon successful download + granules: list, optional + List of granules to pass to Harmony. This is optional -- if not + provided, Harmony will use the provided spatiotemporal bounds to + find overlapping granules. If provided, Harmony will only operate + on the provided granules. + + Returns + ------- + tuple + (files downloaded successfully, files failed) + """ + job_id = pa.find_harmony_runs( + collection=collection_id, + bbox=bbox, + starttime=start_date_time, + endtime=end_date_time, + output_dir=data_path, + granules=granules + ) + if not job_id: + job_id = pa.subset( + concept_id=collection_id, + bbox=bbox, + start_time=start_date_time, + stop_time=end_date_time, + granules=granules + ) + pa.save_harmony_run( + collection=collection_id, + bbox=bbox, + starttime=start_date_time, + endtime=end_date_time, + job_id=job_id, + output_dir=data_path, + granule_ids=granules + ) + else: + logging.info('Resuming existing harmony job id...') + + job_status = pa.download_subsetted_files(job_id, data_path, args, force, process_cmd) + return 1, 1 if job_status in ('complete_with_errors', 'failed') else 0 From 658ba05fe1d9b09d0784a7379545fb7ce90bae6f Mon Sep 17 00:00:00 2001 From: skperez Date: Fri, 4 Aug 2023 16:35:24 -0700 Subject: [PATCH 06/22] update spacing --- pyproject.toml | 2 -- subscriber/podaac_data_downloader.py | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 5b2e046..6fe3997 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,8 +17,6 @@ requests = "^2.27.1" tenacity = "^8.0.1" harmony-py = "^0.4.9" - - [tool.poetry.dev-dependencies] pytest = "^7.1.2" flake8 = "^4.0.1" diff --git a/subscriber/podaac_data_downloader.py b/subscriber/podaac_data_downloader.py index e12609a..7c63092 100755 --- a/subscriber/podaac_data_downloader.py +++ b/subscriber/podaac_data_downloader.py @@ -168,7 +168,7 @@ def run(args=None): logging.info("Success Count: " + str(success_cnt)) - #create citation file if success > 0 + # create citation file if success > 0 if success_cnt > 0: try: logging.debug("Creating citation file.") From 364dc4079ce14a6a87d9820e5d274ebd91ee8c94 Mon Sep 17 00:00:00 2001 From: skperez Date: Mon, 7 Aug 2023 09:38:00 -0700 Subject: [PATCH 07/22] Update docs --- CHANGELOG.md | 4 ++++ Downloader.md | 3 +++ Subscriber.md | 4 ++++ poetry.lock | 4 ++-- 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d8ca5d6..7b3654f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) +## [Unreleased] +### Added +- Added support for Harmony subsetting + ## [1.14.0] ### Added - Added support for wildcard search patterns in podaac-data-downloader when executed with the -gr option (i.e. search/download by CMR Granule Ur/Id). Also, added usage details to Downloader.md to describe this new feature [138](https://github.com/podaac/data-subscriber/pull/138). diff --git a/Downloader.md b/Downloader.md index 3b15e0d..63805bc 100644 --- a/Downloader.md +++ b/Downloader.md @@ -41,6 +41,7 @@ optional arguments: Specify a provider for collection search. Default is POCLOUD. --limit LIMIT Integer limit for number of granules to download. Useful in testing. Defaults to no limit. --dry-run Search and identify files to download, but do not actually download them + --subset Flag to enable subsetting on the specified collection ``` @@ -236,7 +237,9 @@ and Using the `--process` option, you can run a simple command agaisnt the "just" downloaded file. This will take the format of " ". This means you can run a command like `--process gzip` to gzip all downloaded files. We do not support more advanced processes at this time (piping, running a process on a directory, etc). +### Granule subsetting +To enable granule subsetting, include the `--subset` flag in your request. This will invoke the NASA Harmony API to subset the granules in the specified collection. The collection must have subsetting enabled for this feature to function. If it does not, the data will be downloaded normally. ### In need of Help? The PO.DAAC User Services Office is the primary point of contact for answering your questions concerning data and information held by the PO.DAAC. User Services staff members are knowledgeable about both the data ordering system and the data products themselves. We answer questions about data, route requests to other DAACs, and direct questions we cannot answer to the appropriate information source. diff --git a/Subscriber.md b/Subscriber.md index f3afc1b..551b849 100644 --- a/Subscriber.md +++ b/Subscriber.md @@ -35,6 +35,7 @@ $> podaac-data-subscriber -h -p PROVIDER, --provider PROVIDER Specify a provider for collection search. Default is POCLOUD. --dry-run Search and identify files to download, but do not actually download them +--subset Flag to enable subsetting on the specified collection ``` ## Run the Script @@ -212,6 +213,9 @@ and Using the `--process` option, you can run a simple command agaisnt the "just" downloaded file. This will take the format of " ". This means you can run a command like `--process gzip` to gzip all downloaded files. We do not support more advanced processes at this time (piping, running a process on a directory, etc). +### Granule subsetting + +To enable granule subsetting, include the `--subset` flag in your request. This will invoke the NASA Harmony API to subset the granules in the specified collection. The collection must have subsetting enabled for this feature to function. If it does not, the data will be downloaded normally. ### In need of Help? The PO.DAAC User Services Office is the primary point of contact for answering your questions concerning data and information held by the PO.DAAC. User Services staff members are knowledgeable about both the data ordering system and the data products themselves. We answer questions about data, route requests to other DAACs, and direct questions we cannot answer to the appropriate information source. diff --git a/poetry.lock b/poetry.lock index 3c20f24..eba454d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -239,7 +239,7 @@ files = [ name = "packaging" version = "23.1" description = "Core utilities for Python packages" -category = "dev" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -543,4 +543,4 @@ testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more [metadata] lock-version = "2.0" python-versions = "^3.7" -content-hash = "408b1292a8478f6220f742eecfaa1a55acc7e7584eaeb60292962af4fef3fa59" +content-hash = "3e86d63c7fceba752c5a9abd6a6d4e868d7f1875dd37cb45db7c4c7050630298" From 0b30966c42b2140a518894353e5f824a1a55a863 Mon Sep 17 00:00:00 2001 From: skperez Date: Fri, 18 Aug 2023 14:11:35 -0700 Subject: [PATCH 08/22] update poetry lock --- poetry.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/poetry.lock b/poetry.lock index eba454d..d7bfe55 100644 --- a/poetry.lock +++ b/poetry.lock @@ -125,14 +125,14 @@ requests = "*" [[package]] name = "exceptiongroup" -version = "1.1.2" +version = "1.1.3" description = "Backport of PEP 654 (exception groups)" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "exceptiongroup-1.1.2-py3-none-any.whl", hash = "sha256:e346e69d186172ca7cf029c8c1d16235aa0e04035e5750b4b95039e65204328f"}, - {file = "exceptiongroup-1.1.2.tar.gz", hash = "sha256:12c3e887d6485d16943a309616de20ae5582633e0a2eda17f4e10fd61c1e8af5"}, + {file = "exceptiongroup-1.1.3-py3-none-any.whl", hash = "sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3"}, + {file = "exceptiongroup-1.1.3.tar.gz", hash = "sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9"}, ] [package.extras] @@ -469,14 +469,14 @@ six = ">=1.5.2" [[package]] name = "tenacity" -version = "8.2.2" +version = "8.2.3" description = "Retry code until it succeeds" category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "tenacity-8.2.2-py3-none-any.whl", hash = "sha256:2f277afb21b851637e8f52e6a613ff08734c347dc19ade928e519d7d2d8569b0"}, - {file = "tenacity-8.2.2.tar.gz", hash = "sha256:43af037822bd0029025877f3b2d97cc4d7bb0c2991000a3d59d71517c5c969e0"}, + {file = "tenacity-8.2.3-py3-none-any.whl", hash = "sha256:ce510e327a630c9e1beaf17d42e6ffacc88185044ad85cf74c0a8887c6a0f88c"}, + {file = "tenacity-8.2.3.tar.gz", hash = "sha256:5398ef0d78e63f40007c1fb4c0bff96e1911394d2fa8d194f77619c05ff6cc8a"}, ] [package.extras] From c9513c51abd1e8231956186a81e57cc951571f70 Mon Sep 17 00:00:00 2001 From: skperez Date: Fri, 18 Aug 2023 14:21:07 -0700 Subject: [PATCH 09/22] upgrade to poetry 1.5.1 (latest) --- .github/workflows/python-app.yml | 2 +- poetry.lock | 32 +------------------------------- 2 files changed, 2 insertions(+), 32 deletions(-) diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml index d713f51..ef6347d 100644 --- a/.github/workflows/python-app.yml +++ b/.github/workflows/python-app.yml @@ -16,7 +16,7 @@ jobs: max-parallel: 2 matrix: python-version: [ "3.7", "3.8", "3.9", "3.10" ] - poetry-version: [ "1.1.14" ] + poetry-version: [ "1.5.1" ] os: [ ubuntu-22.04, macos-latest, windows-latest ] runs-on: ${{ matrix.os }} steps: diff --git a/poetry.lock b/poetry.lock index d7bfe55..fd9315f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,10 +1,9 @@ -# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. [[package]] name = "certifi" version = "2023.7.22" description = "Python package for providing Mozilla's CA Bundle." -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -16,7 +15,6 @@ files = [ name = "charset-normalizer" version = "3.2.0" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -category = "main" optional = false python-versions = ">=3.7.0" files = [ @@ -101,7 +99,6 @@ files = [ name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." -category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ @@ -113,7 +110,6 @@ files = [ name = "curlify" version = "2.2.1" description = "Library to convert python requests object to curl command." -category = "main" optional = false python-versions = "*" files = [ @@ -127,7 +123,6 @@ requests = "*" name = "exceptiongroup" version = "1.1.3" description = "Backport of PEP 654 (exception groups)" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -142,7 +137,6 @@ test = ["pytest (>=6)"] name = "flake8" version = "4.0.1" description = "the modular source code checker: pep8 pyflakes and co" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -160,7 +154,6 @@ pyflakes = ">=2.4.0,<2.5.0" name = "harmony-py" version = "0.4.9" description = "The NASA Harmony Python library" -category = "main" optional = false python-versions = ">=3.6, <4" files = [ @@ -183,7 +176,6 @@ dev = ["PyYAML (>=5.4,<6.0)", "autopep8 (>=1.4,<2.0)", "camel-case-switcher (>=2 name = "idna" version = "3.4" description = "Internationalized Domain Names in Applications (IDNA)" -category = "main" optional = false python-versions = ">=3.5" files = [ @@ -195,7 +187,6 @@ files = [ name = "importlib-metadata" version = "4.2.0" description = "Read metadata from Python packages" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -215,7 +206,6 @@ testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pep517", name = "iniconfig" version = "2.0.0" description = "brain-dead simple config-ini parsing" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -227,7 +217,6 @@ files = [ name = "mccabe" version = "0.6.1" description = "McCabe checker, plugin for flake8" -category = "dev" optional = false python-versions = "*" files = [ @@ -239,7 +228,6 @@ files = [ name = "packaging" version = "23.1" description = "Core utilities for Python packages" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -251,7 +239,6 @@ files = [ name = "pluggy" version = "1.2.0" description = "plugin and hook calling mechanisms for python" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -270,7 +257,6 @@ testing = ["pytest", "pytest-benchmark"] name = "pockets" version = "0.9.1" description = "A collection of helpful Python tools!" -category = "main" optional = false python-versions = "*" files = [ @@ -285,7 +271,6 @@ six = ">=1.5.2" name = "progressbar2" version = "3.55.0" description = "A Python Progressbar library to provide visual (yet text based) progress to long running operations." -category = "main" optional = false python-versions = "*" files = [ @@ -305,7 +290,6 @@ tests = ["flake8 (>=3.7.7)", "freezegun (>=0.3.11)", "pytest (>=4.6.9)", "pytest name = "pycodestyle" version = "2.8.0" description = "Python style guide checker" -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -317,7 +301,6 @@ files = [ name = "pyflakes" version = "2.4.0" description = "passive checker of Python programs" -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -329,7 +312,6 @@ files = [ name = "pytest" version = "7.4.0" description = "pytest: simple powerful testing with Python" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -353,7 +335,6 @@ testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "no name = "pytest-mock" version = "3.11.1" description = "Thin-wrapper around the mock package for easier use with pytest" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -371,7 +352,6 @@ dev = ["pre-commit", "pytest-asyncio", "tox"] name = "python-dateutil" version = "2.8.2" description = "Extensions to the standard Python datetime module" -category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" files = [ @@ -386,7 +366,6 @@ six = ">=1.5" name = "python-dotenv" version = "0.20.0" description = "Read key-value pairs from a .env file and set them as environment variables" -category = "main" optional = false python-versions = ">=3.5" files = [ @@ -401,7 +380,6 @@ cli = ["click (>=5.0)"] name = "python-utils" version = "3.5.2" description = "Python Utils is a module with some convenient utilities not included with the standard Python install" -category = "main" optional = false python-versions = ">3.6.0" files = [ @@ -421,7 +399,6 @@ tests = ["flake8", "loguru", "pytest", "pytest-asyncio", "pytest-cov", "pytest-m name = "requests" version = "2.31.0" description = "Python HTTP for Humans." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -443,7 +420,6 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] name = "six" version = "1.16.0" description = "Python 2 and 3 compatibility utilities" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -455,7 +431,6 @@ files = [ name = "sphinxcontrib-napoleon" version = "0.7" description = "Sphinx \"napoleon\" extension." -category = "main" optional = false python-versions = "*" files = [ @@ -471,7 +446,6 @@ six = ">=1.5.2" name = "tenacity" version = "8.2.3" description = "Retry code until it succeeds" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -486,7 +460,6 @@ doc = ["reno", "sphinx", "tornado (>=4.5)"] name = "tomli" version = "2.0.1" description = "A lil' TOML parser" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -498,7 +471,6 @@ files = [ name = "typing-extensions" version = "4.7.1" description = "Backported and Experimental Type Hints for Python 3.7+" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -510,7 +482,6 @@ files = [ name = "urllib3" version = "2.0.4" description = "HTTP library with thread-safe connection pooling, file post, and more." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -528,7 +499,6 @@ zstd = ["zstandard (>=0.18.0)"] name = "zipp" version = "3.15.0" description = "Backport of pathlib-compatible object wrapper for zip files" -category = "dev" optional = false python-versions = ">=3.7" files = [ From 3decb92ecf899833590ab83ebb63276a89ab2d52 Mon Sep 17 00:00:00 2001 From: skperez Date: Fri, 18 Aug 2023 15:41:47 -0700 Subject: [PATCH 10/22] fix failing checksum test --- subscriber/podaac_data_downloader.py | 2 +- tests/test_subscriber_extracting_checksums.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/subscriber/podaac_data_downloader.py b/subscriber/podaac_data_downloader.py index 0149ad7..08408ae 100755 --- a/subscriber/podaac_data_downloader.py +++ b/subscriber/podaac_data_downloader.py @@ -284,7 +284,7 @@ def cmr_downloader(args, token, data_path): results['items']] downloads_metadata = [[u['URL'] for u in r['umm']['RelatedUrls'] if u['Type'] == "EXTENDED METADATA"] for r in results['items']] - checksums = pa.extract_checksums(results) + checksums = pa.extract_checksums(results['items']) for f in downloads_data: downloads_all.append(f) diff --git a/tests/test_subscriber_extracting_checksums.py b/tests/test_subscriber_extracting_checksums.py index 87a5f00..5192d65 100644 --- a/tests/test_subscriber_extracting_checksums.py +++ b/tests/test_subscriber_extracting_checksums.py @@ -104,7 +104,7 @@ """ def test_extract_checksums(): - checksums = extract_checksums(json.loads(minimal_granule_search_results)) + checksums = extract_checksums(json.loads(minimal_granule_search_results)['items']) assert checksums["20211231000000-REMSS-L3U_GHRSST-SSTsubskin-AMSR2-f34_20211231v8-v02.0-fv01.0.nc"] == { "Value": "d96387295ea979fb8f7b9aa5f231c4ab", "Algorithm": "MD5" From 285970b01066c7e165a2623e94aaf89f24f95b59 Mon Sep 17 00:00:00 2001 From: skperez Date: Fri, 18 Aug 2023 16:15:05 -0700 Subject: [PATCH 11/22] fixed regression test issues --- subscriber/podaac_data_subscriber.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/subscriber/podaac_data_subscriber.py b/subscriber/podaac_data_subscriber.py index a3e019d..f7bb7f5 100755 --- a/subscriber/podaac_data_subscriber.py +++ b/subscriber/podaac_data_subscriber.py @@ -284,9 +284,9 @@ def run(args=None): process_cmd=process_cmd ) - if len(granules) > 0: + if len(granules) > 0 and not args.dry_run: if not failure_cnt > 0: - with open(f'{data_path}/.update__{collection_id}', 'w') as f: + with open(f'{data_path}/.update__{args.collection}', 'w') as f: f.write(datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ")) if success_cnt > 0: @@ -346,7 +346,7 @@ def cmr_downloader(granules, extensions, args, data_path, file_start_times, ts_s for download in downloads: logging.info(download) logging.info("Dry-run option specific. Exiting.") - return + return 0, 0, 0 # NEED TO REFACTOR THIS, A LOT OF STUFF in here # Finish by downloading the files to the data directory in a loop. From d5dcceaabfd19e6f2a8faa6ad77c93b5bbff106a Mon Sep 17 00:00:00 2001 From: skperez Date: Mon, 21 Aug 2023 08:52:59 -0700 Subject: [PATCH 12/22] bump poetry version in second gh action file --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2697eb1..7133f88 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,7 +20,7 @@ jobs: - name: Install Poetry uses: abatilo/actions-poetry@v2.0.0 with: - poetry-version: 1.1.14 + poetry-version: [ "1.5.1" ] - name: Install dependencies run: | poetry install From ceceae828fdb1f06a344a9ad934d9c406724bf0c Mon Sep 17 00:00:00 2001 From: skperez Date: Mon, 21 Aug 2023 15:26:39 -0700 Subject: [PATCH 13/22] Update poetry version to fix build issue --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7133f88..ef4aa2c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,7 +20,7 @@ jobs: - name: Install Poetry uses: abatilo/actions-poetry@v2.0.0 with: - poetry-version: [ "1.5.1" ] + poetry-version: "1.5.1" - name: Install dependencies run: | poetry install From 63192509139a1e44803049ccbfcf18bb3e19646a Mon Sep 17 00:00:00 2001 From: skperez Date: Tue, 22 Aug 2023 09:42:29 -0700 Subject: [PATCH 14/22] bump poetry version --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ef4aa2c..22fc272 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,7 +20,7 @@ jobs: - name: Install Poetry uses: abatilo/actions-poetry@v2.0.0 with: - poetry-version: "1.5.1" + poetry-version: '1.5.1' - name: Install dependencies run: | poetry install From 12ca7b4b8e80b65582dddc697b367eeee877c4b5 Mon Sep 17 00:00:00 2001 From: skperez Date: Tue, 22 Aug 2023 11:56:21 -0700 Subject: [PATCH 15/22] bump poetry version --- .github/workflows/python-app.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml index ef6347d..52e8f59 100644 --- a/.github/workflows/python-app.yml +++ b/.github/workflows/python-app.yml @@ -63,7 +63,7 @@ jobs: max-parallel: 1 matrix: python-version: [ "3.7", "3.8", "3.9", "3.10" ] - poetry-version: [ "1.1.14" ] + poetry-version: [ "1.5.1" ] os: [ ubuntu-22.04, macos-latest, windows-latest ] runs-on: ${{ matrix.os }} steps: From cd217eb7a5dfa2500996183923dec503d985d4d4 Mon Sep 17 00:00:00 2001 From: skperez Date: Tue, 22 Aug 2023 13:51:48 -0700 Subject: [PATCH 16/22] bump version to 1.15.0 --- CHANGELOG.md | 2 +- pyproject.toml | 2 +- subscriber/podaac_access.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b3654f..87a1a25 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) -## [Unreleased] +## [1.15.0] ### Added - Added support for Harmony subsetting diff --git a/pyproject.toml b/pyproject.toml index 9a80994..7154a50 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "podaac-data-subscriber" -version = "1.14.0" +version = "1.15.0-alpha.1 description = "PO.DAAC Data Subscriber Command Line Tool" authors = ["PO.DAAC "] readme = "README.md" diff --git a/subscriber/podaac_access.py b/subscriber/podaac_access.py index 4096a67..77ef65e 100644 --- a/subscriber/podaac_access.py +++ b/subscriber/podaac_access.py @@ -26,7 +26,7 @@ import tenacity from datetime import datetime -__version__ = "1.14.0" +__version__ = "1.15.0" extensions = ["\\.nc", "\\.h5", "\\.zip", "\\.tar.gz", "\\.tiff"] edl = "urs.earthdata.nasa.gov" cmr = "cmr.earthdata.nasa.gov" From 7c126019c9a9d348b4013c90bfec51828f8e6e2d Mon Sep 17 00:00:00 2001 From: skperez Date: Tue, 22 Aug 2023 14:33:42 -0700 Subject: [PATCH 17/22] bump version to 1.15.0 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 7154a50..e5d9a40 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "podaac-data-subscriber" -version = "1.15.0-alpha.1 +version = "1.15.0-alpha.1" description = "PO.DAAC Data Subscriber Command Line Tool" authors = ["PO.DAAC "] readme = "README.md" From c85590344bcffe063fb9b4894ef100e3972ae235 Mon Sep 17 00:00:00 2001 From: skperez Date: Mon, 5 Feb 2024 15:40:00 -0800 Subject: [PATCH 18/22] add unreleased section to changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 87a1a25..8486031 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) +## [Unreleased] +### Fixed +### Added + ## [1.15.0] ### Added - Added support for Harmony subsetting From 9782d1fa81192fe4e8c13caf159b615413569652 Mon Sep 17 00:00:00 2001 From: Stepheny Perez Date: Thu, 7 Mar 2024 09:03:03 -0800 Subject: [PATCH 19/22] issue/161: Fix bug where --subset flag fails with data subscriber (#162) * fix bug where the subset flag fails for subscriber * move arg validation to correct spot --- CHANGELOG.md | 1 + subscriber/podaac_access.py | 7 ------- subscriber/podaac_data_downloader.py | 7 +++++++ 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8486031..7f00524 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ## [Unreleased] ### Fixed +- Fixed bug where --subset in combination with the subscriber caused errors ### Added ## [1.15.0] diff --git a/subscriber/podaac_access.py b/subscriber/podaac_access.py index e69da75..48be4b3 100644 --- a/subscriber/podaac_access.py +++ b/subscriber/podaac_access.py @@ -221,13 +221,6 @@ def validate(args): 'Please specify exactly one flag ' 'from -dc, -dy, -dydoy, or -dymd') - if args.subset and args.search_cycles: - # Cycle+Subset are not supported, because Harmony does not - # currently accept Cycle. - raise ValueError( - 'Error: Incompatible Parameters. You\'ve provided both cycles and subset, which is ' - 'not allowed. Please provide either cycles or subset separately, but not both.') - if args.subset and args.bbox: bounds = list(map(float, args.bbox.split(','))) if bounds[0] > bounds[2]: diff --git a/subscriber/podaac_data_downloader.py b/subscriber/podaac_data_downloader.py index 08408ae..aff5956 100755 --- a/subscriber/podaac_data_downloader.py +++ b/subscriber/podaac_data_downloader.py @@ -44,6 +44,13 @@ def validate(args): if None in [args.endDate, args.startDate] and args.search_cycles is None and args.granulename is None: raise ValueError( "Error parsing command line arguments: Both --start-date and --end-date must be specified") # noqa E50 + if args.subset and args.search_cycles: + # Cycle+Subset are not supported, because Harmony does not + # currently accept Cycle. + raise ValueError( + 'Error: Incompatible Parameters. You\'ve provided both cycles and subset, which is ' + 'not allowed. Please provide either cycles or subset separately, but not both.' + ) def create_parser(): From 080987e4dca95026dad97d5a5a041038c17e88be Mon Sep 17 00:00:00 2001 From: skperez Date: Thu, 7 Mar 2024 09:04:59 -0800 Subject: [PATCH 20/22] bump version --- CHANGELOG.md | 2 +- pyproject.toml | 2 +- subscriber/podaac_access.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f00524..ccf9276 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) -## [Unreleased] +## [1.15.1] ### Fixed - Fixed bug where --subset in combination with the subscriber caused errors ### Added diff --git a/pyproject.toml b/pyproject.toml index 47f56a4..c748703 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "podaac-data-subscriber" -version = "1.15.0" +version = "1.15.1" description = "PO.DAAC Data Subscriber Command Line Tool" authors = ["PO.DAAC "] readme = "README.md" diff --git a/subscriber/podaac_access.py b/subscriber/podaac_access.py index 48be4b3..bd83207 100644 --- a/subscriber/podaac_access.py +++ b/subscriber/podaac_access.py @@ -26,7 +26,7 @@ import tenacity from datetime import datetime -__version__ = "1.15.0" +__version__ = "1.15.1" extensions = ["\\.nc", "\\.h5", "\\.zip", "\\.tar.gz", "\\.tiff"] edl = "urs.earthdata.nasa.gov" cmr = "cmr.earthdata.nasa.gov" From 4528e6e4f56bd7f77de8d7164229c7c3785f8575 Mon Sep 17 00:00:00 2001 From: skperez Date: Thu, 7 Mar 2024 09:57:24 -0800 Subject: [PATCH 21/22] bump version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index c748703..3fe7d51 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "podaac-data-subscriber" -version = "1.15.1" +version = "1.15.1-alpha.1" description = "PO.DAAC Data Subscriber Command Line Tool" authors = ["PO.DAAC "] readme = "README.md" From e5f8205b9b283537a29184580a4f575c7b10615a Mon Sep 17 00:00:00 2001 From: Stepheny Perez Date: Thu, 14 Mar 2024 12:34:03 -0700 Subject: [PATCH 22/22] Issue/164: Upgrade harmony-py to avoid 413 request entity too large issue (#165) * bump harmony-py version to 0.4.12 * /version 1.15.1-alpha.2 --- poetry.lock | 27 +++++++++++++-------------- pyproject.toml | 4 ++-- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/poetry.lock b/poetry.lock index fd9315f..21bff98 100644 --- a/poetry.lock +++ b/poetry.lock @@ -152,25 +152,25 @@ pyflakes = ">=2.4.0,<2.5.0" [[package]] name = "harmony-py" -version = "0.4.9" +version = "0.4.12" description = "The NASA Harmony Python library" optional = false python-versions = ">=3.6, <4" files = [ - {file = "harmony-py-0.4.9.tar.gz", hash = "sha256:9e72d80029e2e1708ecd40c30a2498bbdcbf406d659da8073da29c5c64fd34cd"}, - {file = "harmony_py-0.4.9-py3-none-any.whl", hash = "sha256:a37d2226732c937c5599d5ba7e669aebc024a824bccef0cf8625346c340716b1"}, + {file = "harmony-py-0.4.12.tar.gz", hash = "sha256:735b1410306110e6a0e76c305db98730d0060389fdc9e8403d2e4b0049143355"}, + {file = "harmony_py-0.4.12-py3-none-any.whl", hash = "sha256:526405f0cec67a5545609e7ded56fc279b036ebd2cf08606b8e05fc5fc7f61ec"}, ] [package.dependencies] curlify = ">=2.2.1,<2.3.0" -progressbar2 = ">=3.55.0,<3.56.0" +progressbar2 = ">=4.2.0,<4.3.0" python-dateutil = ">=2.8.2,<2.9.0" python-dotenv = ">=0.20.0,<0.21.0" requests = ">=2.28,<3.0" sphinxcontrib-napoleon = ">=0.7,<1.0" [package.extras] -dev = ["PyYAML (>=5.4,<6.0)", "autopep8 (>=1.4,<2.0)", "camel-case-switcher (>=2.0,<3.0)", "coverage (>=5.4,<6.0)", "flake8 (>=3.8,<4.0)", "hypothesis (>=6.2,<7.0)", "importlib-metadata (<5.0)", "mypy (>=0.812,<1.0)", "nose (>=1.3,<2.0)", "pytest (>=6.2,<7.0)", "pytest-cov (>=2.11,<3.0)", "pytest-mock (>=3.5,<4.0)", "pytest-watch (>=4.2,<5.0)", "responses (>=0.12,<1.0)", "setuptools (>=54.2)", "sphinx (>=5.3.0,<5.4.0)", "wheel (>=0.36)"] +dev = ["PyYAML (>=6.0.1,<6.1.0)", "autopep8 (>=1.4,<2.0)", "camel-case-switcher (>=2.0,<3.0)", "coverage (>=5.4,<6.0)", "flake8 (>=3.8,<4.0)", "hypothesis (>=6.2,<7.0)", "importlib-metadata (<5.0)", "mypy (>=0.812,<1.0)", "nose (>=1.3,<2.0)", "pytest (>=6.2,<7.0)", "pytest-cov (>=2.11,<3.0)", "pytest-mock (>=3.5,<4.0)", "pytest-watch (>=4.2,<5.0)", "responses (>=0.12,<1.0)", "setuptools (>=54.2)", "sphinx (>=7.1.2,<7.2.0)", "wheel (>=0.36)"] [[package]] name = "idna" @@ -269,22 +269,21 @@ six = ">=1.5.2" [[package]] name = "progressbar2" -version = "3.55.0" +version = "4.2.0" description = "A Python Progressbar library to provide visual (yet text based) progress to long running operations." optional = false -python-versions = "*" +python-versions = ">=3.7.0" files = [ - {file = "progressbar2-3.55.0-py2.py3-none-any.whl", hash = "sha256:e98fee031da31ab9138fd8dd838ac80eafba82764eb75a43d25e3ca622f47d14"}, - {file = "progressbar2-3.55.0.tar.gz", hash = "sha256:86835d1f1a9317ab41aeb1da5e4184975e2306586839d66daf63067c102f8f04"}, + {file = "progressbar2-4.2.0-py2.py3-none-any.whl", hash = "sha256:1a8e201211f99a85df55f720b3b6da7fb5c8cdef56792c4547205be2de5ea606"}, + {file = "progressbar2-4.2.0.tar.gz", hash = "sha256:1393922fcb64598944ad457569fbeb4b3ac189ef50b5adb9cef3284e87e394ce"}, ] [package.dependencies] -python-utils = ">=2.3.0" -six = "*" +python-utils = ">=3.0.0" [package.extras] -docs = ["sphinx (>=1.7.4)"] -tests = ["flake8 (>=3.7.7)", "freezegun (>=0.3.11)", "pytest (>=4.6.9)", "pytest-cov (>=2.6.1)", "sphinx (>=1.8.5)"] +docs = ["sphinx (>=1.8.5)"] +tests = ["flake8 (>=3.7.7)", "freezegun (>=0.3.11)", "pytest (>=4.6.9)", "pytest-cov (>=2.6.1)", "pytest-mypy", "sphinx (>=1.8.5)"] [[package]] name = "pycodestyle" @@ -513,4 +512,4 @@ testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more [metadata] lock-version = "2.0" python-versions = "^3.7" -content-hash = "3e86d63c7fceba752c5a9abd6a6d4e868d7f1875dd37cb45db7c4c7050630298" +content-hash = "134b9ae9f97c067afc9c98706b622285801c0690ea00ec371712797b756e5c24" diff --git a/pyproject.toml b/pyproject.toml index 3fe7d51..0313175 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "podaac-data-subscriber" -version = "1.15.1-alpha.1" +version = "1.15.1-alpha.2" description = "PO.DAAC Data Subscriber Command Line Tool" authors = ["PO.DAAC "] readme = "README.md" @@ -16,7 +16,7 @@ python = "^3.7" requests = "^2.27.1" tenacity = "^8.0.1" packaging = "^23.0" -harmony-py = "^0.4.9" +harmony-py = "^0.4.12" [tool.poetry.dev-dependencies] pytest = "^7.1.2"