pycityagent 2.0.0a84__cp311-cp311-macosx_11_0_arm64.whl → 2.0.0a85__cp311-cp311-macosx_11_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,7 +3,7 @@ import logging
3
3
  import re
4
4
  import time
5
5
  from collections.abc import Sequence
6
- from typing import Any, Literal, Union
6
+ from typing import Any, Literal, Union, cast
7
7
 
8
8
  import grpc
9
9
  import pycityproto.city.economy.v2.economy_pb2 as economyv2
@@ -83,17 +83,18 @@ class EconomyClient:
83
83
  - It establishes an asynchronous connection and provides methods to communicate with the service.
84
84
  """
85
85
 
86
- def __init__(self, server_address: str, secure: bool = False):
86
+ def __init__(
87
+ self,
88
+ server_address: str,
89
+ ):
87
90
  """
88
91
  Initialize the EconomyClient.
89
92
 
90
93
  - **Args**:
91
94
  - `server_address` (`str`): The address of the Economy server to connect to.
92
- - `secure` (`bool`, optional): Whether to use a secure connection. Defaults to `False`.
93
95
 
94
96
  - **Attributes**:
95
97
  - `server_address` (`str`): The address of the Economy server.
96
- - `secure` (`bool`): A flag indicating if a secure connection should be used.
97
98
  - `_aio_stub` (`OrgServiceStub`): A gRPC stub used to make remote calls to the Economy service.
98
99
 
99
100
  - **Description**:
@@ -102,6 +103,8 @@ class EconomyClient:
102
103
  - Instantiates a gRPC stub (`_aio_stub`) for interacting with the Economy service.
103
104
  """
104
105
  self.server_address = server_address
106
+
107
+ secure = self.server_address.startswith("https")
105
108
  self.secure = secure
106
109
  aio_channel = _create_aio_channel(server_address, secure)
107
110
  self._aio_stub = org_grpc.OrgServiceStub(aio_channel)
@@ -149,7 +152,9 @@ class EconomyClient:
149
152
  self._agent_ids = agent_ids
150
153
  self._org_ids = org_ids
151
154
 
152
- async def get_agent(self, id: Union[list[int], int]) -> economyv2.Agent:
155
+ async def get_agent(
156
+ self, id: Union[list[int], int]
157
+ ) -> Union[dict[str, Any], list[dict[str, Any]]]:
153
158
  """
154
159
  Get agent by id
155
160
 
@@ -160,17 +165,10 @@ class EconomyClient:
160
165
  - `economyv2.Agent`: The agent object.
161
166
  """
162
167
  start_time = time.time()
163
- log = {
164
- "req": "get_agent",
165
- "start_time": start_time,
166
- "consumption": 0
167
- }
168
+ log = {"req": "get_agent", "start_time": start_time, "consumption": 0}
168
169
  if isinstance(id, list):
169
170
  agents = await self._aio_stub.BatchGet(
170
- org_service.BatchGetRequest(
171
- ids=id,
172
- type="agent"
173
- )
171
+ org_service.BatchGetRequest(ids=id, type="agent")
174
172
  )
175
173
  agents = MessageToDict(agents)["agents"]
176
174
  agent_dicts = [camel_to_snake(agent) for agent in agents]
@@ -179,16 +177,16 @@ class EconomyClient:
179
177
  return agent_dicts
180
178
  else:
181
179
  agent = await self._aio_stub.GetAgent(
182
- org_service.GetAgentRequest(
183
- agent_id=id
184
- )
180
+ org_service.GetAgentRequest(agent_id=id)
185
181
  )
186
182
  agent_dict = MessageToDict(agent)["agent"]
187
183
  log["consumption"] = time.time() - start_time
188
184
  self._log_list.append(log)
189
185
  return camel_to_snake(agent_dict)
190
186
 
191
- async def get_org(self, id: Union[list[int], int]) -> economyv2.Org:
187
+ async def get_org(
188
+ self, id: Union[list[int], int]
189
+ ) -> Union[dict[str, Any], list[dict[str, Any]]]:
192
190
  """
193
191
  Get org by id
194
192
 
@@ -199,17 +197,10 @@ class EconomyClient:
199
197
  - `economyv2.Org`: The org object.
200
198
  """
201
199
  start_time = time.time()
202
- log = {
203
- "req": "get_org",
204
- "start_time": start_time,
205
- "consumption": 0
206
- }
200
+ log = {"req": "get_org", "start_time": start_time, "consumption": 0}
207
201
  if isinstance(id, list):
208
202
  orgs = await self._aio_stub.BatchGet(
209
- org_service.BatchGetRequest(
210
- ids=id,
211
- type="org"
212
- )
203
+ org_service.BatchGetRequest(ids=id, type="org")
213
204
  )
214
205
  orgs = MessageToDict(orgs)["orgs"]
215
206
  org_dicts = [camel_to_snake(org) for org in orgs]
@@ -217,11 +208,7 @@ class EconomyClient:
217
208
  self._log_list.append(log)
218
209
  return org_dicts
219
210
  else:
220
- org = await self._aio_stub.GetOrg(
221
- org_service.GetOrgRequest(
222
- org_id=id
223
- )
224
- )
211
+ org = await self._aio_stub.GetOrg(org_service.GetOrgRequest(org_id=id))
225
212
  org_dict = MessageToDict(org)["org"]
226
213
  log["consumption"] = time.time() - start_time
227
214
  self._log_list.append(log)
@@ -243,18 +230,15 @@ class EconomyClient:
243
230
  - Any
244
231
  """
245
232
  start_time = time.time()
246
- log = {
247
- "req": "get",
248
- "start_time": start_time,
249
- "consumption": 0
250
- }
251
- if isinstance(id, list):
233
+ log = {"req": "get", "start_time": start_time, "consumption": 0}
234
+ if isinstance(id, Sequence):
252
235
  requests = "Org" if id[0] in self._org_ids else "Agent"
253
236
  if requests == "Org":
254
237
  response = await self.get_org(id)
255
238
  else:
256
239
  response = await self.get_agent(id)
257
240
  results = []
241
+ response = cast(list[dict[str, Any]], response)
258
242
  for res in response:
259
243
  results.append(res[key])
260
244
  log["consumption"] = time.time() - start_time
@@ -268,10 +252,11 @@ class EconomyClient:
268
252
  response = await self.get_org(id)
269
253
  else:
270
254
  response = await self.get_agent(id)
255
+ response = cast(dict[str, Any], response)
271
256
  log["consumption"] = time.time() - start_time
272
257
  self._log_list.append(log)
273
258
  return response[key]
274
-
259
+
275
260
  def _merge(self, original_value, key, value):
276
261
  try:
277
262
  orig_value = original_value[key]
@@ -321,16 +306,14 @@ class EconomyClient:
321
306
  - Any
322
307
  """
323
308
  start_time = time.time()
324
- log = {
325
- "req": "update",
326
- "start_time": start_time,
327
- "consumption": 0
328
- }
309
+ log = {"req": "update", "start_time": start_time, "consumption": 0}
329
310
  if isinstance(id, list):
330
311
  if not isinstance(value, list):
331
312
  raise ValueError(f"Invalid value, the value must be a list!")
332
313
  if len(id) != len(value):
333
- raise ValueError(f"Invalid ids and values, the length of ids and values must be the same!")
314
+ raise ValueError(
315
+ f"Invalid ids and values, the length of ids and values must be the same!"
316
+ )
334
317
  request_type = "Org" if id[0] in self._org_ids else "Agent"
335
318
  else:
336
319
  if id not in self._agent_ids and id not in self._org_ids:
@@ -363,16 +346,11 @@ class EconomyClient:
363
346
  # ))
364
347
  # await asyncio.gather(*batch_update_tasks)
365
348
  await self._aio_stub.BatchUpdate(
366
- org_service.BatchUpdateRequest(
367
- orgs=original_value,
368
- agents=None
369
- )
349
+ org_service.BatchUpdateRequest(orgs=original_value, agents=None)
370
350
  )
371
351
  else:
372
352
  await self._aio_stub.UpdateOrg(
373
- org_service.UpdateOrgRequest(
374
- org=original_value
375
- )
353
+ org_service.UpdateOrgRequest(org=original_value)
376
354
  )
377
355
  log["consumption"] = time.time() - start_time
378
356
  self._log_list.append(log)
@@ -387,16 +365,11 @@ class EconomyClient:
387
365
  # ))
388
366
  # await asyncio.gather(*batch_update_tasks)
389
367
  await self._aio_stub.BatchUpdate(
390
- org_service.BatchUpdateRequest(
391
- orgs=None,
392
- agents=original_value
393
- )
368
+ org_service.BatchUpdateRequest(orgs=None, agents=original_value)
394
369
  )
395
370
  else:
396
371
  await self._aio_stub.UpdateAgent(
397
- org_service.UpdateAgentRequest(
398
- agent=original_value
399
- )
372
+ org_service.UpdateAgentRequest(agent=original_value)
400
373
  )
401
374
  log["consumption"] = time.time() - start_time
402
375
  self._log_list.append(log)
@@ -572,18 +545,11 @@ class EconomyClient:
572
545
  return response.actual_consumption
573
546
  else:
574
547
  return -1
575
-
576
-
548
+
577
549
  async def calculate_real_gdp(self, nbs_id: int):
578
550
  start_time = time.time()
579
- log = {
580
- "req": "calculate_real_gdp",
581
- "start_time": start_time,
582
- "consumption": 0
583
- }
584
- request = org_service.CalculateRealGDPRequest(
585
- nbs_agent_id=nbs_id
586
- )
551
+ log = {"req": "calculate_real_gdp", "start_time": start_time, "consumption": 0}
552
+ request = org_service.CalculateRealGDPRequest(nbs_agent_id=nbs_id)
587
553
  response: org_service.CalculateRealGDPResponse = (
588
554
  await self._aio_stub.CalculateRealGDP(request)
589
555
  )
@@ -87,49 +87,63 @@ class Simulator:
87
87
  - 模拟器配置
88
88
  - simulator config
89
89
  """
90
- _mongo_uri, _mongo_db, _mongo_coll, _map_cache_dir = (
91
- config["map_request"]["mongo_uri"],
92
- config["map_request"]["mongo_db"],
93
- config["map_request"]["mongo_coll"],
94
- config["map_request"]["cache_dir"],
95
- )
96
- _mongo_client = MongoClient(_mongo_uri)
97
- os.makedirs(_map_cache_dir, exist_ok=True)
98
- _map_pb_path = os.path.join(_map_cache_dir, f"{_mongo_db}.{_mongo_coll}.pb") # type: ignore
99
- _map_pb = map_pb2.Map()
100
- if os.path.exists(_map_pb_path):
101
- with open(_map_pb_path, "rb") as f:
102
- _map_pb.ParseFromString(f.read())
90
+ _map_request = config["map_request"]
91
+ if "file_path" not in _map_request:
92
+ # from mongo db
93
+ _mongo_uri, _mongo_db, _mongo_coll, _map_cache_dir = (
94
+ _map_request["mongo_uri"],
95
+ _map_request["mongo_db"],
96
+ _map_request["mongo_coll"],
97
+ _map_request["cache_dir"],
98
+ )
99
+ _mongo_client = MongoClient(_mongo_uri)
100
+ os.makedirs(_map_cache_dir, exist_ok=True)
101
+ _map_pb_path = os.path.join(_map_cache_dir, f"{_mongo_db}.{_mongo_coll}.pb") # type: ignore
102
+ _map_pb = map_pb2.Map()
103
+ if os.path.exists(_map_pb_path):
104
+ with open(_map_pb_path, "rb") as f:
105
+ _map_pb.ParseFromString(f.read())
106
+ else:
107
+ _map_pb = coll2pb(_mongo_client[_mongo_db][_mongo_coll], _map_pb)
108
+ with open(_map_pb_path, "wb") as f:
109
+ f.write(_map_pb.SerializeToString())
103
110
  else:
104
- _map_pb = coll2pb(_mongo_client[_mongo_db][_mongo_coll], _map_pb)
105
- with open(_map_pb_path, "wb") as f:
106
- f.write(_map_pb.SerializeToString())
111
+ # from local file
112
+ _mongo_uri, _mongo_db, _mongo_coll, _map_cache_dir = "", "", "", ""
113
+ _map_pb_path = _map_request["file_path"]
107
114
 
108
115
  if "simulator" in config:
109
116
  if config["simulator"] is None:
110
117
  config["simulator"] = {}
111
- if "server" not in config["simulator"]:
118
+ if not config["simulator"].get("_server_activated", False):
112
119
  self._sim_env = sim_env = ControlSimEnv(
113
120
  task_name=config["simulator"].get("task", "citysim"),
114
121
  map_file=_map_pb_path,
115
122
  max_day=config["simulator"].get("max_day", 1000),
116
123
  start_step=config["simulator"].get("start_step", 28800),
117
- total_step=config["simulator"].get("total_step", 24*60*60*365),
124
+ total_step=config["simulator"].get(
125
+ "total_step", 24 * 60 * 60 * 365
126
+ ),
118
127
  log_dir=config["simulator"].get("log_dir", "./log"),
119
128
  min_step_time=config["simulator"].get("min_step_time", 1000),
120
129
  sim_addr=config["simulator"].get("server", None),
121
130
  )
122
131
  self.server_addr = sim_env.sim_addr
123
132
  config["simulator"]["server"] = self.server_addr
133
+ config["simulator"]["_server_activated"] = True
124
134
  # using local client
125
- self._client = CityClient(sim_env.sim_addr, secure=False)
135
+ self._client = CityClient(
136
+ sim_env.sim_addr, secure=self.server_addr.startswith("https")
137
+ )
126
138
  """
127
139
  - 模拟器grpc客户端
128
140
  - grpc client of simulator
129
141
  """
130
142
  else:
131
- self._client = CityClient(config["simulator"]["server"], secure=False)
132
143
  self.server_addr = config["simulator"]["server"]
144
+ self._client = CityClient(
145
+ self.server_addr, secure=self.server_addr.startswith("https")
146
+ )
133
147
  else:
134
148
  self.server_addr = None
135
149
  logger.warning(
@@ -141,10 +155,9 @@ class Simulator:
141
155
  - Simulator map object
142
156
  """
143
157
  if create_map:
144
- _map_cache_path = "" # 地图pb文件路径
145
158
  self._map = CityMap.remote(
146
159
  (_mongo_uri, _mongo_db, _mongo_coll, _map_cache_dir),
147
- _map_cache_path,
160
+ _map_pb_path,
148
161
  )
149
162
  self._create_poi_id_2_aoi_id()
150
163
 
@@ -363,7 +376,7 @@ class Simulator:
363
376
  log = {"req": "get_simulator_day", "start_time": start_time, "consumption": 0}
364
377
  now = await self._client.clock_service.Now({})
365
378
  now = cast(dict[str, int], now)
366
- day = int(now["t"]//(24*60*60))
379
+ day = int(now["t"] // (24 * 60 * 60))
367
380
  log["consumption"] = time.time() - start_time
368
381
  self._log_list.append(log)
369
382
  return day
@@ -385,7 +398,7 @@ class Simulator:
385
398
  now = cast(dict[str, int], now)
386
399
  log["consumption"] = time.time() - start_time
387
400
  self._log_list.append(log)
388
- return now["t"]%(24*60*60)
401
+ return now["t"] % (24 * 60 * 60)
389
402
 
390
403
  async def get_person(self, person_id: int) -> dict:
391
404
  """
@@ -22,13 +22,8 @@ from ..llm.llmconfig import LLMConfig
22
22
  from ..memory import FaissQuery, Memory
23
23
  from ..message import Messager
24
24
  from ..metrics import MlflowClient
25
- from ..utils import (
26
- DIALOG_SCHEMA,
27
- INSTITUTION_STATUS_SCHEMA,
28
- PROFILE_SCHEMA,
29
- STATUS_SCHEMA,
30
- SURVEY_SCHEMA,
31
- )
25
+ from ..utils import (DIALOG_SCHEMA, INSTITUTION_STATUS_SCHEMA, PROFILE_SCHEMA,
26
+ STATUS_SCHEMA, SURVEY_SCHEMA)
32
27
 
33
28
  logger = logging.getLogger("pycityagent")
34
29
  __all__ = ["AgentGroup"]
@@ -1021,7 +1021,9 @@ class AgentSimulation:
1021
1021
  try:
1022
1022
  # step
1023
1023
  simulator_day = await self._simulator.get_simulator_day()
1024
- simulator_time = int(await self._simulator.get_simulator_second_from_start_of_day())
1024
+ simulator_time = int(
1025
+ await self._simulator.get_simulator_second_from_start_of_day()
1026
+ )
1025
1027
  logger.info(
1026
1028
  f"Start simulation day {simulator_day} at {simulator_time}, step {self._total_steps}"
1027
1029
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: pycityagent
3
- Version: 2.0.0a84
3
+ Version: 2.0.0a85
4
4
  Summary: LLM-based city environment agent building library
5
5
  Author-email: Yuwei Yan <pinkgranite86@gmail.com>, Junbo Yan <yanjb20thu@gmali.com>, Jun Zhang <zhangjun990222@gmali.com>
6
6
  License: MIT License
@@ -1,10 +1,16 @@
1
+ pycityagent-2.0.0a85.dist-info/RECORD,,
2
+ pycityagent-2.0.0a85.dist-info/LICENSE,sha256=n2HPXiupinpyHMnIkbCf3OTYd3KMqbmldu1e7av0CAU,1084
3
+ pycityagent-2.0.0a85.dist-info/WHEEL,sha256=NW1RskY9zow1Y68W-gXg0oZyBRAugI1JHywIzAIai5o,109
4
+ pycityagent-2.0.0a85.dist-info/entry_points.txt,sha256=BZcne49AAIFv-hawxGnPbblea7X3MtAtoPyDX8L4OC4,132
5
+ pycityagent-2.0.0a85.dist-info/top_level.txt,sha256=yOmeu6cSXmiUtScu53a3s0p7BGtLMaV0aff83EHCTic,43
6
+ pycityagent-2.0.0a85.dist-info/METADATA,sha256=KKmALYa8DummI6EtxRIqeGaH5Fg_lS4yElcWAOdV2wU,9110
1
7
  pycityagent/pycityagent-sim,sha256=Ax6cjHjT8VcT5t07VboL_Ruor2eXSdSEml4Jvv-L5dQ,36972594
2
8
  pycityagent/__init__.py,sha256=PUKWTXc-xdMG7px8oTNclodsILUgypANj2Z647sY63k,808
3
9
  pycityagent/pycityagent-ui,sha256=Ur95yZygIaZ5l_CDqP9394M5GQ66iV5PkcNPYFWqzvk,41225346
4
10
  pycityagent/metrics/mlflow_client.py,sha256=-iyh4BPVnBkluhmfucUzibCUnBX2iftkz4tVJJVxwHw,6958
5
11
  pycityagent/metrics/__init__.py,sha256=X08PaBbGVAd7_PRGLREXWxaqm7nS82WBQpD1zvQzcqc,128
6
12
  pycityagent/economy/__init__.py,sha256=aonY4WHnx-6EGJ4WKrx4S-2jAkYNLtqUA04jp6q8B7w,75
7
- pycityagent/economy/econ_client.py,sha256=NUzrFzl0EL4UkMscGRRSu1JQmeCPwIkPvTbJDRefUcQ,29231
13
+ pycityagent/economy/econ_client.py,sha256=KXoRKnOrqYlFqgLHpNim1C5QRM7QPO3GtXG1Aq-yf6U,28621
8
14
  pycityagent/tools/__init__.py,sha256=y7sMVMHf0AbivlczM2h-kr7mkgXK-WAx3S9BXLXkWvw,235
9
15
  pycityagent/tools/tool.py,sha256=4ZJSHbNM8dfAVwZEw8T0a2_9OuPsPQpKSVL4WxZVBUc,9022
10
16
  pycityagent/llm/llmconfig.py,sha256=6AqCMV4B_JqBD2mb98bLGzpUdlOCnziQKae-Hhxxp-E,469
@@ -21,9 +27,9 @@ pycityagent/memory/utils.py,sha256=oJWLdPeJy_jcdKcDTo9JAH9kDZhqjoQhhv_zT9qWC0w,8
21
27
  pycityagent/memory/const.py,sha256=nFmjvt-8FEB0hc0glOH3lliqJhkhf3D_NKxWI0pf6TY,936
22
28
  pycityagent/memory/faiss_query.py,sha256=KPeyzIjD0dzkxr-TlOeCiIlkdh1WAyyipCAXUEt97Lk,17350
23
29
  pycityagent/memory/state.py,sha256=JFCBuK1AS-HqscvdGS9ATF9AUU8t29_2leDY_6iO2_4,5158
24
- pycityagent/simulation/simulation.py,sha256=08xtIVwmO35r5XbUW9nMDo9rL_6mtDtjWbeXnUyNR6c,49340
30
+ pycityagent/simulation/simulation.py,sha256=bHpR3FtUM6ewurwByRr57OgdTWXTPq9-knIjGt2GHlo,49370
25
31
  pycityagent/simulation/__init__.py,sha256=u1WpgwVxPboXWMxrUQKMXJNmTKQYAeCaqZv9HmSxESY,118
26
- pycityagent/simulation/agentgroup.py,sha256=oXo2iRUThh_96JhXHMufT8_BPx0PrlwqbMpiVqK_viA,36957
32
+ pycityagent/simulation/agentgroup.py,sha256=rPloocCwB6rfjWbIz3T052mYq2lEcBp97mblkMD2y0A,36955
27
33
  pycityagent/simulation/storage/pg.py,sha256=xRshSOGttW-p0re0fNBOjOpb-nQ5msIE2LsdT79_E_Y,8425
28
34
  pycityagent/message/message_interceptor.py,sha256=QWuTUqi1Cu214fhFs0f78tD2zflMnb6zEAGB4RutXxs,17736
29
35
  pycityagent/message/__init__.py,sha256=f5QH7DKPqEAMyfSlBMnl3uouOKlsoel909STlIe7nUk,276
@@ -46,7 +52,7 @@ pycityagent/workflow/prompt.py,sha256=rzenP4EFGxbWE1aq-x2036b6umKvi5cQx2xtWULwgI
46
52
  pycityagent/workflow/block.py,sha256=WJfCeL8e117GzkVPJCRNsQZZinccMnVyEubkwrf-17U,12295
47
53
  pycityagent/workflow/trigger.py,sha256=4nzAwywGQsFabgo6gzp-vD2EV4wII7Z0LHGEAsflSEY,7608
48
54
  pycityagent/environment/__init__.py,sha256=fFIth2jxxgZ92cXm-aoM2igHgaSqsYGwtBhyb7opjzk,166
49
- pycityagent/environment/simulator.py,sha256=qiqeRQDm7cprFJhAkxtdBNAvohiGGUaNIPGyFXmPdZU,22667
55
+ pycityagent/environment/simulator.py,sha256=sbM0FMjR_q2mssbpMI7Lx9QI2iFj1Hbzg48fbRMd4tY,23206
50
56
  pycityagent/environment/utils/port.py,sha256=3OM6kSUt3PxvDUOlgyiendBtETaWU8Mzk_8H0TzTmYg,295
51
57
  pycityagent/environment/utils/grpc.py,sha256=_lB4-k4dTKuNvApaDiYgFxiLTPtYG42DVQtG9yOj9pQ,2022
52
58
  pycityagent/environment/utils/base64.py,sha256=hoREzQo3FXMN79pqQLO2jgsDEvudciomyKii7MWljAM,374
@@ -89,9 +95,3 @@ pycityagent/cityagent/blocks/mobility_block.py,sha256=qkRiV0nkGOUUoo9lGIjAFE_Hl0
89
95
  pycityagent/survey/models.py,sha256=g3xni4GcA1Py3vlGt6z4ltutjgQ4G0uINYAM8vKRJAw,5225
90
96
  pycityagent/survey/__init__.py,sha256=rxwou8U9KeFSP7rMzXtmtp2fVFZxK4Trzi-psx9LPIs,153
91
97
  pycityagent/survey/manager.py,sha256=tHkdeq4lTfAHwvgf4-udsXri0z2l6E00rEbvwl7SqRs,3439
92
- pycityagent-2.0.0a84.dist-info/RECORD,,
93
- pycityagent-2.0.0a84.dist-info/LICENSE,sha256=n2HPXiupinpyHMnIkbCf3OTYd3KMqbmldu1e7av0CAU,1084
94
- pycityagent-2.0.0a84.dist-info/WHEEL,sha256=NW1RskY9zow1Y68W-gXg0oZyBRAugI1JHywIzAIai5o,109
95
- pycityagent-2.0.0a84.dist-info/entry_points.txt,sha256=BZcne49AAIFv-hawxGnPbblea7X3MtAtoPyDX8L4OC4,132
96
- pycityagent-2.0.0a84.dist-info/top_level.txt,sha256=yOmeu6cSXmiUtScu53a3s0p7BGtLMaV0aff83EHCTic,43
97
- pycityagent-2.0.0a84.dist-info/METADATA,sha256=wK7JDsxgO5pTlH_YLtftS9-nmD9T97_6-YZp8zru9dA,9110