diff --git a/.github/workflows/calculate-times.yaml b/.github/workflows/calculate-times.yaml index 1d519cc..b5d54d2 100644 --- a/.github/workflows/calculate-times.yaml +++ b/.github/workflows/calculate-times.yaml @@ -188,7 +188,7 @@ jobs: echo "chunks=$(cat chunks.txt)" >> $GITHUB_OUTPUT # If override chunks are set, use those instead - chunks_parsed=($(echo "$chunks" | jq -r '.[]')) + chunks_parsed=($(cat chunks.txt | jq -r '.[]')) if [ -n "${{ inputs.override_chunks }}" ]; then override_chunks_parsed=($(echo "${{ inputs.override_chunks }}" | tr -d ' ' | tr ',' ' ')) for chunk in "${override_chunks_parsed[@]}"; do @@ -280,6 +280,21 @@ jobs: tar -xf ./build/valhalla_tiles.tar.zst -C ./build rm -f ./build/valhalla_tiles.tar.zst + # In rare cases the runner gets killed due to OoM errors. This bumps swap + # to 90% of the space remaining on disk + - name: Increase swapfile + run: | + space_left=$(df /dev/root -B 1 --output=avail | grep -v Avail) + space_mult=0.9 + space_alloc=$(echo "${space_left}*${space_mult}" | bc) + space_alloc_rnd=$(printf %.0f $(echo ${space_alloc})) + sudo swapoff -a + sudo fallocate -l ${space_alloc_rnd} /swapfile + sudo chmod 600 /swapfile + sudo mkswap /swapfile + sudo swapon /swapfile + sudo swapon --show + - name: Run job chunk shell: bash working-directory: 'data' diff --git a/data/params.yaml b/data/params.yaml index 56d4c2c..531231b 100644 --- a/data/params.yaml +++ b/data/params.yaml @@ -20,7 +20,7 @@ actions: # The minimum number of origins to include in a job. Higher = fewer jobs # that take longer. Lower = more jobs that finish quicker - origin_min_chunk_size: 900 + origin_min_chunk_size: 1000 # The max number of destination splits to create for a workflow destination_n_chunks: 4 @@ -46,7 +46,7 @@ times: # Maximum size of chunk of origins AND destinations to process in a single call to # Valhalla. This is necessary because larger matrices will cause it to choke - max_split_size: 150 + max_split_size: 100 # Coordinates are snapped to the OSM street network before time calculation. # Setting this to true will use the snapped coordinates directly in the diff --git a/data/src/calculate_times.py b/data/src/calculate_times.py index 6e7bed2..10eafc2 100644 --- a/data/src/calculate_times.py +++ b/data/src/calculate_times.py @@ -65,7 +65,9 @@ def main() -> None: inputs.destinations, config.args.mode ) - # Calculate times for each chunk and return a single DataFrame + # Calculate times for each chunk and return a single DataFrame. Assumes + # there are Valhalla services running locally at localhost:8002 (and :8003 + # if second-pass is enabled) logger.info("Tiles loaded and coodinates ready, starting routing") tt_calc = TravelTimeCalculator(config, inputs) results_df = tt_calc.many_to_many() diff --git a/data/src/utils/times.py b/data/src/utils/times.py index 89fe997..e02b120 100644 --- a/data/src/utils/times.py +++ b/data/src/utils/times.py @@ -3,6 +3,8 @@ import logging import os import re +import shutil +import subprocess import time from concurrent.futures import ThreadPoolExecutor from pathlib import Path @@ -104,7 +106,11 @@ def __init__( self.compression_level: int = compression_level self.endpoint_url: str | None = endpoint_url self.storage_options = { - "s3": {"client_kwargs": {"endpoint_url": endpoint_url}}, + "s3": { + # https://github.com/fsspec/s3fs/pull/888 + "client_kwargs": {"endpoint_url": endpoint_url}, + "fixed_upload_size": True, + }, "local": {}, } @@ -331,6 +337,7 @@ def __init__( args: argparse.Namespace, params: dict, logger: logging.Logger, + ncpu: int | None = None, verbose: bool = False, ) -> None: self.args = TravelTimeArgs(args, params) @@ -344,6 +351,7 @@ def __init__( endpoint_url=self.params["s3"]["endpoint_url"], ) self.logger = logger + self.ncpu = ncpu if ncpu else os.cpu_count() self.verbose = verbose def _load_od_file(self, path: str) -> pd.DataFrame: @@ -566,7 +574,7 @@ def many_to_many(self, second_pass: bool = True) -> pd.DataFrame: m_spl_d = self.inputs.max_split_size_destinations n_dc = self.inputs.n_destinations - with ThreadPoolExecutor(max_workers=os.cpu_count()) as executor: + with ThreadPoolExecutor(self.config.ncpu) as executor: futures = [] for o in range(0, n_oc, max_spl_o): for d in range(0, n_dc, m_spl_d): @@ -608,6 +616,22 @@ def many_to_many(self, second_pass: bool = True) -> pd.DataFrame: # Check for completeness in the output. If any times are missing # after the first pass, run a second pass with the fallback router if results_df.isnull().values.any() and second_pass: + # Stop the first-pass Docker container with the goal of freeing + # the memory used by Valhalla caching + if shutil.which("docker"): + self.config.logger.info( + "Stopping first-pass Valhalla Docker container" + ) + subprocess.run( + ["docker", "compose", "down", "valhalla-run-fp"], + check=True, + text=True, + ) + else: + self.config.logger.warning( + "Tried to stop the first-pass Valhalla Docker container, " + "but Docker is not installed on this machine" + ) missing = results_df[results_df["duration_sec"].isnull()] self.config.logger.info( "Starting second pass for %s missing pairs (out of %s total)", @@ -651,11 +675,7 @@ def many_to_many(self, second_pass: bool = True) -> pd.DataFrame: o_ids = missing_set["origin_id"].unique() d_ids = missing_set["destination_id"].unique() - # Don't use the all cores here as it tends to choke - ncpu = os.cpu_count() - ncpu = ncpu - 1 if ncpu is not None and ncpu > 1 else 1 - - with ThreadPoolExecutor(max_workers=ncpu) as executor: + with ThreadPoolExecutor(self.config.ncpu) as executor: futures = [] for o in range(0, len(o_ids), max_spl_o): for d in range(0, len(d_ids), m_spl_d): diff --git a/data/valhalla.json b/data/valhalla.json index 2c98e53..b9e0d1c 100644 --- a/data/valhalla.json +++ b/data/valhalla.json @@ -128,7 +128,7 @@ "max_cache_size": 3000000000, "max_concurrent_reader_users": 1, "reclassify_links": true, - "shortcuts": true, + "shortcuts": false, "tile_dir": "/custom_files/tiles", "tile_extract": "/custom_files/tiles.tar", "timezone": "/custom_files/timezone_data/timezones.sqlite", diff --git a/data/valhalla_sp.json b/data/valhalla_sp.json index e697eef..30031b1 100644 --- a/data/valhalla_sp.json +++ b/data/valhalla_sp.json @@ -130,7 +130,7 @@ "max_cache_size": 3000000000, "max_concurrent_reader_users": 1, "reclassify_links": true, - "shortcuts": true, + "shortcuts": false, "tile_dir": "/custom_files/tiles", "tile_extract": "/custom_files/tiles.tar", "timezone": "/custom_files/timezone_data/timezones.sqlite", diff --git a/pyproject.toml b/pyproject.toml index 5369652..eb03513 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,7 +40,8 @@ data = [ "pandas==2.2.3", "pyarrow==17.0.0", "pyyaml==6.0.2", - "requests==2.32.3" + "requests==2.32.3", + "s3fs==2024.12.0", ] site = [ "boto3==1.35.35", diff --git a/uv.lock b/uv.lock index d484fad..47be187 100644 --- a/uv.lock +++ b/uv.lock @@ -440,7 +440,7 @@ name = "click" version = "8.1.7" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "platform_system == 'Windows'" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/96/d3/f04c7bfcf5c1862a2a5b845c6b2b360488cf47af55dfa79c98f6a6bf98b5/click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de", size = 336121 } wheels = [ @@ -498,6 +498,9 @@ name = "configobj" version = "5.0.9" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/f5/c4/c7f9e41bc2e5f8eeae4a08a01c91b2aea3dfab40a3e14b25e87e7db8d501/configobj-5.0.9.tar.gz", hash = "sha256:03c881bbf23aa07bccf1b837005975993c4ab4427ba57f959afdd9d1a2386848", size = 101518 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a6/c4/0679472c60052c27efa612b4cd3ddd2a23e885dcdc73461781d2c802d39e/configobj-5.0.9-py2.py3-none-any.whl", hash = "sha256:1ba10c5b6ee16229c79a05047aeda2b55eb4e80d7c7d8ecf17ec1ca600c79882", size = 35615 }, +] [[package]] name = "contourpy" @@ -1130,11 +1133,11 @@ wheels = [ [[package]] name = "fsspec" -version = "2024.10.0" +version = "2024.12.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a0/52/f16a068ebadae42526484c31f4398e62962504e5724a8ba5dc3409483df2/fsspec-2024.10.0.tar.gz", hash = "sha256:eda2d8a4116d4f2429db8550f2457da57279247dd930bb12f821b58391359493", size = 286853 } +sdist = { url = "https://files.pythonhosted.org/packages/ee/11/de70dee31455c546fbc88301971ec03c328f3d1138cfba14263f651e9551/fsspec-2024.12.0.tar.gz", hash = "sha256:670700c977ed2fb51e0d9f9253177ed20cbde4a3e5c0283cc5385b5870c8533f", size = 291600 } wheels = [ - { url = "https://files.pythonhosted.org/packages/c6/b2/454d6e7f0158951d8a78c2e1eb4f69ae81beb8dca5fee9809c6c99e9d0d0/fsspec-2024.10.0-py3-none-any.whl", hash = "sha256:03b9a6785766a4de40368b88906366755e2819e758b83705c88cd7cb5fe81871", size = 179641 }, + { url = "https://files.pythonhosted.org/packages/de/86/5486b0188d08aa643e127774a99bac51ffa6cf343e3deb0583956dca5b22/fsspec-2024.12.0-py3-none-any.whl", hash = "sha256:b520aed47ad9804237ff878b504267a3b0b441e97508bd6d2d8774e3db85cee2", size = 183862 }, ] [package.optional-dependencies] @@ -1828,6 +1831,7 @@ data = [ { name = "pyarrow" }, { name = "pyyaml" }, { name = "requests" }, + { name = "s3fs" }, ] dev = [ { name = "pandas-stubs" }, @@ -1865,6 +1869,7 @@ requires-dist = [ { name = "requests", specifier = ">=2.32.3" }, { name = "requests", marker = "extra == 'data'", specifier = "==2.32.3" }, { name = "requests", marker = "extra == 'site'", specifier = "==2.32.3" }, + { name = "s3fs", marker = "extra == 'data'", specifier = "==2024.12.0" }, { name = "setuptools", marker = "extra == 'dev'", specifier = ">=61.0" }, { name = "types-pyyaml", marker = "extra == 'dev'", specifier = ">=6.0.12.20240917" }, { name = "types-requests", marker = "extra == 'dev'", specifier = ">=2.32.0.20241016" }, @@ -2685,6 +2690,7 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7f/b7/20c6f3c0b656fe609675d69bc135c03aac9e3865912444be6339207b6648/ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f66efbc1caa63c088dead1c4170d148eabc9b80d95fb75b6c92ac0aad2437d76", size = 686712 }, { url = "https://files.pythonhosted.org/packages/cd/11/d12dbf683471f888d354dac59593873c2b45feb193c5e3e0f2ebf85e68b9/ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:22353049ba4181685023b25b5b51a574bce33e7f51c759371a7422dcae5402a6", size = 663936 }, { url = "https://files.pythonhosted.org/packages/72/14/4c268f5077db5c83f743ee1daeb236269fa8577133a5cfa49f8b382baf13/ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:932205970b9f9991b34f55136be327501903f7c66830e9760a8ffb15b07f05cd", size = 696580 }, + { url = "https://files.pythonhosted.org/packages/30/fc/8cd12f189c6405a4c1cf37bd633aa740a9538c8e40497c231072d0fef5cf/ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a52d48f4e7bf9005e8f0a89209bf9a73f7190ddf0489eee5eb51377385f59f2a", size = 663393 }, { url = "https://files.pythonhosted.org/packages/80/29/c0a017b704aaf3cbf704989785cd9c5d5b8ccec2dae6ac0c53833c84e677/ruamel.yaml.clib-0.2.12-cp310-cp310-win32.whl", hash = "sha256:3eac5a91891ceb88138c113f9db04f3cebdae277f5d44eaa3651a4f573e6a5da", size = 100326 }, { url = "https://files.pythonhosted.org/packages/3a/65/fa39d74db4e2d0cd252355732d966a460a41cd01c6353b820a0952432839/ruamel.yaml.clib-0.2.12-cp310-cp310-win_amd64.whl", hash = "sha256:ab007f2f5a87bd08ab1499bdf96f3d5c6ad4dcfa364884cb4549aa0154b13a28", size = 118079 }, { url = "https://files.pythonhosted.org/packages/fb/8f/683c6ad562f558cbc4f7c029abcd9599148c51c54b5ef0f24f2638da9fbb/ruamel.yaml.clib-0.2.12-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:4a6679521a58256a90b0d89e03992c15144c5f3858f40d7c18886023d7943db6", size = 132224 }, @@ -2693,6 +2699,7 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/86/29/88c2567bc893c84d88b4c48027367c3562ae69121d568e8a3f3a8d363f4d/ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:811ea1594b8a0fb466172c384267a4e5e367298af6b228931f273b111f17ef52", size = 703012 }, { url = "https://files.pythonhosted.org/packages/11/46/879763c619b5470820f0cd6ca97d134771e502776bc2b844d2adb6e37753/ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cf12567a7b565cbf65d438dec6cfbe2917d3c1bdddfce84a9930b7d35ea59642", size = 704352 }, { url = "https://files.pythonhosted.org/packages/02/80/ece7e6034256a4186bbe50dee28cd032d816974941a6abf6a9d65e4228a7/ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7dd5adc8b930b12c8fc5b99e2d535a09889941aa0d0bd06f4749e9a9397c71d2", size = 737344 }, + { url = "https://files.pythonhosted.org/packages/f0/ca/e4106ac7e80efbabdf4bf91d3d32fc424e41418458251712f5672eada9ce/ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1492a6051dab8d912fc2adeef0e8c72216b24d57bd896ea607cb90bb0c4981d3", size = 714498 }, { url = "https://files.pythonhosted.org/packages/67/58/b1f60a1d591b771298ffa0428237afb092c7f29ae23bad93420b1eb10703/ruamel.yaml.clib-0.2.12-cp311-cp311-win32.whl", hash = "sha256:bd0a08f0bab19093c54e18a14a10b4322e1eacc5217056f3c063bd2f59853ce4", size = 100205 }, { url = "https://files.pythonhosted.org/packages/b4/4f/b52f634c9548a9291a70dfce26ca7ebce388235c93588a1068028ea23fcc/ruamel.yaml.clib-0.2.12-cp311-cp311-win_amd64.whl", hash = "sha256:a274fb2cb086c7a3dea4322ec27f4cb5cc4b6298adb583ab0e211a4682f241eb", size = 118185 }, { url = "https://files.pythonhosted.org/packages/48/41/e7a405afbdc26af961678474a55373e1b323605a4f5e2ddd4a80ea80f628/ruamel.yaml.clib-0.2.12-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:20b0f8dc160ba83b6dcc0e256846e1a02d044e13f7ea74a3d1d56ede4e48c632", size = 133433 }, @@ -2701,6 +2708,7 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/52/a9/d39f3c5ada0a3bb2870d7db41901125dbe2434fa4f12ca8c5b83a42d7c53/ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:749c16fcc4a2b09f28843cda5a193e0283e47454b63ec4b81eaa2242f50e4ccd", size = 706497 }, { url = "https://files.pythonhosted.org/packages/b0/fa/097e38135dadd9ac25aecf2a54be17ddf6e4c23e43d538492a90ab3d71c6/ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bf165fef1f223beae7333275156ab2022cffe255dcc51c27f066b4370da81e31", size = 698042 }, { url = "https://files.pythonhosted.org/packages/ec/d5/a659ca6f503b9379b930f13bc6b130c9f176469b73b9834296822a83a132/ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:32621c177bbf782ca5a18ba4d7af0f1082a3f6e517ac2a18b3974d4edf349680", size = 745831 }, + { url = "https://files.pythonhosted.org/packages/db/5d/36619b61ffa2429eeaefaab4f3374666adf36ad8ac6330d855848d7d36fd/ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b82a7c94a498853aa0b272fd5bc67f29008da798d4f93a2f9f289feb8426a58d", size = 715692 }, { url = "https://files.pythonhosted.org/packages/b1/82/85cb92f15a4231c89b95dfe08b09eb6adca929ef7df7e17ab59902b6f589/ruamel.yaml.clib-0.2.12-cp312-cp312-win32.whl", hash = "sha256:e8c4ebfcfd57177b572e2040777b8abc537cdef58a2120e830124946aa9b42c5", size = 98777 }, { url = "https://files.pythonhosted.org/packages/d7/8f/c3654f6f1ddb75daf3922c3d8fc6005b1ab56671ad56ffb874d908bfa668/ruamel.yaml.clib-0.2.12-cp312-cp312-win_amd64.whl", hash = "sha256:0467c5965282c62203273b838ae77c0d29d7638c8a4e3a1c8bdd3602c10904e4", size = 115523 }, { url = "https://files.pythonhosted.org/packages/29/00/4864119668d71a5fa45678f380b5923ff410701565821925c69780356ffa/ruamel.yaml.clib-0.2.12-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:4c8c5d82f50bb53986a5e02d1b3092b03622c02c2eb78e29bec33fd9593bae1a", size = 132011 }, @@ -2709,22 +2717,23 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e2/a9/28f60726d29dfc01b8decdb385de4ced2ced9faeb37a847bd5cf26836815/ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96777d473c05ee3e5e3c3e999f5d23c6f4ec5b0c38c098b3a5229085f74236c6", size = 701785 }, { url = "https://files.pythonhosted.org/packages/84/7e/8e7ec45920daa7f76046578e4f677a3215fe8f18ee30a9cb7627a19d9b4c/ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:3bc2a80e6420ca8b7d3590791e2dfc709c88ab9152c00eeb511c9875ce5778bf", size = 693017 }, { url = "https://files.pythonhosted.org/packages/c5/b3/d650eaade4ca225f02a648321e1ab835b9d361c60d51150bac49063b83fa/ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:e188d2699864c11c36cdfdada94d781fd5d6b0071cd9c427bceb08ad3d7c70e1", size = 741270 }, + { url = "https://files.pythonhosted.org/packages/87/b8/01c29b924dcbbed75cc45b30c30d565d763b9c4d540545a0eeecffb8f09c/ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4f6f3eac23941b32afccc23081e1f50612bdbe4e982012ef4f5797986828cd01", size = 709059 }, { url = "https://files.pythonhosted.org/packages/30/8c/ed73f047a73638257aa9377ad356bea4d96125b305c34a28766f4445cc0f/ruamel.yaml.clib-0.2.12-cp313-cp313-win32.whl", hash = "sha256:6442cb36270b3afb1b4951f060eccca1ce49f3d087ca1ca4563a6eb479cb3de6", size = 98583 }, { url = "https://files.pythonhosted.org/packages/b0/85/e8e751d8791564dd333d5d9a4eab0a7a115f7e349595417fd50ecae3395c/ruamel.yaml.clib-0.2.12-cp313-cp313-win_amd64.whl", hash = "sha256:e5b8daf27af0b90da7bb903a876477a9e6d7270be6146906b276605997c7e9a3", size = 115190 }, ] [[package]] name = "s3fs" -version = "2024.10.0" +version = "2024.12.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiobotocore" }, { name = "aiohttp" }, { name = "fsspec" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/75/65/4b4c868cff76c036d11dc75dd91e5696dbf16ce626514166f35d5f4a930f/s3fs-2024.10.0.tar.gz", hash = "sha256:58b8c3650f8b99dbedf361543da3533aac8707035a104db5d80b094617ad4a3f", size = 75916 } +sdist = { url = "https://files.pythonhosted.org/packages/96/88/e2fc4fc2a618126ac3cea9b16a4abc5a37dff2522067c9730b5d72d67ac3/s3fs-2024.12.0.tar.gz", hash = "sha256:1b0f3a8f5946cca5ba29871d6792ab1e4528ed762327d8aefafc81b73b99fd56", size = 76578 } wheels = [ - { url = "https://files.pythonhosted.org/packages/99/44/bb9ff095ae7b1b6908480f683b6ca6b71c2105d343a5e5cb25334b01f5fa/s3fs-2024.10.0-py3-none-any.whl", hash = "sha256:7a2025d60d5b1a6025726b3a5e292a8e5aa713abc3b16fd1f81735181f7bb282", size = 29855 }, + { url = "https://files.pythonhosted.org/packages/f7/af/eaec1466887348d7f6cc9d3a668b30b62a4629fb187d0268146118ba3d5e/s3fs-2024.12.0-py3-none-any.whl", hash = "sha256:d8665549f9d1de083151582437a2f10d5f3b3227c1f8e67a2b0b730db813e005", size = 30196 }, ] [[package]] @@ -3035,7 +3044,7 @@ name = "tqdm" version = "4.66.6" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "platform_system == 'Windows'" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/e9/34/bef135b27fe1864993a5284ad001157ee9b5538e859ac90f5b0e8cc8c9ec/tqdm-4.66.6.tar.gz", hash = "sha256:4bdd694238bef1485ce839d67967ab50af8f9272aab687c0d7702a01da0be090", size = 169533 } wheels = [