diff --git a/pyproject.toml b/pyproject.toml index 4bf4990..a15f84e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,11 +3,11 @@ name = "Estimates-Program" version = "0.0.0" # Not used, refer to config.yml instead requires-python = ">=3.11" dependencies = [ + "black>=25.12.0,<26.0.0", "cerberus>=1.3.8,<2.0.0", "mssql>=1.0.1,<2.0.0", "numpy>=2.4.0,<3.0.0", "pandas>=2.3.3,<3.0.0", - "polars>=1.36.1,<2.0.0", "pyodbc>=5.3.0,<6.0.0", "pyyaml>=6.0.3,<7.0.0", "sqlalchemy>=2.0.45,<3.0.0", diff --git a/python/ase.py b/python/ase.py index ed56105..411f097 100644 --- a/python/ase.py +++ b/python/ase.py @@ -2,12 +2,12 @@ # wiki page for more details: # https://github.com/SANDAG/Estimates-Program/wiki/Population-by-Age-Sex-Ethnicity +import csv import functools import logging import numpy as np import pandas as pd -import polars as pl import sqlalchemy as sql import python.tests as tests @@ -78,7 +78,7 @@ def run_ase(year: int) -> None: ase_outputs = _create_ase(year, ase_inputs) _validate_ase_outputs(ase_outputs) - _insert_ase(ase_outputs) + _insert_ase(year, ase_outputs) @functools.lru_cache(maxsize=1) @@ -915,15 +915,15 @@ def _validate_ase_outputs(ase_outputs: dict[str, pd.DataFrame]) -> None: ) -def _insert_ase(ase_outputs: dict[str, pd.DataFrame]) -> None: +def _insert_ase(year: int, ase_outputs: dict[str, pd.DataFrame]) -> None: """Insert age/sex/ethnicity population by type to database.""" for pop_type, output in ase_outputs.items(): logger.info("Loading Estimates for " + pop_type) - # Convert the DataFrame to a Polars DataFrame - # Polars used solely for write to CSV performance - pl_df = pl.from_pandas( - output[ + # Write the DataFrame to a CSV file + csv_temp_location = utils.BULK_INSERT_STAGING / (pop_type + ".txt") + ( + output.loc[lambda df: df["value"] != 0][ [ "run_id", "year", @@ -934,29 +934,25 @@ def _insert_ase(ase_outputs: dict[str, pd.DataFrame]) -> None: "ethnicity", "value", ] - ], - include_index=False, - ) - - # Write the DataFrame to a CSV file - pl_df.write_csv( - utils.BULK_INSERT_STAGING / (pop_type + ".txt"), - include_header=False, - separator="|", - quote_style="never", + ].to_csv( + csv_temp_location, + header=False, + index=False, + sep="|", + quoting=csv.QUOTE_NONE, + ) ) # Bulk insert the CSV file into the production database with utils.ESTIMATES_ENGINE.connect() as con: - fp = (utils.BULK_INSERT_STAGING / (pop_type + ".txt")).as_posix() query = sql.text( f""" BULK INSERT [outputs].[ase] - FROM '{fp}' + FROM '{csv_temp_location.as_posix()}' WITH ( TABLOCK, MAXERRORS=0, - FIELDTERMINATOR = '|', + FIELDTERMINATOR = '|', ROWTERMINATOR = '0x0A', CHECK_CONSTRAINTS ) @@ -966,4 +962,4 @@ def _insert_ase(ase_outputs: dict[str, pd.DataFrame]) -> None: con.commit() # Remove the temporary CSV file - (utils.BULK_INSERT_STAGING / (pop_type + ".txt")).unlink() + csv_temp_location.unlink() diff --git a/python/utils.py b/python/utils.py index c2436fe..5f54c4e 100644 --- a/python/utils.py +++ b/python/utils.py @@ -105,6 +105,7 @@ RUN_INSTRUCTIONS = input_parser.run_instructions RUN_ID = input_parser.run_id MGRA_VERSION = input_parser.mgra_version +MGRA_SERIES = int(MGRA_VERSION.replace("mgra", "")) logger.info( f"RUN_ID: {RUN_ID}, MGRA_VERSION: {MGRA_VERSION}, YEARS: {RUN_INSTRUCTIONS["years"]}" diff --git a/sql/ase/insert_ase_zeros.sql b/sql/ase/insert_ase_zeros.sql new file mode 100644 index 0000000..1217262 --- /dev/null +++ b/sql/ase/insert_ase_zeros.sql @@ -0,0 +1,55 @@ +DECLARE @run_id INTEGER = :run_id; +DECLARE @year INTEGER = :year; +DECLARE @series INTEGER = :series; + +DROP TABLE IF EXISTS [#shell]; +SELECT *, 0 AS [value] +INTO [#shell] +FROM (VALUES(@run_id)) AS [run_id]([run_id]) +CROSS JOIN (VALUES(@year)) AS [year]([year]) +CROSS JOIN ( + SELECT DISTINCT [mgra] + FROM [demographic_warehouse].[dim].[mgra] + WHERE [series] = @series +) AS [mgra] +CROSS JOIN ( + SELECT DISTINCT [long_name] AS [pop_type] + FROM [demographic_warehouse].[dim].[housing_type] + WHERE [housing_type_id] IN (1, 2, 3, 4, 6) -- Skip 'Group Quarters - Civilian' +) AS [pop_type] +CROSS JOIN ( + SELECT DISTINCT [name] AS [age_group] + FROM [demographic_warehouse].[dim].[age_group] + WHERE [age_group_id] BETWEEN 1 AND 20 + ) AS [age_group] +CROSS JOIN ( + SELECT DISTINCT [sex] + FROM [demographic_warehouse].[dim].[sex] + WHERE [sex_id] IN (1, 2) + ) AS [sex] +CROSS JOIN ( + SELECT DISTINCT [long_name] AS [ethnicity] + FROM [demographic_warehouse].[dim].[ethnicity] + WHERE [ethnicity_id] IN (1, 2, 3, 4, 5, 6, 8) -- Skip 'Non-Hispanic, Other' + ) AS [ethnicity] + +INSERT INTO [EstimatesProgram].[outputs].[ase] +SELECT + [#shell].[run_id], + [#shell].[year], + [#shell].[mgra], + [#shell].[pop_type], + [#shell].[age_group], + [#shell].[sex], + [#shell].[ethnicity], + [#shell].[value] +FROM [#shell] +LEFT JOIN [EstimatesProgram].[outputs].[ase] + ON [#shell].[run_id] = [ase].[run_id] + AND [#shell].[year] = [ase].[year] + AND [#shell].[mgra] = [ase].[mgra] + AND [#shell].[pop_type] = [ase].[pop_type] + AND [#shell].[age_group] = [ase].[age_group] + AND [#shell].[sex] = [ase].[sex] + AND [#shell].[ethnicity] = [ase].[ethnicity] +WHERE [ase].[value] IS NULL diff --git a/sql/create_objects.sql b/sql/create_objects.sql index dc3e6ca..5ef9b93 100644 --- a/sql/create_objects.sql +++ b/sql/create_objects.sql @@ -131,6 +131,87 @@ CREATE TABLE [outputs].[ase] ( CONSTRAINT [chk_non_negative_outputs_ase] CHECK ([value] >= 0) ) +-- For purposes of data insertion speed, only non-zero ASE data is inserted into +-- [outputs].[ase]. In case you want the full table with zeros, you can use the below +-- function +CREATE FUNCTION [outputs].[ase_with_zeros]( + @run_id INTEGER +) +RETURNS @ase_with_zeros TABLE ( + [run_id] INTEGER NOT NULL, + [year] INTEGER NOT NULL, + [mgra] INTEGER NOT NULL, + [pop_type] NVARCHAR(75) NOT NULL, + [age_group] NVARCHAR(15) NOT NULL, + [sex] NVARCHAR(6) NOT NULL, + [ethnicity] NVARCHAR(50) NOT NULL, + [value] INTEGER NOT NULL + ) +AS +BEGIN + INSERT INTO @ase_with_zeros + DECLARE @run_id INTEGER = 134; + SELECT + [shell].[run_id], + [shell].[year], + [shell].[mgra], + [shell].[pop_type], + [shell].[age_group], + [shell].[sex], + [shell].[ethnicity], + ISNULL([ase].[value], 0) AS [value] + FROM ( + SELECT + [run_id].[run_id], + [year].[year], + [mgra].[mgra], + [pop_type].[pop_type], + [age_group].[age_group], + [sex].[sex], + [ethnicity].[ethnicity] + FROM (VALUES(@run_id)) AS [run_id]([run_id]) + CROSS JOIN ( + SELECT DISTINCT [year] + FROM [outputs].[ase] + WHERE [run_id] = @run_id + ) AS [year] + CROSS JOIN ( + SELECT DISTINCT [mgra] + FROM [inputs].[mgra] + WHERE [run_id] = @run_id + ) AS [mgra] + CROSS JOIN ( + SELECT DISTINCT [pop_type] + FROM [outputs].[ase] + WHERE [run_id] = @run_id + ) AS [pop_type] + CROSS JOIN ( + SELECT DISTINCT [age_group] + FROM [outputs].[ase] + WHERE [run_id] = @run_id + ) AS [age_group] + CROSS JOIN ( + SELECT DISTINCT [sex] + FROM [outputs].[ase] + WHERE [run_id] = @run_id + ) AS [sex] + CROSS JOIN ( + SELECT DISTINCT [ethnicity] + FROM [outputs].[ase] + WHERE [run_id] = @run_id + ) AS [ethnicity] + ) AS [shell] + LEFT JOIN [outputs].[ase] + ON [shell].[run_id] = [ase].[run_id] + AND [shell].[year] = [ase].[year] + AND [shell].[mgra] = [ase].[mgra] + AND [shell].[pop_type] = [ase].[pop_type] + AND [shell].[age_group] = [ase].[age_group] + AND [shell].[sex] = [ase].[sex] + AND [shell].[ethnicity] = [ase].[ethnicity] + RETURN; +END + CREATE TABLE [outputs].[gq] ( [run_id] INT NOT NULL, [year] INT NOT NULL, diff --git a/uv.lock b/uv.lock index f8e1c9a..ae7dcbb 100644 --- a/uv.lock +++ b/uv.lock @@ -6,6 +6,43 @@ resolution-markers = [ "python_full_version < '3.12'", ] +[[package]] +name = "black" +version = "25.12.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "mypy-extensions" }, + { name = "packaging" }, + { name = "pathspec" }, + { name = "platformdirs" }, + { name = "pytokens" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c4/d9/07b458a3f1c525ac392b5edc6b191ff140b596f9d77092429417a54e249d/black-25.12.0.tar.gz", hash = "sha256:8d3dd9cea14bff7ddc0eb243c811cdb1a011ebb4800a5f0335a01a68654796a7", size = 659264, upload-time = "2025-12-08T01:40:52.501Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/60/ad/7ac0d0e1e0612788dbc48e62aef8a8e8feffac7eb3d787db4e43b8462fa8/black-25.12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d0cfa263e85caea2cff57d8f917f9f51adae8e20b610e2b23de35b5b11ce691a", size = 1877003, upload-time = "2025-12-08T01:43:29.967Z" }, + { url = "https://files.pythonhosted.org/packages/e8/dd/a237e9f565f3617a88b49284b59cbca2a4f56ebe68676c1aad0ce36a54a7/black-25.12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1a2f578ae20c19c50a382286ba78bfbeafdf788579b053d8e4980afb079ab9be", size = 1712639, upload-time = "2025-12-08T01:52:46.756Z" }, + { url = "https://files.pythonhosted.org/packages/12/80/e187079df1ea4c12a0c63282ddd8b81d5107db6d642f7d7b75a6bcd6fc21/black-25.12.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d3e1b65634b0e471d07ff86ec338819e2ef860689859ef4501ab7ac290431f9b", size = 1758143, upload-time = "2025-12-08T01:45:29.137Z" }, + { url = "https://files.pythonhosted.org/packages/93/b5/3096ccee4f29dc2c3aac57274326c4d2d929a77e629f695f544e159bfae4/black-25.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:a3fa71e3b8dd9f7c6ac4d818345237dfb4175ed3bf37cd5a581dbc4c034f1ec5", size = 1420698, upload-time = "2025-12-08T01:45:53.379Z" }, + { url = "https://files.pythonhosted.org/packages/7e/39/f81c0ffbc25ffbe61c7d0385bf277e62ffc3e52f5ee668d7369d9854fadf/black-25.12.0-cp311-cp311-win_arm64.whl", hash = "sha256:51e267458f7e650afed8445dc7edb3187143003d52a1b710c7321aef22aa9655", size = 1229317, upload-time = "2025-12-08T01:46:35.606Z" }, + { url = "https://files.pythonhosted.org/packages/d1/bd/26083f805115db17fda9877b3c7321d08c647df39d0df4c4ca8f8450593e/black-25.12.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:31f96b7c98c1ddaeb07dc0f56c652e25bdedaac76d5b68a059d998b57c55594a", size = 1924178, upload-time = "2025-12-08T01:49:51.048Z" }, + { url = "https://files.pythonhosted.org/packages/89/6b/ea00d6651561e2bdd9231c4177f4f2ae19cc13a0b0574f47602a7519b6ca/black-25.12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:05dd459a19e218078a1f98178c13f861fe6a9a5f88fc969ca4d9b49eb1809783", size = 1742643, upload-time = "2025-12-08T01:49:59.09Z" }, + { url = "https://files.pythonhosted.org/packages/6d/f3/360fa4182e36e9875fabcf3a9717db9d27a8d11870f21cff97725c54f35b/black-25.12.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c1f68c5eff61f226934be6b5b80296cf6939e5d2f0c2f7d543ea08b204bfaf59", size = 1800158, upload-time = "2025-12-08T01:44:27.301Z" }, + { url = "https://files.pythonhosted.org/packages/f8/08/2c64830cb6616278067e040acca21d4f79727b23077633953081c9445d61/black-25.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:274f940c147ddab4442d316b27f9e332ca586d39c85ecf59ebdea82cc9ee8892", size = 1426197, upload-time = "2025-12-08T01:45:51.198Z" }, + { url = "https://files.pythonhosted.org/packages/d4/60/a93f55fd9b9816b7432cf6842f0e3000fdd5b7869492a04b9011a133ee37/black-25.12.0-cp312-cp312-win_arm64.whl", hash = "sha256:169506ba91ef21e2e0591563deda7f00030cb466e747c4b09cb0a9dae5db2f43", size = 1237266, upload-time = "2025-12-08T01:45:10.556Z" }, + { url = "https://files.pythonhosted.org/packages/c8/52/c551e36bc95495d2aa1a37d50566267aa47608c81a53f91daa809e03293f/black-25.12.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a05ddeb656534c3e27a05a29196c962877c83fa5503db89e68857d1161ad08a5", size = 1923809, upload-time = "2025-12-08T01:46:55.126Z" }, + { url = "https://files.pythonhosted.org/packages/a0/f7/aac9b014140ee56d247e707af8db0aae2e9efc28d4a8aba92d0abd7ae9d1/black-25.12.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9ec77439ef3e34896995503865a85732c94396edcc739f302c5673a2315e1e7f", size = 1742384, upload-time = "2025-12-08T01:49:37.022Z" }, + { url = "https://files.pythonhosted.org/packages/74/98/38aaa018b2ab06a863974c12b14a6266badc192b20603a81b738c47e902e/black-25.12.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e509c858adf63aa61d908061b52e580c40eae0dfa72415fa47ac01b12e29baf", size = 1798761, upload-time = "2025-12-08T01:46:05.386Z" }, + { url = "https://files.pythonhosted.org/packages/16/3a/a8ac542125f61574a3f015b521ca83b47321ed19bb63fe6d7560f348bfe1/black-25.12.0-cp313-cp313-win_amd64.whl", hash = "sha256:252678f07f5bac4ff0d0e9b261fbb029fa530cfa206d0a636a34ab445ef8ca9d", size = 1429180, upload-time = "2025-12-08T01:45:34.903Z" }, + { url = "https://files.pythonhosted.org/packages/e6/2d/bdc466a3db9145e946762d52cd55b1385509d9f9004fec1c97bdc8debbfb/black-25.12.0-cp313-cp313-win_arm64.whl", hash = "sha256:bc5b1c09fe3c931ddd20ee548511c64ebf964ada7e6f0763d443947fd1c603ce", size = 1239350, upload-time = "2025-12-08T01:46:09.458Z" }, + { url = "https://files.pythonhosted.org/packages/35/46/1d8f2542210c502e2ae1060b2e09e47af6a5e5963cb78e22ec1a11170b28/black-25.12.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:0a0953b134f9335c2434864a643c842c44fba562155c738a2a37a4d61f00cad5", size = 1917015, upload-time = "2025-12-08T01:53:27.987Z" }, + { url = "https://files.pythonhosted.org/packages/41/37/68accadf977672beb8e2c64e080f568c74159c1aaa6414b4cd2aef2d7906/black-25.12.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2355bbb6c3b76062870942d8cc450d4f8ac71f9c93c40122762c8784df49543f", size = 1741830, upload-time = "2025-12-08T01:54:36.861Z" }, + { url = "https://files.pythonhosted.org/packages/ac/76/03608a9d8f0faad47a3af3a3c8c53af3367f6c0dd2d23a84710456c7ac56/black-25.12.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9678bd991cc793e81d19aeeae57966ee02909877cb65838ccffef24c3ebac08f", size = 1791450, upload-time = "2025-12-08T01:44:52.581Z" }, + { url = "https://files.pythonhosted.org/packages/06/99/b2a4bd7dfaea7964974f947e1c76d6886d65fe5d24f687df2d85406b2609/black-25.12.0-cp314-cp314-win_amd64.whl", hash = "sha256:97596189949a8aad13ad12fcbb4ae89330039b96ad6742e6f6b45e75ad5cfd83", size = 1452042, upload-time = "2025-12-08T01:46:13.188Z" }, + { url = "https://files.pythonhosted.org/packages/b2/7c/d9825de75ae5dd7795d007681b752275ea85a1c5d83269b4b9c754c2aaab/black-25.12.0-cp314-cp314-win_arm64.whl", hash = "sha256:778285d9ea197f34704e3791ea9404cd6d07595745907dd2ce3da7a13627b29b", size = 1267446, upload-time = "2025-12-08T01:46:14.497Z" }, + { url = "https://files.pythonhosted.org/packages/68/11/21331aed19145a952ad28fca2756a1433ee9308079bd03bd898e903a2e53/black-25.12.0-py3-none-any.whl", hash = "sha256:48ceb36c16dbc84062740049eef990bb2ce07598272e673c17d1a7720c71c828", size = 206191, upload-time = "2025-12-08T01:40:50.963Z" }, +] + [[package]] name = "cerberus" version = "1.3.8" @@ -15,16 +52,37 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a1/00/ff53f3a4d51e64e9137ce2408a43edf18fec96eebb61f87a6598578fa563/cerberus-1.3.8-py3-none-any.whl", hash = "sha256:46c029e3e2a4735408ed36bec14ef2cbf3e50d8ebe47fb34ee1e54b2da814df2", size = 30567, upload-time = "2025-11-06T18:29:38.815Z" }, ] +[[package]] +name = "click" +version = "8.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3d/fa/656b739db8587d7b5dfa22e22ed02566950fbfbcdc20311993483657a5c0/click-8.3.1.tar.gz", hash = "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a", size = 295065, upload-time = "2025-11-15T20:45:42.706Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl", hash = "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6", size = 108274, upload-time = "2025-11-15T20:45:41.139Z" }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + [[package]] name = "estimates-program" version = "0.0.0" source = { virtual = "." } dependencies = [ + { name = "black" }, { name = "cerberus" }, { name = "mssql" }, { name = "numpy" }, { name = "pandas" }, - { name = "polars" }, { name = "pyodbc" }, { name = "pyyaml" }, { name = "sqlalchemy" }, @@ -32,11 +90,11 @@ dependencies = [ [package.metadata] requires-dist = [ + { name = "black", specifier = ">=25.12.0,<26.0.0" }, { name = "cerberus", specifier = ">=1.3.8,<2.0.0" }, { name = "mssql", specifier = ">=1.0.1,<2.0.0" }, { name = "numpy", specifier = ">=2.4.0,<3.0.0" }, { name = "pandas", specifier = ">=2.3.3,<3.0.0" }, - { name = "polars", specifier = ">=1.36.1,<2.0.0" }, { name = "pyodbc", specifier = ">=5.3.0,<6.0.0" }, { name = "pyyaml", specifier = ">=6.0.3,<7.0.0" }, { name = "sqlalchemy", specifier = ">=2.0.45,<3.0.0" }, @@ -101,6 +159,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2d/dd/9cf874fa8ea704614c1f7a583a3de02b4e43477652fa4ba1328f287b4cdc/mssql-1.0.1-py3-none-any.whl", hash = "sha256:bd9e42b63ef1582bd133825538529f31bfccb6b13e7874b222af92697c1adbde", size = 3703, upload-time = "2020-01-07T02:23:54.471Z" }, ] +[[package]] +name = "mypy-extensions" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/6e/371856a3fb9d31ca8dac321cda606860fa4548858c0cc45d9d1d4ca2628b/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558", size = 6343, upload-time = "2025-04-22T14:54:24.164Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" }, +] + [[package]] name = "numpy" version = "2.4.0" @@ -180,6 +247,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/11/73/edeacba3167b1ca66d51b1a5a14697c2c40098b5ffa01811c67b1785a5ab/numpy-2.4.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:a39fb973a726e63223287adc6dafe444ce75af952d711e400f3bf2b36ef55a7b", size = 12489376, upload-time = "2025-12-20T16:18:16.524Z" }, ] +[[package]] +name = "packaging" +version = "25.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, +] + [[package]] name = "pandas" version = "2.3.3" @@ -235,29 +311,21 @@ wheels = [ ] [[package]] -name = "polars" -version = "1.36.1" +name = "pathspec" +version = "1.0.2" source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "polars-runtime-32" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/9f/dc/56f2a90c79a2cb13f9e956eab6385effe54216ae7a2068b3a6406bae4345/polars-1.36.1.tar.gz", hash = "sha256:12c7616a2305559144711ab73eaa18814f7aa898c522e7645014b68f1432d54c", size = 711993, upload-time = "2025-12-10T01:14:53.033Z" } +sdist = { url = "https://files.pythonhosted.org/packages/41/b9/6eb731b52f132181a9144bbe77ff82117f6b2d2fbfba49aaab2c014c4760/pathspec-1.0.2.tar.gz", hash = "sha256:fa32b1eb775ed9ba8d599b22c5f906dc098113989da2c00bf8b210078ca7fb92", size = 130502, upload-time = "2026-01-08T04:33:27.613Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f6/c6/36a1b874036b49893ecae0ac44a2f63d1a76e6212631a5b2f50a86e0e8af/polars-1.36.1-py3-none-any.whl", hash = "sha256:853c1bbb237add6a5f6d133c15094a9b727d66dd6a4eb91dbb07cdb056b2b8ef", size = 802429, upload-time = "2025-12-10T01:13:53.838Z" }, + { url = "https://files.pythonhosted.org/packages/78/6b/14fc9049d78435fd29e82846c777bd7ed9c470013dc8d0260fff3ff1c11e/pathspec-1.0.2-py3-none-any.whl", hash = "sha256:62f8558917908d237d399b9b338ef455a814801a4688bc41074b25feefd93472", size = 54844, upload-time = "2026-01-08T04:33:26.4Z" }, ] [[package]] -name = "polars-runtime-32" -version = "1.36.1" +name = "platformdirs" +version = "4.5.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/31/df/597c0ef5eb8d761a16d72327846599b57c5d40d7f9e74306fc154aba8c37/polars_runtime_32-1.36.1.tar.gz", hash = "sha256:201c2cfd80ceb5d5cd7b63085b5fd08d6ae6554f922bcb941035e39638528a09", size = 2788751, upload-time = "2025-12-10T01:14:54.172Z" } +sdist = { url = "https://files.pythonhosted.org/packages/cf/86/0248f086a84f01b37aaec0fa567b397df1a119f73c16f6c7a9aac73ea309/platformdirs-4.5.1.tar.gz", hash = "sha256:61d5cdcc6065745cdd94f0f878977f8de9437be93de97c1c12f853c9c0cdcbda", size = 21715, upload-time = "2025-12-05T13:52:58.638Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e1/ea/871129a2d296966c0925b078a9a93c6c5e7facb1c5eebfcd3d5811aeddc1/polars_runtime_32-1.36.1-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:327b621ca82594f277751f7e23d4b939ebd1be18d54b4cdf7a2f8406cecc18b2", size = 43494311, upload-time = "2025-12-10T01:13:56.096Z" }, - { url = "https://files.pythonhosted.org/packages/d8/76/0038210ad1e526ce5bb2933b13760d6b986b3045eccc1338e661bd656f77/polars_runtime_32-1.36.1-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:ab0d1f23084afee2b97de8c37aa3e02ec3569749ae39571bd89e7a8b11ae9e83", size = 39300602, upload-time = "2025-12-10T01:13:59.366Z" }, - { url = "https://files.pythonhosted.org/packages/54/1e/2707bee75a780a953a77a2c59829ee90ef55708f02fc4add761c579bf76e/polars_runtime_32-1.36.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:899b9ad2e47ceb31eb157f27a09dbc2047efbf4969a923a6b1ba7f0412c3e64c", size = 44511780, upload-time = "2025-12-10T01:14:02.285Z" }, - { url = "https://files.pythonhosted.org/packages/11/b2/3fede95feee441be64b4bcb32444679a8fbb7a453a10251583053f6efe52/polars_runtime_32-1.36.1-cp39-abi3-manylinux_2_24_aarch64.whl", hash = "sha256:d9d077bb9df711bc635a86540df48242bb91975b353e53ef261c6fae6cb0948f", size = 40688448, upload-time = "2025-12-10T01:14:05.131Z" }, - { url = "https://files.pythonhosted.org/packages/05/0f/e629713a72999939b7b4bfdbf030a32794db588b04fdf3dc977dd8ea6c53/polars_runtime_32-1.36.1-cp39-abi3-win_amd64.whl", hash = "sha256:cc17101f28c9a169ff8b5b8d4977a3683cd403621841623825525f440b564cf0", size = 44464898, upload-time = "2025-12-10T01:14:08.296Z" }, - { url = "https://files.pythonhosted.org/packages/d1/d8/a12e6aa14f63784cead437083319ec7cece0d5bb9a5bfe7678cc6578b52a/polars_runtime_32-1.36.1-cp39-abi3-win_arm64.whl", hash = "sha256:809e73857be71250141225ddd5d2b30c97e6340aeaa0d445f930e01bef6888dc", size = 39798896, upload-time = "2025-12-10T01:14:11.568Z" }, + { url = "https://files.pythonhosted.org/packages/cb/28/3bfe2fa5a7b9c46fe7e13c97bda14c895fb10fa2ebf1d0abb90e0cea7ee1/platformdirs-4.5.1-py3-none-any.whl", hash = "sha256:d03afa3963c806a9bed9d5125c8f4cb2fdaf74a55ab60e5d59b3fde758104d31", size = 18731, upload-time = "2025-12-05T13:52:56.823Z" }, ] [[package]] @@ -325,6 +393,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, ] +[[package]] +name = "pytokens" +version = "0.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4e/8d/a762be14dae1c3bf280202ba3172020b2b0b4c537f94427435f19c413b72/pytokens-0.3.0.tar.gz", hash = "sha256:2f932b14ed08de5fcf0b391ace2642f858f1394c0857202959000b68ed7a458a", size = 17644, upload-time = "2025-11-05T13:36:35.34Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/84/25/d9db8be44e205a124f6c98bc0324b2bb149b7431c53877fc6d1038dddaf5/pytokens-0.3.0-py3-none-any.whl", hash = "sha256:95b2b5eaf832e469d141a378872480ede3f251a5a5041b8ec6e581d3ac71bbf3", size = 12195, upload-time = "2025-11-05T13:36:33.183Z" }, +] + [[package]] name = "pytz" version = "2025.2"