Mohammed Altaf commited on
Commit
b3fce19
·
1 Parent(s): 8ab6a5f

added configurations for black and formatted code

Browse files
Files changed (7) hide show
  1. baseline.py +12 -9
  2. client.py +2 -3
  3. pyproject.toml +6 -0
  4. server/app.py +1 -2
  5. server/data_analysis_env.py +14 -10
  6. tasks/__init__.py +1 -1
  7. uv.lock +82 -0
baseline.py CHANGED
@@ -16,7 +16,6 @@ import sys
16
  import requests
17
  from openai import OpenAI
18
 
19
-
20
  SYSTEM_PROMPT = """You are a data analyst. You are given a dataset loaded as a pandas DataFrame called `df`.
21
  You can execute Python/pandas code to explore the dataset and answer the question.
22
 
@@ -87,10 +86,12 @@ def run_task(client: OpenAI, base_url: str, task_id: int, max_steps: int = 15) -
87
  action = json.loads(assistant_msg)
88
  except json.JSONDecodeError:
89
  messages.append({"role": "assistant", "content": assistant_msg})
90
- messages.append({
91
- "role": "user",
92
- "content": "Invalid JSON. Please respond with valid JSON only.",
93
- })
 
 
94
  continue
95
 
96
  action_type = action.get("action", "")
@@ -135,10 +136,12 @@ def run_task(client: OpenAI, base_url: str, task_id: int, max_steps: int = 15) -
135
  return score
136
  else:
137
  messages.append({"role": "assistant", "content": assistant_msg})
138
- messages.append({
139
- "role": "user",
140
- "content": f"Unknown action '{action_type}'. Use 'execute_code' or 'submit_answer'.",
141
- })
 
 
142
 
143
  print(" Max steps reached without submitting an answer.")
144
  return 0.0
 
16
  import requests
17
  from openai import OpenAI
18
 
 
19
  SYSTEM_PROMPT = """You are a data analyst. You are given a dataset loaded as a pandas DataFrame called `df`.
20
  You can execute Python/pandas code to explore the dataset and answer the question.
21
 
 
86
  action = json.loads(assistant_msg)
87
  except json.JSONDecodeError:
88
  messages.append({"role": "assistant", "content": assistant_msg})
89
+ messages.append(
90
+ {
91
+ "role": "user",
92
+ "content": "Invalid JSON. Please respond with valid JSON only.",
93
+ }
94
+ )
95
  continue
96
 
97
  action_type = action.get("action", "")
 
136
  return score
137
  else:
138
  messages.append({"role": "assistant", "content": assistant_msg})
139
+ messages.append(
140
+ {
141
+ "role": "user",
142
+ "content": f"Unknown action '{action_type}'. Use 'execute_code' or 'submit_answer'.",
143
+ }
144
+ )
145
 
146
  print(" Max steps reached without submitting an answer.")
147
  return 0.0
client.py CHANGED
@@ -4,10 +4,9 @@ Provides a typed async/sync client for interacting with the
4
  data analysis environment server over HTTP/WebSocket.
5
  """
6
 
7
- from openenv.core.env_client import EnvClient
8
- from openenv.core.client_types import StepResult
9
-
10
  from models import DataAction, DataObservation, DataState
 
 
11
 
12
 
13
  class DataAnalysisClient(EnvClient[DataAction, DataObservation, DataState]):
 
4
  data analysis environment server over HTTP/WebSocket.
5
  """
6
 
 
 
 
7
  from models import DataAction, DataObservation, DataState
8
+ from openenv.core.client_types import StepResult
9
+ from openenv.core.env_client import EnvClient
10
 
11
 
12
  class DataAnalysisClient(EnvClient[DataAction, DataObservation, DataState]):
pyproject.toml CHANGED
@@ -12,7 +12,13 @@ dependencies = [
12
  "pandas>=2.0.0",
13
  "numpy>=1.24.0",
14
  "openai>=1.0.0",
 
 
15
  ]
16
 
17
  [project.scripts]
18
  server = "server.app:main"
 
 
 
 
 
12
  "pandas>=2.0.0",
13
  "numpy>=1.24.0",
14
  "openai>=1.0.0",
15
+ "black>=26.3.1",
16
+ "isort>=8.0.1",
17
  ]
18
 
19
  [project.scripts]
20
  server = "server.app:main"
21
+
22
+ [tool.black]
23
+ line-length = 120
24
+ target-version = ["py313"]
server/app.py CHANGED
@@ -4,9 +4,8 @@ Creates the OpenEnv-compliant HTTP/WebSocket server that wraps
4
  the DataAnalysisEnv environment.
5
  """
6
 
7
- from openenv.core.env_server import create_app
8
-
9
  from models import DataAction, DataObservation
 
10
  from server.data_analysis_env import DataAnalysisEnv
11
 
12
  app = create_app(DataAnalysisEnv, DataAction, DataObservation, env_name="data_analysis_env")
 
4
  the DataAnalysisEnv environment.
5
  """
6
 
 
 
7
  from models import DataAction, DataObservation
8
+ from openenv.core.env_server import create_app
9
  from server.data_analysis_env import DataAnalysisEnv
10
 
11
  app = create_app(DataAnalysisEnv, DataAction, DataObservation, env_name="data_analysis_env")
server/data_analysis_env.py CHANGED
@@ -14,9 +14,8 @@ from typing import Any, Optional
14
  import numpy as np
15
  import pandas as pd
16
 
17
- from openenv.core.env_server import Environment
18
-
19
  from models import DataAction, DataObservation, DataState
 
20
  from tasks import TASKS
21
 
22
  DATASET_PATH = Path(__file__).resolve().parent.parent / "datasets" / "sales.csv"
@@ -53,14 +52,19 @@ class DataAnalysisEnv(Environment):
53
  Returns:
54
  A dictionary to use as the globals for exec().
55
  """
56
- safe_builtins = {
57
- k: v for k, v in __builtins__.items()
58
- if k not in ("open", "exec", "eval", "__import__", "compile", "exit", "quit")
59
- } if isinstance(__builtins__, dict) else {
60
- k: getattr(__builtins__, k) for k in dir(__builtins__)
61
- if k not in ("open", "exec", "eval", "__import__", "compile", "exit", "quit")
62
- and not k.startswith("_")
63
- }
 
 
 
 
 
64
  return {
65
  "__builtins__": safe_builtins,
66
  "df": self._df.copy(),
 
14
  import numpy as np
15
  import pandas as pd
16
 
 
 
17
  from models import DataAction, DataObservation, DataState
18
+ from openenv.core.env_server import Environment
19
  from tasks import TASKS
20
 
21
  DATASET_PATH = Path(__file__).resolve().parent.parent / "datasets" / "sales.csv"
 
52
  Returns:
53
  A dictionary to use as the globals for exec().
54
  """
55
+ safe_builtins = (
56
+ {
57
+ k: v
58
+ for k, v in __builtins__.items()
59
+ if k not in ("open", "exec", "eval", "__import__", "compile", "exit", "quit")
60
+ }
61
+ if isinstance(__builtins__, dict)
62
+ else {
63
+ k: getattr(__builtins__, k)
64
+ for k in dir(__builtins__)
65
+ if k not in ("open", "exec", "eval", "__import__", "compile", "exit", "quit") and not k.startswith("_")
66
+ }
67
+ )
68
  return {
69
  "__builtins__": safe_builtins,
70
  "df": self._df.copy(),
tasks/__init__.py CHANGED
@@ -2,8 +2,8 @@
2
 
3
  from tasks.base_task import BaseTask
4
  from tasks.task_easy import TopRevenueCategoryTask
5
- from tasks.task_medium import CityRevenueShareTask
6
  from tasks.task_hard import RepeatCustomerCohortTask
 
7
 
8
  TASKS = {
9
  1: TopRevenueCategoryTask,
 
2
 
3
  from tasks.base_task import BaseTask
4
  from tasks.task_easy import TopRevenueCategoryTask
 
5
  from tasks.task_hard import RepeatCustomerCohortTask
6
+ from tasks.task_medium import CityRevenueShareTask
7
 
8
  TASKS = {
9
  1: TopRevenueCategoryTask,
uv.lock CHANGED
@@ -147,6 +147,33 @@ wheels = [
147
  { url = "https://files.pythonhosted.org/packages/71/cc/18245721fa7747065ab478316c7fea7c74777d07f37ae60db2e84f8172e8/beartype-0.22.9-py3-none-any.whl", hash = "sha256:d16c9bbc61ea14637596c5f6fbff2ee99cbe3573e46a716401734ef50c3060c2", size = 1333658, upload-time = "2025-12-13T06:50:28.266Z" },
148
  ]
149
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
  [[package]]
151
  name = "brotli"
152
  version = "1.2.0"
@@ -732,6 +759,15 @@ wheels = [
732
  { url = "https://files.pythonhosted.org/packages/fa/5e/f8e9a1d23b9c20a551a8a02ea3637b4642e22c2626e3a13a9a29cdea99eb/importlib_metadata-8.7.1-py3-none-any.whl", hash = "sha256:5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151", size = 27865, upload-time = "2025-12-21T10:00:18.329Z" },
733
  ]
734
 
 
 
 
 
 
 
 
 
 
735
  [[package]]
736
  name = "jaraco-classes"
737
  version = "3.4.0"
@@ -1011,6 +1047,15 @@ wheels = [
1011
  { url = "https://files.pythonhosted.org/packages/a4/8e/469e5a4a2f5855992e425f3cb33804cc07bf18d48f2db061aec61ce50270/more_itertools-10.8.0-py3-none-any.whl", hash = "sha256:52d4362373dcf7c52546bc4af9a86ee7c4579df9a8dc268be0a2f949d376cc9b", size = 69667, upload-time = "2025-09-02T15:23:09.635Z" },
1012
  ]
1013
 
 
 
 
 
 
 
 
 
 
1014
  [[package]]
1015
  name = "numpy"
1016
  version = "2.4.3"
@@ -1123,7 +1168,9 @@ name = "openenv-data-analysis-env"
1123
  version = "0.1.0"
1124
  source = { virtual = "." }
1125
  dependencies = [
 
1126
  { name = "fastapi" },
 
1127
  { name = "numpy" },
1128
  { name = "openai" },
1129
  { name = "openenv-core" },
@@ -1134,7 +1181,9 @@ dependencies = [
1134
 
1135
  [package.metadata]
1136
  requires-dist = [
 
1137
  { name = "fastapi", specifier = ">=0.115.0" },
 
1138
  { name = "numpy", specifier = ">=1.24.0" },
1139
  { name = "openai", specifier = ">=1.0.0" },
1140
  { name = "openenv-core", specifier = ">=0.2.3" },
@@ -1256,6 +1305,15 @@ wheels = [
1256
  { url = "https://files.pythonhosted.org/packages/52/96/5a770e5c461462575474468e5af931cff9de036e7c2b4fea23c1c58d2cbe/pathable-0.5.0-py3-none-any.whl", hash = "sha256:646e3d09491a6351a0c82632a09c02cdf70a252e73196b36d8a15ba0a114f0a6", size = 16867, upload-time = "2026-02-20T08:46:59.536Z" },
1257
  ]
1258
 
 
 
 
 
 
 
 
 
 
1259
  [[package]]
1260
  name = "pillow"
1261
  version = "12.1.1"
@@ -1515,6 +1573,30 @@ wheels = [
1515
  { url = "https://files.pythonhosted.org/packages/1b/d0/397f9626e711ff749a95d96b7af99b9c566a9bb5129b8e4c10fc4d100304/python_multipart-0.0.22-py3-none-any.whl", hash = "sha256:2b2cd894c83d21bf49d702499531c7bafd057d730c201782048f7945d82de155", size = 24579, upload-time = "2026-01-25T10:15:54.811Z" },
1516
  ]
1517
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1518
  [[package]]
1519
  name = "pytz"
1520
  version = "2026.1.post1"
 
147
  { url = "https://files.pythonhosted.org/packages/71/cc/18245721fa7747065ab478316c7fea7c74777d07f37ae60db2e84f8172e8/beartype-0.22.9-py3-none-any.whl", hash = "sha256:d16c9bbc61ea14637596c5f6fbff2ee99cbe3573e46a716401734ef50c3060c2", size = 1333658, upload-time = "2025-12-13T06:50:28.266Z" },
148
  ]
149
 
150
+ [[package]]
151
+ name = "black"
152
+ version = "26.3.1"
153
+ source = { registry = "https://pypi.org/simple" }
154
+ dependencies = [
155
+ { name = "click" },
156
+ { name = "mypy-extensions" },
157
+ { name = "packaging" },
158
+ { name = "pathspec" },
159
+ { name = "platformdirs" },
160
+ { name = "pytokens" },
161
+ ]
162
+ sdist = { url = "https://files.pythonhosted.org/packages/e1/c5/61175d618685d42b005847464b8fb4743a67b1b8fdb75e50e5a96c31a27a/black-26.3.1.tar.gz", hash = "sha256:2c50f5063a9641c7eed7795014ba37b0f5fa227f3d408b968936e24bc0566b07", size = 666155, upload-time = "2026-03-12T03:36:03.593Z" }
163
+ wheels = [
164
+ { url = "https://files.pythonhosted.org/packages/f5/77/5728052a3c0450c53d9bb3945c4c46b91baa62b2cafab6801411b6271e45/black-26.3.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:855822d90f884905362f602880ed8b5df1b7e3ee7d0db2502d4388a954cc8c54", size = 1895034, upload-time = "2026-03-12T03:40:21.813Z" },
165
+ { url = "https://files.pythonhosted.org/packages/52/73/7cae55fdfdfbe9d19e9a8d25d145018965fe2079fa908101c3733b0c55a0/black-26.3.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8a33d657f3276328ce00e4d37fe70361e1ec7614da5d7b6e78de5426cb56332f", size = 1718503, upload-time = "2026-03-12T03:40:23.666Z" },
166
+ { url = "https://files.pythonhosted.org/packages/e1/87/af89ad449e8254fdbc74654e6467e3c9381b61472cc532ee350d28cfdafb/black-26.3.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f1cd08e99d2f9317292a311dfe578fd2a24b15dbce97792f9c4d752275c1fa56", size = 1793557, upload-time = "2026-03-12T03:40:25.497Z" },
167
+ { url = "https://files.pythonhosted.org/packages/43/10/d6c06a791d8124b843bf325ab4ac7d2f5b98731dff84d6064eafd687ded1/black-26.3.1-cp313-cp313-win_amd64.whl", hash = "sha256:c7e72339f841b5a237ff14f7d3880ddd0fc7f98a1199e8c4327f9a4f478c1839", size = 1422766, upload-time = "2026-03-12T03:40:27.14Z" },
168
+ { url = "https://files.pythonhosted.org/packages/59/4f/40a582c015f2d841ac24fed6390bd68f0fc896069ff3a886317959c9daf8/black-26.3.1-cp313-cp313-win_arm64.whl", hash = "sha256:afc622538b430aa4c8c853f7f63bc582b3b8030fd8c80b70fb5fa5b834e575c2", size = 1232140, upload-time = "2026-03-12T03:40:28.882Z" },
169
+ { url = "https://files.pythonhosted.org/packages/d5/da/e36e27c9cebc1311b7579210df6f1c86e50f2d7143ae4fcf8a5017dc8809/black-26.3.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:2d6bfaf7fd0993b420bed691f20f9492d53ce9a2bcccea4b797d34e947318a78", size = 1889234, upload-time = "2026-03-12T03:40:30.964Z" },
170
+ { url = "https://files.pythonhosted.org/packages/0e/7b/9871acf393f64a5fa33668c19350ca87177b181f44bb3d0c33b2d534f22c/black-26.3.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:f89f2ab047c76a9c03f78d0d66ca519e389519902fa27e7a91117ef7611c0568", size = 1720522, upload-time = "2026-03-12T03:40:32.346Z" },
171
+ { url = "https://files.pythonhosted.org/packages/03/87/e766c7f2e90c07fb7586cc787c9ae6462b1eedab390191f2b7fc7f6170a9/black-26.3.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b07fc0dab849d24a80a29cfab8d8a19187d1c4685d8a5e6385a5ce323c1f015f", size = 1787824, upload-time = "2026-03-12T03:40:33.636Z" },
172
+ { url = "https://files.pythonhosted.org/packages/ac/94/2424338fb2d1875e9e83eed4c8e9c67f6905ec25afd826a911aea2b02535/black-26.3.1-cp314-cp314-win_amd64.whl", hash = "sha256:0126ae5b7c09957da2bdbd91a9ba1207453feada9e9fe51992848658c6c8e01c", size = 1445855, upload-time = "2026-03-12T03:40:35.442Z" },
173
+ { url = "https://files.pythonhosted.org/packages/86/43/0c3338bd928afb8ee7471f1a4eec3bdbe2245ccb4a646092a222e8669840/black-26.3.1-cp314-cp314-win_arm64.whl", hash = "sha256:92c0ec1f2cc149551a2b7b47efc32c866406b6891b0ee4625e95967c8f4acfb1", size = 1258109, upload-time = "2026-03-12T03:40:36.832Z" },
174
+ { url = "https://files.pythonhosted.org/packages/8e/0d/52d98722666d6fc6c3dd4c76df339501d6efd40e0ff95e6186a7b7f0befd/black-26.3.1-py3-none-any.whl", hash = "sha256:2bd5aa94fc267d38bb21a70d7410a89f1a1d318841855f698746f8e7f51acd1b", size = 207542, upload-time = "2026-03-12T03:36:01.668Z" },
175
+ ]
176
+
177
  [[package]]
178
  name = "brotli"
179
  version = "1.2.0"
 
759
  { url = "https://files.pythonhosted.org/packages/fa/5e/f8e9a1d23b9c20a551a8a02ea3637b4642e22c2626e3a13a9a29cdea99eb/importlib_metadata-8.7.1-py3-none-any.whl", hash = "sha256:5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151", size = 27865, upload-time = "2025-12-21T10:00:18.329Z" },
760
  ]
761
 
762
+ [[package]]
763
+ name = "isort"
764
+ version = "8.0.1"
765
+ source = { registry = "https://pypi.org/simple" }
766
+ sdist = { url = "https://files.pythonhosted.org/packages/ef/7c/ec4ab396d31b3b395e2e999c8f46dec78c5e29209fac49d1f4dace04041d/isort-8.0.1.tar.gz", hash = "sha256:171ac4ff559cdc060bcfff550bc8404a486fee0caab245679c2abe7cb253c78d", size = 769592, upload-time = "2026-02-28T10:08:20.685Z" }
767
+ wheels = [
768
+ { url = "https://files.pythonhosted.org/packages/3e/95/c7c34aa53c16353c56d0b802fba48d5f5caa2cdee7958acbcb795c830416/isort-8.0.1-py3-none-any.whl", hash = "sha256:28b89bc70f751b559aeca209e6120393d43fbe2490de0559662be7a9787e3d75", size = 89733, upload-time = "2026-02-28T10:08:19.466Z" },
769
+ ]
770
+
771
  [[package]]
772
  name = "jaraco-classes"
773
  version = "3.4.0"
 
1047
  { url = "https://files.pythonhosted.org/packages/a4/8e/469e5a4a2f5855992e425f3cb33804cc07bf18d48f2db061aec61ce50270/more_itertools-10.8.0-py3-none-any.whl", hash = "sha256:52d4362373dcf7c52546bc4af9a86ee7c4579df9a8dc268be0a2f949d376cc9b", size = 69667, upload-time = "2025-09-02T15:23:09.635Z" },
1048
  ]
1049
 
1050
+ [[package]]
1051
+ name = "mypy-extensions"
1052
+ version = "1.1.0"
1053
+ source = { registry = "https://pypi.org/simple" }
1054
+ 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" }
1055
+ wheels = [
1056
+ { 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" },
1057
+ ]
1058
+
1059
  [[package]]
1060
  name = "numpy"
1061
  version = "2.4.3"
 
1168
  version = "0.1.0"
1169
  source = { virtual = "." }
1170
  dependencies = [
1171
+ { name = "black" },
1172
  { name = "fastapi" },
1173
+ { name = "isort" },
1174
  { name = "numpy" },
1175
  { name = "openai" },
1176
  { name = "openenv-core" },
 
1181
 
1182
  [package.metadata]
1183
  requires-dist = [
1184
+ { name = "black", specifier = ">=26.3.1" },
1185
  { name = "fastapi", specifier = ">=0.115.0" },
1186
+ { name = "isort", specifier = ">=8.0.1" },
1187
  { name = "numpy", specifier = ">=1.24.0" },
1188
  { name = "openai", specifier = ">=1.0.0" },
1189
  { name = "openenv-core", specifier = ">=0.2.3" },
 
1305
  { url = "https://files.pythonhosted.org/packages/52/96/5a770e5c461462575474468e5af931cff9de036e7c2b4fea23c1c58d2cbe/pathable-0.5.0-py3-none-any.whl", hash = "sha256:646e3d09491a6351a0c82632a09c02cdf70a252e73196b36d8a15ba0a114f0a6", size = 16867, upload-time = "2026-02-20T08:46:59.536Z" },
1306
  ]
1307
 
1308
+ [[package]]
1309
+ name = "pathspec"
1310
+ version = "1.0.4"
1311
+ source = { registry = "https://pypi.org/simple" }
1312
+ sdist = { url = "https://files.pythonhosted.org/packages/fa/36/e27608899f9b8d4dff0617b2d9ab17ca5608956ca44461ac14ac48b44015/pathspec-1.0.4.tar.gz", hash = "sha256:0210e2ae8a21a9137c0d470578cb0e595af87edaa6ebf12ff176f14a02e0e645", size = 131200, upload-time = "2026-01-27T03:59:46.938Z" }
1313
+ wheels = [
1314
+ { url = "https://files.pythonhosted.org/packages/ef/3c/2c197d226f9ea224a9ab8d197933f9da0ae0aac5b6e0f884e2b8d9c8e9f7/pathspec-1.0.4-py3-none-any.whl", hash = "sha256:fb6ae2fd4e7c921a165808a552060e722767cfa526f99ca5156ed2ce45a5c723", size = 55206, upload-time = "2026-01-27T03:59:45.137Z" },
1315
+ ]
1316
+
1317
  [[package]]
1318
  name = "pillow"
1319
  version = "12.1.1"
 
1573
  { url = "https://files.pythonhosted.org/packages/1b/d0/397f9626e711ff749a95d96b7af99b9c566a9bb5129b8e4c10fc4d100304/python_multipart-0.0.22-py3-none-any.whl", hash = "sha256:2b2cd894c83d21bf49d702499531c7bafd057d730c201782048f7945d82de155", size = 24579, upload-time = "2026-01-25T10:15:54.811Z" },
1574
  ]
1575
 
1576
+ [[package]]
1577
+ name = "pytokens"
1578
+ version = "0.4.1"
1579
+ source = { registry = "https://pypi.org/simple" }
1580
+ sdist = { url = "https://files.pythonhosted.org/packages/b6/34/b4e015b99031667a7b960f888889c5bd34ef585c85e1cb56a594b92836ac/pytokens-0.4.1.tar.gz", hash = "sha256:292052fe80923aae2260c073f822ceba21f3872ced9a68bb7953b348e561179a", size = 23015, upload-time = "2026-01-30T01:03:45.924Z" }
1581
+ wheels = [
1582
+ { url = "https://files.pythonhosted.org/packages/cb/dc/08b1a080372afda3cceb4f3c0a7ba2bde9d6a5241f1edb02a22a019ee147/pytokens-0.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8bdb9d0ce90cbf99c525e75a2fa415144fd570a1ba987380190e8b786bc6ef9b", size = 160720, upload-time = "2026-01-30T01:03:13.843Z" },
1583
+ { url = "https://files.pythonhosted.org/packages/64/0c/41ea22205da480837a700e395507e6a24425151dfb7ead73343d6e2d7ffe/pytokens-0.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5502408cab1cb18e128570f8d598981c68a50d0cbd7c61312a90507cd3a1276f", size = 254204, upload-time = "2026-01-30T01:03:14.886Z" },
1584
+ { url = "https://files.pythonhosted.org/packages/e0/d2/afe5c7f8607018beb99971489dbb846508f1b8f351fcefc225fcf4b2adc0/pytokens-0.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:29d1d8fb1030af4d231789959f21821ab6325e463f0503a61d204343c9b355d1", size = 268423, upload-time = "2026-01-30T01:03:15.936Z" },
1585
+ { url = "https://files.pythonhosted.org/packages/68/d4/00ffdbd370410c04e9591da9220a68dc1693ef7499173eb3e30d06e05ed1/pytokens-0.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:970b08dd6b86058b6dc07efe9e98414f5102974716232d10f32ff39701e841c4", size = 266859, upload-time = "2026-01-30T01:03:17.458Z" },
1586
+ { url = "https://files.pythonhosted.org/packages/a7/c9/c3161313b4ca0c601eeefabd3d3b576edaa9afdefd32da97210700e47652/pytokens-0.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:9bd7d7f544d362576be74f9d5901a22f317efc20046efe2034dced238cbbfe78", size = 103520, upload-time = "2026-01-30T01:03:18.652Z" },
1587
+ { url = "https://files.pythonhosted.org/packages/8f/a7/b470f672e6fc5fee0a01d9e75005a0e617e162381974213a945fcd274843/pytokens-0.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4a14d5f5fc78ce85e426aa159489e2d5961acf0e47575e08f35584009178e321", size = 160821, upload-time = "2026-01-30T01:03:19.684Z" },
1588
+ { url = "https://files.pythonhosted.org/packages/80/98/e83a36fe8d170c911f864bfded690d2542bfcfacb9c649d11a9e6eb9dc41/pytokens-0.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97f50fd18543be72da51dd505e2ed20d2228c74e0464e4262e4899797803d7fa", size = 254263, upload-time = "2026-01-30T01:03:20.834Z" },
1589
+ { url = "https://files.pythonhosted.org/packages/0f/95/70d7041273890f9f97a24234c00b746e8da86df462620194cef1d411ddeb/pytokens-0.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dc74c035f9bfca0255c1af77ddd2d6ae8419012805453e4b0e7513e17904545d", size = 268071, upload-time = "2026-01-30T01:03:21.888Z" },
1590
+ { url = "https://files.pythonhosted.org/packages/da/79/76e6d09ae19c99404656d7db9c35dfd20f2086f3eb6ecb496b5b31163bad/pytokens-0.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f66a6bbe741bd431f6d741e617e0f39ec7257ca1f89089593479347cc4d13324", size = 271716, upload-time = "2026-01-30T01:03:23.633Z" },
1591
+ { url = "https://files.pythonhosted.org/packages/79/37/482e55fa1602e0a7ff012661d8c946bafdc05e480ea5a32f4f7e336d4aa9/pytokens-0.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:b35d7e5ad269804f6697727702da3c517bb8a5228afa450ab0fa787732055fc9", size = 104539, upload-time = "2026-01-30T01:03:24.788Z" },
1592
+ { url = "https://files.pythonhosted.org/packages/30/e8/20e7db907c23f3d63b0be3b8a4fd1927f6da2395f5bcc7f72242bb963dfe/pytokens-0.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:8fcb9ba3709ff77e77f1c7022ff11d13553f3c30299a9fe246a166903e9091eb", size = 168474, upload-time = "2026-01-30T01:03:26.428Z" },
1593
+ { url = "https://files.pythonhosted.org/packages/d6/81/88a95ee9fafdd8f5f3452107748fd04c24930d500b9aba9738f3ade642cc/pytokens-0.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:79fc6b8699564e1f9b521582c35435f1bd32dd06822322ec44afdeba666d8cb3", size = 290473, upload-time = "2026-01-30T01:03:27.415Z" },
1594
+ { url = "https://files.pythonhosted.org/packages/cf/35/3aa899645e29b6375b4aed9f8d21df219e7c958c4c186b465e42ee0a06bf/pytokens-0.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d31b97b3de0f61571a124a00ffe9a81fb9939146c122c11060725bd5aea79975", size = 303485, upload-time = "2026-01-30T01:03:28.558Z" },
1595
+ { url = "https://files.pythonhosted.org/packages/52/a0/07907b6ff512674d9b201859f7d212298c44933633c946703a20c25e9d81/pytokens-0.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:967cf6e3fd4adf7de8fc73cd3043754ae79c36475c1c11d514fc72cf5490094a", size = 306698, upload-time = "2026-01-30T01:03:29.653Z" },
1596
+ { url = "https://files.pythonhosted.org/packages/39/2a/cbbf9250020a4a8dd53ba83a46c097b69e5eb49dd14e708f496f548c6612/pytokens-0.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:584c80c24b078eec1e227079d56dc22ff755e0ba8654d8383b2c549107528918", size = 116287, upload-time = "2026-01-30T01:03:30.912Z" },
1597
+ { url = "https://files.pythonhosted.org/packages/c6/78/397db326746f0a342855b81216ae1f0a32965deccfd7c830a2dbc66d2483/pytokens-0.4.1-py3-none-any.whl", hash = "sha256:26cef14744a8385f35d0e095dc8b3a7583f6c953c2e3d269c7f82484bf5ad2de", size = 13729, upload-time = "2026-01-30T01:03:45.029Z" },
1598
+ ]
1599
+
1600
  [[package]]
1601
  name = "pytz"
1602
  version = "2026.1.post1"