psr-factory 5.0.0b17__py3-none-win_amd64.whl → 5.0.0b19__py3-none-win_amd64.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.
psr/cloud/cloud.py CHANGED
@@ -767,7 +767,7 @@ class Client:
767
767
 
768
768
  if extensions:
769
769
  Client._validate_extensions(extensions)
770
- filter_elements.extend([f".*.{ext}" for ext in extensions])
770
+ filter_elements.extend([f"*.{ext}" for ext in extensions])
771
771
 
772
772
  if files:
773
773
  filter_elements.extend(files)
psr/execqueue/client.py CHANGED
@@ -70,13 +70,13 @@ def upload_and_run_file(zip_path: str, server_url: str, cloud_execution: bool =
70
70
  return None
71
71
 
72
72
 
73
- def get_execution_status(execution_id: str, server_url: str, cloud_execution: bool = False, return_status_id: bool = False) -> Tuple[bool, dict]:
73
+ def get_execution_status(execution_id: str, server_url: str, cloud_execution: bool = False) -> Optional[tuple[int, str]]:
74
74
  """Get the status of an execution."""
75
- data = {'cloud_execution': cloud_execution, 'return_status_id': return_status_id}
75
+ print("Getting status for execution ID:", execution_id)
76
+ data = {'cloud_execution': cloud_execution}
76
77
  response = requests.get(f"{server_url}/status/{execution_id}", data=data)
77
78
  result = response.status_code == 200
78
- return result, response.json()
79
-
79
+ return response.json().get('status_id'), response.json().get('status_msg') if result else None
80
80
 
81
81
  def get_results(execution_id, server_url, cloud_execution=False) -> Optional[List[str]]:
82
82
  """Download the results of an execution."""
@@ -88,7 +88,7 @@ def get_results(execution_id, server_url, cloud_execution=False) -> Optional[Lis
88
88
  print("Files:", files)
89
89
  return files
90
90
  else:
91
- print("Download failed:", response.text)
91
+ print("Results download failed:", response.text)
92
92
  return None
93
93
 
94
94
 
psr/execqueue/db.py CHANGED
@@ -24,6 +24,7 @@ class CloudStatus(Enum):
24
24
  FINISHED = 3
25
25
  ERROR = 4
26
26
  RESULTS_AVAILABLE = 5
27
+ LOGS_AVAILABLE_ERROR = 6
27
28
 
28
29
 
29
30
  DB_NAME = "app.db"
@@ -157,7 +158,7 @@ def update_local_execution_status(session, execution_id: str, status: int):
157
158
  def update_cloud_execution_status(session, repository_id: int, status: int):
158
159
  cloud_execution = session.query(CloudExecution).filter(CloudExecution.repository_id == repository_id).first()
159
160
  if cloud_execution:
160
- if status not in CloudStatus:
161
+ if CloudStatus(status) not in CloudStatus:
161
162
  raise ValueError("Wrong status for update.")
162
163
  cloud_execution.status = status
163
164
  session.commit()
@@ -217,4 +218,7 @@ def get_cloud_execution_status(session, repository_id: int) -> Optional[int]:
217
218
  return cloud_execution.status if cloud_execution else None
218
219
 
219
220
  def get_cloud_finished_executions(session) -> List[CloudExecution]:
220
- return session.query(CloudExecution).filter(CloudExecution.status == CloudStatus.FINISHED.value).all()
221
+ return session.query(CloudExecution).filter(CloudExecution.status == CloudStatus.FINISHED.value).all()
222
+
223
+ def get_cloud_failed_executions(session) -> List[CloudExecution]:
224
+ return session.query(CloudExecution).filter(CloudExecution.status == CloudStatus.ERROR.value).all()
psr/execqueue/server.py CHANGED
@@ -42,7 +42,7 @@ except psr.cloud.CloudInputError as e:
42
42
 
43
43
  _cloud_execution_case_map = {}
44
44
 
45
- app = Flask(__name__)
45
+ app = Flask(__name__, root_path=os.getcwd())
46
46
  session = None
47
47
 
48
48
 
@@ -76,7 +76,7 @@ def run_cloud_case(execution_id: str, case_path: str):
76
76
  name="LSEG Server "+ execution_id,
77
77
  data_path=case_path,
78
78
  program="SDDP",
79
- program_version = "17.2.12",
79
+ program_version = "17.3.9",
80
80
  execution_type="Default",
81
81
  memory_per_process_ratio='2:1',
82
82
  price_optimized=False,
@@ -180,6 +180,20 @@ def monitor_cloud_runs():
180
180
  result_path = os.path.join(CLOUD_RESULTS_FOLDER, str(repository_id))
181
181
  client.download_results(repository_id, result_path)
182
182
  db.update_cloud_execution_status(session, repository_id, db.CloudStatus.RESULTS_AVAILABLE.value)
183
+
184
+ #download failed executions
185
+ for cloud_execution in db.get_cloud_failed_executions(session):
186
+ try:
187
+ repository_id = cloud_execution.repository_id
188
+ print(f"Downloading results for {repository_id}...")
189
+ result_path = os.path.join(CLOUD_RESULTS_FOLDER, str(repository_id))
190
+ client.download_results(repository_id, result_path, extensions=['log'])
191
+ db.update_cloud_execution_status(session, repository_id, db.CloudStatus.LOGS_AVAILABLE_ERROR.value)
192
+ except Exception as e:
193
+ print(f"Error downloading results for {repository_id}: {e}")
194
+ print("Forcing execution to Failed downloaded execution")
195
+ db.update_cloud_execution_status(session, repository_id, db.CloudStatus.LOGS_AVAILABLE_ERROR.value)
196
+ continue
183
197
  else:
184
198
  print("Database not initialized. Retrying in 30s...")
185
199
  time.sleep(30)
@@ -282,30 +296,43 @@ def get_status(execution_id):
282
296
  200:
283
297
  description: Execution status
284
298
  schema:
285
- type: string
299
+ type: object
286
300
  404:
287
301
  description: Execution ID not found
288
- """
302
+ """
289
303
  global client
290
304
  global session
291
305
  cloud_execution = request.form.get('cloud_execution', 'false').lower() == 'true'
292
- return_status_id = request.form.get('return_status_id', 'false').lower() == 'true'
293
306
 
294
307
  if cloud_execution:
295
308
  repository_id = db.get_repository_id_from_cloud_upload_id(session, execution_id)
296
309
  if repository_id is None:
297
310
  return jsonify({'error': 'Execution ID not found in Cloud'}), 404
298
311
  status = db.get_cloud_execution_status(session, repository_id)
299
- if return_status_id:
300
- return jsonify({'status_id': status}), 200
301
312
  if status == db.CloudStatus.ERROR.value:
302
- return jsonify({'message': 'Execution finished with errors'}), 200
313
+ status_msg = 'Execution finished with errors. Only log files will be downloaded'
303
314
  elif status == db.CloudStatus.RUNNING.value:
304
- return jsonify({'message': 'Execution not finished yet'}), 200
315
+ status_msg = 'Execution not finished yet'
305
316
  elif status == db.CloudStatus.FINISHED.value:
306
- return jsonify({'message': 'Execution finished, but download not yet downloaded from Cloud server'}), 200
317
+ status_msg = 'Execution finished, but download not yet started from Cloud server'
307
318
  elif status == db.CloudStatus.RESULTS_AVAILABLE.value:
308
- return jsonify({'message': 'Execution finished and results are available to download'}), 200
319
+ status_msg = 'Execution finished and results are available to download'
320
+ elif status == db.CloudStatus.LOGS_AVAILABLE_ERROR.value:
321
+ status_msg = 'Execution finished with errors and log files are avaialble to download'
322
+ else:
323
+ status_msg = 'Unknown status'
324
+ print(f"Cloud execution status for {execution_id} ({repository_id}): {status_msg}")
325
+ return jsonify({'status_id': status, 'status_msg': status_msg}), 200
326
+ else:
327
+ status = db.get_local_execution_status(session, execution_id)
328
+ if status == db.LOCAL_EXECUTION_ERROR:
329
+ status_msg = 'Execution finished with errors'
330
+ elif status != db.LOCAL_EXECUTION_FINISHED:
331
+ status_msg = 'Execution not finished yet'
332
+ else:
333
+ status_msg = 'Execution finished'
334
+ return jsonify({'status_id': status, 'status_msg': status_msg}), 200
335
+
309
336
 
310
337
  @app.route('/results/<execution_id>', methods=['GET'])
311
338
  def get_results(execution_id: str):
@@ -319,18 +346,17 @@ def get_results(execution_id: str):
319
346
  return jsonify({'error': 'Execution ID not found in Cloud'}),
320
347
  status = db.get_cloud_execution_status(session, execution_id)
321
348
 
322
- if status == db.CloudStatus.ERROR:
323
- return jsonify({'error': 'Execution Finished with errors'}), 401
324
- elif status == db.CloudStatus.RUNNING:
325
- return jsonify({'error': 'Execution not finished yet'}), 402
349
+ if status == db.CloudStatus.RUNNING:
350
+ return jsonify({'error': f'{repository_id} execution not finished yet'}), 402
326
351
  elif status == db.CloudStatus.FINISHED:
327
- return jsonify({'error': 'Results not available yet'}), 403
352
+ return jsonify({'error': f'{repository_id} results not available yet'}), 403
328
353
  else:
329
354
  #fazer download da pasta do resultado
330
355
  result_path = os.path.join(CLOUD_RESULTS_FOLDER, str(repository_id))
331
356
  if not os.path.exists(result_path):
332
- return jsonify({'error': 'Execution result folder not found'}), 404
357
+ return jsonify({'error': f'{repository_id} execution result folder not found'}), 404
333
358
  result_files = os.listdir(result_path)
359
+ result_files = [f for f in result_files if os.path.isfile(os.path.join(result_path, f))]
334
360
  return jsonify({'execution_id': repository_id, 'files': result_files}), 200
335
361
  else:
336
362
  status = db.get_local_execution_status(session, execution_id)
@@ -357,14 +383,18 @@ def download_file(execution_id: str, file):
357
383
  else:
358
384
  result_path = os.path.join(LOCAL_RESULTS_FOLDER, execution_id)
359
385
  if not os.path.exists(result_path):
360
- return jsonify({'error': 'Execution result folder not found'}), 404
386
+ if cloud_execution:
387
+ msg = f'{repository_id} execution result folder not found'
388
+ else:
389
+ msg = f'Execution result folder not found'
390
+ return jsonify({'error': msg}), 404
361
391
 
362
- file_path = os.path.join(result_path, file)
392
+ file_path = os.path.normpath(os.path.join(result_path, file)).replace("\\", "/")
363
393
  if not os.path.exists(file_path):
364
394
  return jsonify({'error': 'File not found'}), 404
365
395
 
366
396
  try:
367
- return send_file(file_path, as_attachment=True)
397
+ return send_file(file_path, download_name=file, as_attachment=True)
368
398
  except Exception as e:
369
399
  return jsonify({'error': str(e)}), 500
370
400
 
psr/execqueue/watcher.py CHANGED
@@ -12,7 +12,7 @@ SERVER_URL = os.getenv("SERVER_URL", "http://127.0.0.1:5000")
12
12
  WATCH_DIR = os.getenv("WATCH_DIR")
13
13
  PROCESSED_DIR = os.getenv("PROCESSED_DIR")
14
14
  RESULTS_DIR = os.getenv("RESULTS_DIR", "results")
15
- SLEEP_SECONDS = int(os.getenv("WATCHER_SLEEP", "30"))
15
+ SLEEP_SECONDS = int(os.getenv("WATCHER_SLEEP", "1"))
16
16
  DB_PATH = os.getenv("WATCHER_DB_PATH", "watcher.sqlite")
17
17
 
18
18
 
@@ -42,14 +42,32 @@ def _log_to_db(filename, cloud_upload_id):
42
42
  conn.commit()
43
43
  conn.close()
44
44
 
45
-
45
+ def _is_file_locked(filepath):
46
+ """Returns True if the file is locked by another process (e.g., still being copied)."""
47
+ if not os.path.exists(filepath):
48
+ return True
49
+ try:
50
+ # Try to open for exclusive writing
51
+ with open(filepath, 'rb+') as f:
52
+ pass
53
+ return False
54
+ except (OSError, PermissionError):
55
+ return True
56
+
46
57
  def _process_zip_files():
47
58
  for filename in os.listdir(WATCH_DIR):
48
59
  if filename.lower().endswith('.zip'):
49
60
  zip_path = os.path.join(WATCH_DIR, filename)
61
+
62
+ # Check if the file is locked
63
+ if _is_file_locked(zip_path):
64
+ logging.info(f"Skipping {zip_path}: file is locked or being copied.")
65
+ continue
66
+
50
67
  logging.info(f"zip file found: {zip_path}")
51
68
 
52
- case_id = execqueue.upload_case_file(zip_path, SERVER_URL)
69
+ #case_id = execqueue.upload_case_file(zip_path, SERVER_URL)
70
+ case_id = 1
53
71
  if not case_id:
54
72
  logging.error(f"Failed uploading file {zip_path}")
55
73
  continue
@@ -73,11 +91,12 @@ def _check_and_download_results():
73
91
  rows = cursor.fetchall()
74
92
  for row in rows:
75
93
  record_id, filename, cloud_upload_id = row
76
- result, response = execqueue.get_execution_status(cloud_upload_id, SERVER_URL, cloud_execution=True, return_status_id=True)
77
- status = response.get('status_id', 0)
78
- message = response.get('message', None)
79
- error = response.get('error', None)
80
- if status == "5" or status == 5:
94
+ status_id, status_msg = execqueue.get_execution_status(cloud_upload_id, SERVER_URL, cloud_execution=True)
95
+ logging.info(f"Execution status for {cloud_upload_id}: {status_id} - {status_msg}")
96
+ if status_id is None:
97
+ logging.error(f"Failed to get status for {cloud_upload_id}. Skipping download.")
98
+ continue
99
+ if status_id == 5 or status_id == 6:
81
100
  files = execqueue.get_results(cloud_upload_id, SERVER_URL, cloud_execution=True)
82
101
  if files:
83
102
  base_filename = os.path.splitext(filename)[0]
@@ -91,10 +110,6 @@ def _check_and_download_results():
91
110
  cursor.execute("UPDATE processed_files SET downloaded=1 WHERE id=?", (record_id,))
92
111
  conn.commit()
93
112
  logging.info(f"Results of {cloud_upload_id} downloaded to {download_path}")
94
- elif status == "4" or status == 4:
95
- logging.info(f"Execution {cloud_upload_id} is finished with errors.")
96
- cursor.execute("UPDATE processed_files SET downloaded=4 WHERE id=?", (record_id,))
97
- conn.commit()
98
113
 
99
114
  conn.close()
100
115
 
psr/factory/__init__.py CHANGED
@@ -2,6 +2,6 @@
2
2
  # Unauthorized copying of this file, via any medium is strictly prohibited
3
3
  # Proprietary and confidential
4
4
 
5
- __version__ = "5.0.0b17"
5
+ __version__ = "5.0.0b19"
6
6
 
7
7
  from .api import *
psr/factory/factory.dll CHANGED
Binary file
psr/factory/factory.pmd CHANGED
@@ -5036,6 +5036,8 @@ DEFINE_MODEL MODL:SDDP_V10.2_Bateria
5036
5036
 
5037
5037
  MERGE_MODEL SDDP_MAINTENANCE_PER_STAGE
5038
5038
  MERGE_MODEL SDDP_MAINTENANCE_PER_HOUR
5039
+
5040
+ PARM REFERENCE ControlledBus PSRBus
5039
5041
  END_MODEL
5040
5042
  //--------------------------------------------------------------------------------------------------
5041
5043
  // Modelo para Consumo de Combustivel
@@ -5044,6 +5046,7 @@ DEFINE_MODEL MODL:SDDP_ConsumoCombustivel
5044
5046
  DIMENSION block
5045
5047
  DIMENSION segment
5046
5048
  VETOR DATE Data
5049
+ VETOR REAL GerMax INDEX Data
5047
5050
  VETOR REAL O&MCost INDEX Data
5048
5051
  VETOR REAL G DIM(segment) INDEX Data
5049
5052
  VETOR REAL CTransp INDEX Data
Binary file
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: psr-factory
3
- Version: 5.0.0b17
3
+ Version: 5.0.0b19
4
4
  Summary: PSR database management module.
5
5
  Author-email: "PSR Inc." <psrfactory@psr-inc.com>
6
6
  License-Expression: MIT
@@ -55,69 +55,3 @@ Requires-Dist: pefile; extra == "all"
55
55
  Requires-Dist: boto3; extra == "all"
56
56
  Requires-Dist: botocore; extra == "all"
57
57
  Dynamic: license-file
58
-
59
- PSR Factory (version 4.0.38)
60
- ============================
61
-
62
- Factory is a library that helps to manage SDDP cases.
63
- It contains functions that create, load, and save studies, and also functions that create,
64
- access, and modify objects in a study.
65
-
66
-
67
- Installation
68
- ------------
69
-
70
- ### System-wide installation
71
-
72
- Open the command prompt and run the following command:
73
-
74
- ```bash
75
- pip install psr_factory-4.0.38-py3-none-win_amd64.whl
76
- ```
77
-
78
- Factory will be available to all Python scripts in your system after importing it:
79
-
80
- ```python
81
- import psr.factory
82
- ```
83
-
84
- ### Local/project-specific usage
85
-
86
- Copy the folder `psr` and its contents to your project folder or a specific folder (e.g., `C:\path\to\factory`). Then, in your Python script, add the following lines:
87
-
88
- ```python
89
- import sys
90
- sys.path.append(r"C:\path\to\factory")
91
- import psr.factory
92
- ```
93
-
94
-
95
- Usage sample
96
- ------------
97
-
98
- ```python
99
- import psr.factory
100
-
101
- study = psr.factory.load_study(r"C:\temp\my\study")
102
- system_1 = study.find("System.*")[0]
103
-
104
- battery = psr.factory.create("Battery")
105
- battery.code = 1
106
- battery.name = "Battery 1"
107
- battery.set("InstalledCapacity", 10.0)
108
- battery.set("RefSystem", system_1)
109
- study.add(battery)
110
-
111
- study.save(r"C:\temp\my\updated_study")
112
- ```
113
-
114
-
115
- Full documentation
116
- ------------------
117
-
118
- The full documentation and reference is available at [https://docs.psr-inc.com/factory/](https://docs.psr-inc.com/manual/factory/).
119
-
120
- Releases
121
- --------
122
-
123
- New releases can be found in the release notes at [https://psrenergy-docs.github.io/factory/releases.html](https://psrenergy-docs.github.io/factory/releases.html).
@@ -3,7 +3,7 @@ psr/apps/apps.py,sha256=V8Ewht7P1I-3sSkV3dnbxbLjF2slxPjcmtzmVaLjiNY,6746
3
3
  psr/apps/version.py,sha256=vs459L6JsatAkUxna7BNG-vMCaXpO1Ye8c1bmkEx4U4,194
4
4
  psr/cloud/__init__.py,sha256=inZMwG7O9Fca9hg1BhqYObOYtTTJOkpuTIuXnkHJZkI,246
5
5
  psr/cloud/aws.py,sha256=ro8kBNVxpGDXgZ5haceqX-MAD-0F5KFDJJ4M6rRvwS8,9915
6
- psr/cloud/cloud.py,sha256=RNFUXCAj4IRAMWUUyiEeZfwOqVVZdN28UZPLPSbm-5Y,59207
6
+ psr/cloud/cloud.py,sha256=gLwVL4aJITo75F4x2k53TJx0-giBLF614p3t3NdfD9o,59206
7
7
  psr/cloud/data.py,sha256=oDJyzcNsA7aAYi_qJKCUjCeGZvN-25E8KjZ-5RamNLE,4160
8
8
  psr/cloud/desktop.py,sha256=JFroCMEFV1Nz3has74n7OVrGCg2lS7Ev5bcjdw2hRxY,2980
9
9
  psr/cloud/log.py,sha256=Dvhz1enIWlFWeaRK7JAAuZVPfODgoEIRNcHEmbEliyQ,1366
@@ -11,18 +11,18 @@ psr/cloud/status.py,sha256=vcI4B9S6wCt9maT5NNrVwYaEgGIvy6kkC1UVpJjYbtw,3607
11
11
  psr/cloud/tempfile.py,sha256=1IOeye0eKWnmBynK5K5FMWiTaEVhn4GbQ8_y0THEva0,3893
12
12
  psr/cloud/version.py,sha256=jwq5nQsan38iZF0lj5GFK7l9EIe4aSF1NzdcupAfHP4,192
13
13
  psr/cloud/xml.py,sha256=ac2lyflOQm8khPvJn0zmI26I4sfUDY6A_OTsxzbMQEs,1896
14
- psr/execqueue/client.py,sha256=EjhXXWZli8MZP1rkKuYA1EL-VxO4aAUYZKsRa1mrG6Q,4374
14
+ psr/execqueue/client.py,sha256=P89Yt76W2GqRXaG_MLsa0kXf0jPp-weBd3aSTRcDzcs,4443
15
15
  psr/execqueue/config.py,sha256=3KVwASOgRlymOSPeabotgBdLVB5sPKnPQ9og2q3LQfw,1418
16
- psr/execqueue/db.py,sha256=0pH5ksXChz6PR_GQs6OPokK3zVkY1-OZRAqYbVIEh9k,8281
17
- psr/execqueue/server.py,sha256=IwqVq0hTMAqAyvCF7FXQsf8i82NyWq2BjnZFDOjwg9s,13936
18
- psr/execqueue/watcher.py,sha256=34TdU6quJIjWoOBlIbP1fA6fxaX5WmV1tAhvrIL30Uo,5213
19
- psr/factory/__init__.py,sha256=x7QgqQMjCxzDk6KzDpRTfczgMTQQuiNDrsczAi1ynFM,219
16
+ psr/execqueue/db.py,sha256=sNr_StNEgZZQCKcyCWiB1WrQJIhE9UvLUxPA2tWiXGs,8498
17
+ psr/execqueue/server.py,sha256=nW-Hi5zWHgPeLicASKJND7u6rz6eqwC16k91tUUQPxk,15741
18
+ psr/execqueue/watcher.py,sha256=RCjaWCS3jdbcugMk3-hOQCmrKxFzVOm-Wn-SLYBdBgY,5662
19
+ psr/factory/__init__.py,sha256=E5_ke-sdZr5-RNQ0YkE6Ia4k_dGMXhJAsi0xnl9RBUw,219
20
20
  psr/factory/api.py,sha256=OsjFnXgl6ltYtcpDIhvjauGFprVrIaHWPcMgCGJ1C1E,101464
21
- psr/factory/factory.dll,sha256=v-etVKFq-0V4IxN_eE1-0_J_wZZjy8DXwSP-eS-2Y7M,18276688
22
- psr/factory/factory.pmd,sha256=NEOeQifMlZfrfQqSgDdvH8yKqdIYhj7biZHeceROr8M,250454
21
+ psr/factory/factory.dll,sha256=Ayn-rwrdTP_jM-x8bFXHLEOp30NFB55kkWbarkjVZns,18301440
22
+ psr/factory/factory.pmd,sha256=HryDY8T6vAV5r0W4ytKNPiIYcdn4LexrsVZ5qFYBZ-g,250535
23
23
  psr/factory/factory.pmk,sha256=THhHxBKTBchru3fxTCos-pBAPJJnuug8T2dw0xniDfQ,580185
24
24
  psr/factory/factorylib.py,sha256=rwqu9lucfBhiFECDd5UVuy1K9jIJ54mUfxNPh4JhY4I,28182
25
- psr/factory/libcurl-x64.dll,sha256=3jBgZlBIITj6jzCW39wpf_2UE15DPORnnhLssEqtn5A,5317968
25
+ psr/factory/libcurl-x64.dll,sha256=6WGBmqX4q_eD8Vc0E2VpCvVrFV3W7TQoaKqSdbhXBu0,5313096
26
26
  psr/factory/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
27
  psr/factory/samples/__init__.py,sha256=xxOch5Fokzjy571a6OHD87FWM17qKgvfcbr8xn-n36I,80
28
28
  psr/factory/samples/sddp_case01.py,sha256=eLhtOAS2STl9-H7Nr5VUG4ATO0bVcn-CJtCn3Rf-vpI,5044
@@ -33,8 +33,8 @@ psr/psrfcommon/tempfile.py,sha256=5S13wa2DCLYTUdwbLm_KMBRnDRJ0WDlu8GO2BmZoNdg,39
33
33
  psr/runner/__init__.py,sha256=kI9HDX-B_LMQJUHHylFHas2rNpWfNNa0pZXoIvX_Alw,230
34
34
  psr/runner/runner.py,sha256=L_YOCArpkr_O-UJH6aT3K46NlEYT_o7LA1Ldk81BULQ,27326
35
35
  psr/runner/version.py,sha256=mch2Y8anSXGMn9w72Z78PhSRhOyn55EwaoLAYhY4McE,194
36
- psr_factory-5.0.0b17.dist-info/licenses/LICENSE.txt,sha256=N6mqZK2Ft3iXGHj-by_MHC_dJo9qwn0URjakEPys3H4,1089
37
- psr_factory-5.0.0b17.dist-info/METADATA,sha256=rzpiO3UKY-mVsanTn2hpRiD685M-M0Gm5EZUrFXdPl8,3957
38
- psr_factory-5.0.0b17.dist-info/WHEEL,sha256=ZjXRCNaQ9YSypEK2TE0LRB0sy2OVXSszb4Sx1XjM99k,97
39
- psr_factory-5.0.0b17.dist-info/top_level.txt,sha256=Jb393O96WQk3b5D1gMcrZBLKJJgZpzNjTPoldUi00ck,4
40
- psr_factory-5.0.0b17.dist-info/RECORD,,
36
+ psr_factory-5.0.0b19.dist-info/licenses/LICENSE.txt,sha256=N6mqZK2Ft3iXGHj-by_MHC_dJo9qwn0URjakEPys3H4,1089
37
+ psr_factory-5.0.0b19.dist-info/METADATA,sha256=FibEzT-fEVac6AqnO-y2pXM7tan6URDMUTEk4waReHA,2333
38
+ psr_factory-5.0.0b19.dist-info/WHEEL,sha256=ZjXRCNaQ9YSypEK2TE0LRB0sy2OVXSszb4Sx1XjM99k,97
39
+ psr_factory-5.0.0b19.dist-info/top_level.txt,sha256=Jb393O96WQk3b5D1gMcrZBLKJJgZpzNjTPoldUi00ck,4
40
+ psr_factory-5.0.0b19.dist-info/RECORD,,