psr-factory 5.0.0b32__py3-none-win_amd64.whl → 5.0.0b36__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.
Potentially problematic release.
This version of psr-factory might be problematic. Click here for more details.
- psr/cloud/aws.py +101 -14
- psr/cloud/cloud.py +84 -57
- psr/cloud/version.py +1 -1
- psr/execqueue/config.py +1 -0
- psr/execqueue/server.py +1 -1
- psr/execqueue/watcher.py +1 -1
- psr/factory/__init__.py +1 -1
- psr/factory/factory.dll +0 -0
- {psr_factory-5.0.0b32.dist-info → psr_factory-5.0.0b36.dist-info}/METADATA +68 -1
- {psr_factory-5.0.0b32.dist-info → psr_factory-5.0.0b36.dist-info}/RECORD +13 -13
- {psr_factory-5.0.0b32.dist-info → psr_factory-5.0.0b36.dist-info}/WHEEL +0 -0
- {psr_factory-5.0.0b32.dist-info → psr_factory-5.0.0b36.dist-info}/licenses/LICENSE.txt +0 -0
- {psr_factory-5.0.0b32.dist-info → psr_factory-5.0.0b36.dist-info}/top_level.txt +0 -0
psr/cloud/aws.py
CHANGED
|
@@ -5,6 +5,7 @@ from typing import Dict, List, Optional
|
|
|
5
5
|
|
|
6
6
|
import boto3
|
|
7
7
|
from botocore.exceptions import ClientError
|
|
8
|
+
from tqdm import tqdm
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
class AWS:
|
|
@@ -14,7 +15,6 @@ class AWS:
|
|
|
14
15
|
secret: str,
|
|
15
16
|
session_token: str,
|
|
16
17
|
url: str,
|
|
17
|
-
bucket_name: str,
|
|
18
18
|
Logger=None,
|
|
19
19
|
):
|
|
20
20
|
self.s3_client = boto3.client(
|
|
@@ -24,7 +24,6 @@ class AWS:
|
|
|
24
24
|
aws_session_token=session_token,
|
|
25
25
|
region_name=AWS.get_region(url),
|
|
26
26
|
)
|
|
27
|
-
self.bucket_name = bucket_name
|
|
28
27
|
self.logger = Logger
|
|
29
28
|
|
|
30
29
|
@staticmethod
|
|
@@ -38,15 +37,21 @@ class AWS:
|
|
|
38
37
|
def upload_file(
|
|
39
38
|
self,
|
|
40
39
|
file_path: str,
|
|
40
|
+
bucket_name: str,
|
|
41
41
|
object_name: Optional[str] = None,
|
|
42
42
|
extra_args: Optional[dict] = None,
|
|
43
|
+
Callback=None,
|
|
43
44
|
) -> bool:
|
|
44
45
|
"""Upload a file to an S3 bucket using the AWS instance's S3 client."""
|
|
45
46
|
if object_name is None:
|
|
46
47
|
object_name = os.path.basename(file_path)
|
|
47
48
|
try:
|
|
48
49
|
self.s3_client.upload_file(
|
|
49
|
-
file_path,
|
|
50
|
+
file_path,
|
|
51
|
+
bucket_name,
|
|
52
|
+
object_name,
|
|
53
|
+
ExtraArgs=extra_args,
|
|
54
|
+
Callback=Callback,
|
|
50
55
|
)
|
|
51
56
|
return True
|
|
52
57
|
except ClientError as e:
|
|
@@ -57,7 +62,7 @@ class AWS:
|
|
|
57
62
|
self,
|
|
58
63
|
files: List[str],
|
|
59
64
|
repository_id: str,
|
|
60
|
-
|
|
65
|
+
bucket_name: str,
|
|
61
66
|
checksums: Optional[Dict[str, str]] = None,
|
|
62
67
|
zip_compress: bool = False,
|
|
63
68
|
compress_zip_name: str = None,
|
|
@@ -80,7 +85,7 @@ class AWS:
|
|
|
80
85
|
suffix=".zip", delete=False
|
|
81
86
|
) as tmp_zip_file:
|
|
82
87
|
zip_path = tmp_zip_file.name
|
|
83
|
-
tmp_zip_file.close()
|
|
88
|
+
tmp_zip_file.close()
|
|
84
89
|
|
|
85
90
|
try:
|
|
86
91
|
with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as zipf:
|
|
@@ -90,9 +95,11 @@ class AWS:
|
|
|
90
95
|
object_name = f"{repository_id}/uploaded/{compress_zip_name}.zip"
|
|
91
96
|
extra_args = {"Metadata": base_metadata.copy()}
|
|
92
97
|
|
|
93
|
-
if not self.upload_file(
|
|
98
|
+
if not self.upload_file(
|
|
99
|
+
zip_path, bucket_name, object_name, extra_args=extra_args
|
|
100
|
+
):
|
|
94
101
|
raise ValueError(
|
|
95
|
-
f"Failed to upload zip file {zip_path} to S3 bucket {
|
|
102
|
+
f"Failed to upload zip file {zip_path} to S3 bucket {bucket_name}."
|
|
96
103
|
)
|
|
97
104
|
finally:
|
|
98
105
|
if os.path.exists(zip_path):
|
|
@@ -110,7 +117,7 @@ class AWS:
|
|
|
110
117
|
|
|
111
118
|
if not self.upload_file(file_path, object_name, extra_args=extra_args):
|
|
112
119
|
raise ValueError(
|
|
113
|
-
f"Failed to upload file {file_path} to S3 bucket {
|
|
120
|
+
f"Failed to upload file {file_path} to S3 bucket {bucket_name}."
|
|
114
121
|
)
|
|
115
122
|
|
|
116
123
|
# Always upload .metadata files if the source 'files' list is provided
|
|
@@ -136,15 +143,74 @@ class AWS:
|
|
|
136
143
|
extra_args=extra_args,
|
|
137
144
|
):
|
|
138
145
|
raise ValueError(
|
|
139
|
-
f"Failed to upload metadata file {local_metadata_file_path} to S3 bucket {
|
|
146
|
+
f"Failed to upload metadata file {local_metadata_file_path} to S3 bucket {bucket_name}."
|
|
140
147
|
)
|
|
141
148
|
|
|
142
|
-
def
|
|
143
|
-
|
|
149
|
+
def upload_version(
|
|
150
|
+
self,
|
|
151
|
+
model_name: str,
|
|
152
|
+
version_name: str,
|
|
153
|
+
bucket_name: str,
|
|
154
|
+
file_path: str,
|
|
155
|
+
):
|
|
156
|
+
"""
|
|
157
|
+
Uploads a new version of the model to S3.
|
|
158
|
+
"""
|
|
159
|
+
build = os.path.basename(file_path)
|
|
160
|
+
object_name = f"{model_name}/{version_name}/linux/{build}"
|
|
161
|
+
file_size = os.path.getsize(file_path)
|
|
162
|
+
custom_format = (
|
|
163
|
+
"{desc} [{percentage:3.0f}%] |{bar}| {n_fmt}/{total_fmt} @ {rate_fmt}"
|
|
164
|
+
)
|
|
165
|
+
with tqdm(
|
|
166
|
+
bar_format=custom_format,
|
|
167
|
+
total=file_size,
|
|
168
|
+
unit="B",
|
|
169
|
+
unit_scale=True,
|
|
170
|
+
desc=f"Uploading {build}...",
|
|
171
|
+
) as pbar:
|
|
172
|
+
if not self.upload_file(
|
|
173
|
+
file_path,
|
|
174
|
+
bucket_name,
|
|
175
|
+
object_name,
|
|
176
|
+
Callback=lambda bytes_transferred: pbar.update(bytes_transferred),
|
|
177
|
+
):
|
|
178
|
+
raise ValueError(
|
|
179
|
+
f"Failed to upload file {file_path} to S3 bucket {bucket_name}."
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
# Delete all objects in the "latest" folder
|
|
183
|
+
latest_prefix = f"{model_name}/{version_name}/linux/latest/"
|
|
184
|
+
try:
|
|
185
|
+
response = self.s3_client.list_objects_v2(
|
|
186
|
+
Bucket=bucket_name, Prefix=latest_prefix
|
|
187
|
+
)
|
|
188
|
+
if "Contents" in response:
|
|
189
|
+
for obj in response["Contents"]:
|
|
190
|
+
self.s3_client.delete_object(Bucket=bucket_name, Key=obj["Key"])
|
|
191
|
+
except ClientError as e:
|
|
192
|
+
self.logger.error(f"Error deleting objects in 'latest' folder: {e}")
|
|
193
|
+
raise RuntimeError(f"Failed to clean 'latest' folder in S3: {e}")
|
|
194
|
+
|
|
195
|
+
# Copy the uploaded version file to the "latest" folder
|
|
196
|
+
latest_object_name = f"{model_name}/{version_name}/linux/latest/{build}"
|
|
197
|
+
copy_source = {"Bucket": bucket_name, "Key": object_name}
|
|
144
198
|
try:
|
|
145
|
-
self.s3_client.
|
|
146
|
-
|
|
199
|
+
self.s3_client.copy_object(
|
|
200
|
+
Bucket=bucket_name, CopySource=copy_source, Key=latest_object_name
|
|
147
201
|
)
|
|
202
|
+
except ClientError as e:
|
|
203
|
+
self.logger.error(f"Error copying version file to 'latest' folder: {e}")
|
|
204
|
+
raise RuntimeError(
|
|
205
|
+
f"Failed to copy version file to 'latest' folder in S3: {e}"
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
def download_file(
|
|
209
|
+
self, bucket_name: str, s3_object_key: str, local_file_path: str
|
|
210
|
+
) -> bool:
|
|
211
|
+
"""Downloads a single object from S3 to a local file path."""
|
|
212
|
+
try:
|
|
213
|
+
self.s3_client.download_file(bucket_name, s3_object_key, local_file_path)
|
|
148
214
|
return True
|
|
149
215
|
except ClientError as e:
|
|
150
216
|
self.logger.error(f"ERROR: Failed to download {s3_object_key} from S3: {e}")
|
|
@@ -154,6 +220,7 @@ class AWS:
|
|
|
154
220
|
self,
|
|
155
221
|
repository_id: str,
|
|
156
222
|
cluster_name: str,
|
|
223
|
+
bucket_name: str,
|
|
157
224
|
output_path: str,
|
|
158
225
|
file_list: List[str],
|
|
159
226
|
) -> List[str]:
|
|
@@ -170,7 +237,7 @@ class AWS:
|
|
|
170
237
|
self.logger.info(
|
|
171
238
|
f"Downloading {s3_object_key} to {local_file_path}"
|
|
172
239
|
)
|
|
173
|
-
if self.download_file(s3_object_key, local_file_path):
|
|
240
|
+
if self.download_file(bucket_name, s3_object_key, local_file_path):
|
|
174
241
|
downloaded_files.append(os.path.basename(local_file_path))
|
|
175
242
|
except ClientError as e:
|
|
176
243
|
self.logger.error(f"ERROR: S3 ClientError during download: {e}")
|
|
@@ -182,3 +249,23 @@ class AWS:
|
|
|
182
249
|
raise RuntimeError(f"An unexpected error occurred during S3 download: {e}")
|
|
183
250
|
|
|
184
251
|
return downloaded_files
|
|
252
|
+
|
|
253
|
+
def check_version_build_exists(
|
|
254
|
+
self,
|
|
255
|
+
bucket_name: str,
|
|
256
|
+
model_name: str,
|
|
257
|
+
version_name: str,
|
|
258
|
+
build_id: str,
|
|
259
|
+
) -> bool:
|
|
260
|
+
"""
|
|
261
|
+
Checks if a specific version build exists in the S3 bucket.
|
|
262
|
+
"""
|
|
263
|
+
object_key = f"{model_name}/{version_name}/linux/{build_id}.zip"
|
|
264
|
+
try:
|
|
265
|
+
self.s3_client.head_object(Bucket=bucket_name, Key=object_key)
|
|
266
|
+
return True
|
|
267
|
+
except ClientError as e:
|
|
268
|
+
if e.response["Error"]["Code"] == "404":
|
|
269
|
+
return False
|
|
270
|
+
self.logger.error(f"Error checking version build existence: {e}")
|
|
271
|
+
raise RuntimeError(f"Failed to check version build existence in S3: {e}")
|
psr/cloud/cloud.py
CHANGED
|
@@ -618,7 +618,6 @@ class Client:
|
|
|
618
618
|
"nproc": case.number_of_processes,
|
|
619
619
|
"repositorioId": "0",
|
|
620
620
|
"instanciaTipo": instance_type_id,
|
|
621
|
-
"validacaoModelo": "True",
|
|
622
621
|
"validacaoUsuario": "False",
|
|
623
622
|
"idVersao": case.program_version,
|
|
624
623
|
"modeloVersao": case.program_version_name,
|
|
@@ -810,9 +809,12 @@ class Client:
|
|
|
810
809
|
f.write("")
|
|
811
810
|
else:
|
|
812
811
|
# Download results using Console
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
812
|
+
try:
|
|
813
|
+
xml_content = create_case_xml(parameters)
|
|
814
|
+
self._run_console(xml_content)
|
|
815
|
+
self._logger.info(f"Results downloaded to {output_path}")
|
|
816
|
+
except Exception as e:
|
|
817
|
+
self._logger.error(f"Error downloading results: {e}")
|
|
816
818
|
|
|
817
819
|
def cancel_case(self, case_id: int, wait: bool = False) -> bool:
|
|
818
820
|
parameters = {
|
|
@@ -848,42 +850,59 @@ class Client:
|
|
|
848
850
|
return True
|
|
849
851
|
|
|
850
852
|
def _cases_from_xml(self, xml: ET.Element) -> List["Case"]:
|
|
853
|
+
def get_attribute(fila, key, type_func, default=None, format_str=None):
|
|
854
|
+
value = fila.attrib.get(key)
|
|
855
|
+
try:
|
|
856
|
+
if value is None:
|
|
857
|
+
return default
|
|
858
|
+
if format_str and type_func == datetime.strptime:
|
|
859
|
+
return datetime.strptime(value, format_str)
|
|
860
|
+
return type_func(value)
|
|
861
|
+
except Exception as e:
|
|
862
|
+
if default is None:
|
|
863
|
+
case_id = fila.attrib.get("repositorioId")
|
|
864
|
+
self._logger.error(
|
|
865
|
+
f"Error parsing field '{key}' with value '{value}' for case ID {case_id}: {e}"
|
|
866
|
+
)
|
|
867
|
+
return default
|
|
868
|
+
|
|
851
869
|
instance_type_map = self._get_instance_type_map()
|
|
852
870
|
cases = []
|
|
853
871
|
for fila in xml.findall("Fila"):
|
|
854
872
|
try:
|
|
855
873
|
case = Case(
|
|
856
|
-
name=fila
|
|
874
|
+
name=get_attribute(fila, "nomeCaso", str),
|
|
857
875
|
data_path=None,
|
|
858
|
-
program=fila
|
|
859
|
-
program_version=
|
|
860
|
-
execution_type=
|
|
861
|
-
price_optimized=
|
|
862
|
-
number_of_processes=
|
|
863
|
-
id=
|
|
864
|
-
user=fila
|
|
865
|
-
execution_date=
|
|
866
|
-
fila
|
|
876
|
+
program=get_attribute(fila, "programa", str),
|
|
877
|
+
program_version=get_attribute(fila, "idVersao", int),
|
|
878
|
+
execution_type=get_attribute(fila, "idTipoExecucao", int),
|
|
879
|
+
price_optimized=get_attribute(fila, "flagSpot", bool),
|
|
880
|
+
number_of_processes=get_attribute(fila, "numeroProcesso", int),
|
|
881
|
+
id=get_attribute(fila, "repositorioId", int),
|
|
882
|
+
user=get_attribute(fila, "usuario", str),
|
|
883
|
+
execution_date=get_attribute(
|
|
884
|
+
fila,
|
|
885
|
+
"dataInicio",
|
|
886
|
+
datetime.strptime,
|
|
887
|
+
format_str="%d/%m/%Y %H:%M",
|
|
888
|
+
),
|
|
889
|
+
parent_case_id=get_attribute(
|
|
890
|
+
fila, "repositorioPai", int, default=0
|
|
867
891
|
),
|
|
868
|
-
parent_case_id=int(fila.attrib.get("repositorioPai"))
|
|
869
|
-
if fila.attrib.get("repositorioPai")
|
|
870
|
-
else 0,
|
|
871
892
|
memory_per_process_ratio=(
|
|
872
|
-
instance_type_map[
|
|
873
|
-
if fila
|
|
893
|
+
instance_type_map[get_attribute(fila, "instanciaTipo", int)][0]
|
|
894
|
+
if get_attribute(fila, "instanciaTipo", int)
|
|
895
|
+
in instance_type_map
|
|
874
896
|
else min([value[0] for value in instance_type_map.values()])
|
|
875
897
|
),
|
|
876
|
-
repository_duration=
|
|
877
|
-
budget=fila
|
|
898
|
+
repository_duration=get_attribute(fila, "duracaoRepositorio", int),
|
|
899
|
+
budget=get_attribute(fila, "budget", str),
|
|
878
900
|
)
|
|
879
901
|
cases.append(case)
|
|
880
|
-
except
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
# Optionally, log the error or handle it as needed
|
|
884
|
-
# self._logger.error(f"Error processing case with ID {case_id}: {e}")
|
|
902
|
+
except Exception as e:
|
|
903
|
+
case_id = fila.attrib.get("repositorioId")
|
|
904
|
+
self._logger.error(f"Error processing case with ID {case_id}: {e}")
|
|
885
905
|
|
|
886
|
-
# sort cases by execution date desc
|
|
887
906
|
cases.sort(key=lambda x: x.execution_date, reverse=True)
|
|
888
907
|
return cases
|
|
889
908
|
|
|
@@ -979,6 +998,9 @@ class Client:
|
|
|
979
998
|
if not self._python_client
|
|
980
999
|
else "5.4.0",
|
|
981
1000
|
}
|
|
1001
|
+
if service != "listarFila":
|
|
1002
|
+
parameters["cluster"] = self.cluster["name"]
|
|
1003
|
+
|
|
982
1004
|
if additional_arguments:
|
|
983
1005
|
parameters.update(additional_arguments)
|
|
984
1006
|
|
|
@@ -1023,6 +1045,16 @@ class Client:
|
|
|
1023
1045
|
)
|
|
1024
1046
|
return self._cloud_clusters_xml_cache
|
|
1025
1047
|
|
|
1048
|
+
def _get_upload_filter(self, parameters, category: str) -> str:
|
|
1049
|
+
filter_request_result = self._make_soap_request(
|
|
1050
|
+
"obterFiltros", additional_arguments=parameters
|
|
1051
|
+
)
|
|
1052
|
+
upload_filter = filter_request_result.find(
|
|
1053
|
+
f"./Parametro[@nome='{category}']"
|
|
1054
|
+
).text
|
|
1055
|
+
upload_filter = "^[a-zA-Z0-9./_]*(" + upload_filter + ")$"
|
|
1056
|
+
return upload_filter
|
|
1057
|
+
|
|
1026
1058
|
def _execute_case(self, case_dict) -> int:
|
|
1027
1059
|
"""
|
|
1028
1060
|
Execute a case on the PSR Cloud.
|
|
@@ -1032,13 +1064,8 @@ class Client:
|
|
|
1032
1064
|
case_dict["programa"] = case_dict["modelo"]
|
|
1033
1065
|
case_dict["numeroProcessos"] = case_dict["nproc"]
|
|
1034
1066
|
case_dict["versao_cliente"] = "5.4.0"
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
)
|
|
1038
|
-
upload_filter = filter_request_result.find(
|
|
1039
|
-
"./Parametro[@nome='filtroUpload']"
|
|
1040
|
-
).text
|
|
1041
|
-
upload_filter = "^[a-zA-Z0-9./_]*(" + upload_filter + ")$"
|
|
1067
|
+
|
|
1068
|
+
upload_filter = self._get_upload_filter(case_dict, category="filtroUpload")
|
|
1042
1069
|
|
|
1043
1070
|
# Create Repository
|
|
1044
1071
|
self._logger.info("Creating remote repository")
|
|
@@ -1081,7 +1108,9 @@ class Client:
|
|
|
1081
1108
|
# Filtering files to upload
|
|
1082
1109
|
self._logger.info("Checking list of files to send")
|
|
1083
1110
|
|
|
1084
|
-
file_list = _filter_upload_files(
|
|
1111
|
+
file_list = self._filter_upload_files(
|
|
1112
|
+
case_dict["diretorioDados"], upload_filter
|
|
1113
|
+
)
|
|
1085
1114
|
|
|
1086
1115
|
if not file_list:
|
|
1087
1116
|
self._logger.warning(
|
|
@@ -1265,12 +1294,28 @@ class Client:
|
|
|
1265
1294
|
with open(file_path, "rb") as f_check:
|
|
1266
1295
|
return f_check.read(2) == b"\x1f\x8b"
|
|
1267
1296
|
except IOError:
|
|
1268
|
-
|
|
1269
|
-
print(
|
|
1297
|
+
self._logger.warning(
|
|
1270
1298
|
f"WARNING: Could not read {file_path} to check for gzip magic number."
|
|
1271
1299
|
)
|
|
1272
1300
|
return False
|
|
1273
1301
|
|
|
1302
|
+
def _filter_upload_files(self, directory: str, upload_filter: str) -> List[str]:
|
|
1303
|
+
"""
|
|
1304
|
+
Filter files in a directory based on the upload filter.
|
|
1305
|
+
:param directory: Directory to filter files from.
|
|
1306
|
+
:param upload_filter: Regular expression filter for file names.
|
|
1307
|
+
:return: List of filtered file paths.
|
|
1308
|
+
"""
|
|
1309
|
+
if not os.path.exists(directory):
|
|
1310
|
+
raise CloudInputError(f"Directory {directory} does not exist")
|
|
1311
|
+
|
|
1312
|
+
regex = re.compile(upload_filter)
|
|
1313
|
+
filtered_files = []
|
|
1314
|
+
for file in os.listdir(directory):
|
|
1315
|
+
if regex.match(file):
|
|
1316
|
+
filtered_files.append(os.path.join(directory, file))
|
|
1317
|
+
return filtered_files
|
|
1318
|
+
|
|
1274
1319
|
def _decompress_gzipped_file(self, gzipped_file_path: str) -> str:
|
|
1275
1320
|
"""
|
|
1276
1321
|
Decompresses a gzipped file.
|
|
@@ -1300,13 +1345,13 @@ class Client:
|
|
|
1300
1345
|
os.rename(temp_decompressed_path, decompressed_target_path)
|
|
1301
1346
|
return decompressed_target_path
|
|
1302
1347
|
except (gzip.BadGzipFile, EOFError, IOError) as e:
|
|
1303
|
-
|
|
1348
|
+
self._logger.warning(
|
|
1304
1349
|
f"ERROR: Failed to decompress {gzipped_file_path}: {e}. Original file kept."
|
|
1305
1350
|
)
|
|
1306
1351
|
except (
|
|
1307
1352
|
Exception
|
|
1308
1353
|
) as e: # Catch other errors like permission issues during rename/remove
|
|
1309
|
-
|
|
1354
|
+
self._logger.warning(
|
|
1310
1355
|
f"ERROR: Error during post-decompression file operations for {gzipped_file_path}: {e}. Original file kept."
|
|
1311
1356
|
)
|
|
1312
1357
|
finally:
|
|
@@ -1432,24 +1477,6 @@ def _budget_matches_list(budget_part: str, all_budgets: List[str]) -> List[str]:
|
|
|
1432
1477
|
return [budget for budget in all_budgets if lowered_budget_part in budget.lower()]
|
|
1433
1478
|
|
|
1434
1479
|
|
|
1435
|
-
def _filter_upload_files(directory: str, upload_filter: str) -> List[str]:
|
|
1436
|
-
"""
|
|
1437
|
-
Filter files in a directory based on the upload filter.
|
|
1438
|
-
:param directory: Directory to filter files from.
|
|
1439
|
-
:param upload_filter: Regular expression filter for file names.
|
|
1440
|
-
:return: List of filtered file paths.
|
|
1441
|
-
"""
|
|
1442
|
-
if not os.path.exists(directory):
|
|
1443
|
-
raise CloudInputError(f"Directory {directory} does not exist")
|
|
1444
|
-
|
|
1445
|
-
regex = re.compile(upload_filter)
|
|
1446
|
-
filtered_files = []
|
|
1447
|
-
for file in os.listdir(directory):
|
|
1448
|
-
if regex.match(file):
|
|
1449
|
-
filtered_files.append(os.path.join(directory, file))
|
|
1450
|
-
return filtered_files
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
1480
|
def replace_case_str_values(client: Client, case: Case) -> Case:
|
|
1454
1481
|
"""Create a new case object using internal integer IDs instead of string values."""
|
|
1455
1482
|
# Model Version
|
psr/cloud/version.py
CHANGED
psr/execqueue/config.py
CHANGED
psr/execqueue/server.py
CHANGED
|
@@ -403,7 +403,7 @@ if __name__ == '__main__':
|
|
|
403
403
|
print("Starting server...")
|
|
404
404
|
session = initialize_db()
|
|
405
405
|
try:
|
|
406
|
-
app.run(debug=FLASK_DEBUG,
|
|
406
|
+
app.run(host=settings.get("host", DEFAULT_HOST), debug=FLASK_DEBUG,
|
|
407
407
|
port=settings.get("port", DEFAULT_PORT),
|
|
408
408
|
threaded=True,
|
|
409
409
|
use_reloader=False,)
|
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", "
|
|
15
|
+
SLEEP_SECONDS = int(os.getenv("WATCHER_SLEEP", "10"))
|
|
16
16
|
DB_PATH = os.getenv("WATCHER_DB_PATH", "watcher.sqlite")
|
|
17
17
|
|
|
18
18
|
|
psr/factory/__init__.py
CHANGED
psr/factory/factory.dll
CHANGED
|
Binary file
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: psr-factory
|
|
3
|
-
Version: 5.0.
|
|
3
|
+
Version: 5.0.0b36
|
|
4
4
|
Summary: PSR database management module.
|
|
5
5
|
Author-email: "PSR Inc." <psrfactory@psr-inc.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -33,6 +33,7 @@ Requires-Dist: filelock; extra == "cloud"
|
|
|
33
33
|
Requires-Dist: pefile; extra == "cloud"
|
|
34
34
|
Requires-Dist: boto3; extra == "cloud"
|
|
35
35
|
Requires-Dist: botocore; extra == "cloud"
|
|
36
|
+
Requires-Dist: tqdm; extra == "cloud"
|
|
36
37
|
Provides-Extra: execqueue-client
|
|
37
38
|
Requires-Dist: requests; extra == "execqueue-client"
|
|
38
39
|
Provides-Extra: execqueue-server
|
|
@@ -55,3 +56,69 @@ Requires-Dist: pefile; extra == "all"
|
|
|
55
56
|
Requires-Dist: boto3; extra == "all"
|
|
56
57
|
Requires-Dist: botocore; extra == "all"
|
|
57
58
|
Dynamic: license-file
|
|
59
|
+
|
|
60
|
+
PSR Factory (version 4.0.40)
|
|
61
|
+
============================
|
|
62
|
+
|
|
63
|
+
Factory is a library that helps to manage SDDP cases.
|
|
64
|
+
It contains functions that create, load, and save studies, and also functions that create,
|
|
65
|
+
access, and modify objects in a study.
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
Installation
|
|
69
|
+
------------
|
|
70
|
+
|
|
71
|
+
### System-wide installation
|
|
72
|
+
|
|
73
|
+
Open the command prompt and run the following command:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
pip install psr_factory-4.0.40-py3-none-win_amd64.whl
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Factory will be available to all Python scripts in your system after importing it:
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
import psr.factory
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Local/project-specific usage
|
|
86
|
+
|
|
87
|
+
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:
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
import sys
|
|
91
|
+
sys.path.append(r"C:\path\to\factory")
|
|
92
|
+
import psr.factory
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
Usage sample
|
|
97
|
+
------------
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
import psr.factory
|
|
101
|
+
|
|
102
|
+
study = psr.factory.load_study(r"C:\temp\my\study")
|
|
103
|
+
system_1 = study.find("System.*")[0]
|
|
104
|
+
|
|
105
|
+
battery = psr.factory.create("Battery")
|
|
106
|
+
battery.code = 1
|
|
107
|
+
battery.name = "Battery 1"
|
|
108
|
+
battery.set("InstalledCapacity", 10.0)
|
|
109
|
+
battery.set("RefSystem", system_1)
|
|
110
|
+
study.add(battery)
|
|
111
|
+
|
|
112
|
+
study.save(r"C:\temp\my\updated_study")
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
Full documentation
|
|
117
|
+
------------------
|
|
118
|
+
|
|
119
|
+
The full documentation and reference is available at [https://docs.psr-inc.com/factory/](https://docs.psr-inc.com/manual/factory/).
|
|
120
|
+
|
|
121
|
+
Releases
|
|
122
|
+
--------
|
|
123
|
+
|
|
124
|
+
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).
|
|
@@ -2,23 +2,23 @@ psr/apps/__init__.py,sha256=frSq1WIy5vIdU21xJIGX7U3XoAZRj0pcQmFb-R00b7I,228
|
|
|
2
2
|
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
|
-
psr/cloud/aws.py,sha256=
|
|
6
|
-
psr/cloud/cloud.py,sha256=
|
|
5
|
+
psr/cloud/aws.py,sha256=lpfaP2qUq5s7Gffb-k2jwyCP00BhvbB13y1nTTvM1dU,10249
|
|
6
|
+
psr/cloud/cloud.py,sha256=4NpJkVriVJHuBVDi8ubezcQ835vPfWTTbPpG_BBsDfE,61575
|
|
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
|
|
10
10
|
psr/cloud/status.py,sha256=vcI4B9S6wCt9maT5NNrVwYaEgGIvy6kkC1UVpJjYbtw,3607
|
|
11
11
|
psr/cloud/tempfile.py,sha256=1IOeye0eKWnmBynK5K5FMWiTaEVhn4GbQ8_y0THEva0,3893
|
|
12
|
-
psr/cloud/version.py,sha256
|
|
12
|
+
psr/cloud/version.py,sha256=-oC5DNaS_iYTfpsusfmeG-WGktZ5b-x8xT-4zszWvz8,193
|
|
13
13
|
psr/cloud/xml.py,sha256=ac2lyflOQm8khPvJn0zmI26I4sfUDY6A_OTsxzbMQEs,1896
|
|
14
14
|
psr/execqueue/client.py,sha256=P89Yt76W2GqRXaG_MLsa0kXf0jPp-weBd3aSTRcDzcs,4443
|
|
15
|
-
psr/execqueue/config.py,sha256=
|
|
15
|
+
psr/execqueue/config.py,sha256=rUOzO5dtTkwWoZlZfk06K9RE94xCx53T1bJ1h5JaDUo,1446
|
|
16
16
|
psr/execqueue/db.py,sha256=sNr_StNEgZZQCKcyCWiB1WrQJIhE9UvLUxPA2tWiXGs,8498
|
|
17
|
-
psr/execqueue/server.py,sha256=
|
|
18
|
-
psr/execqueue/watcher.py,sha256=
|
|
19
|
-
psr/factory/__init__.py,sha256=
|
|
17
|
+
psr/execqueue/server.py,sha256=LolYERWRt96P_ip4yKU7DsN7M_n9d_pbflbT0ckUV0E,15782
|
|
18
|
+
psr/execqueue/watcher.py,sha256=R1dyXJ-OYn_QjqdItBwbLJZQ2LcbtdHqnRaYkyphi4w,5637
|
|
19
|
+
psr/factory/__init__.py,sha256=lItGdpqHejAKmFze9F9LK5wf2reJToeK9ZEKvke6WaE,219
|
|
20
20
|
psr/factory/api.py,sha256=QASwrk5SbbAqz63u7EhGoBBqqXOqMnicjL-eJ3gOGe0,104270
|
|
21
|
-
psr/factory/factory.dll,sha256=
|
|
21
|
+
psr/factory/factory.dll,sha256=960_HytvI81_q4jM0wSyIkE8iosfPPOl96NHzP-rNDw,18362192
|
|
22
22
|
psr/factory/factory.pmd,sha256=kr5xf2knYu_SJeyCsmoyYVgFwd4-VURi28rno40GIRY,250936
|
|
23
23
|
psr/factory/factory.pmk,sha256=OvpqDnaCc1eeOWGQxogD0Nbg9M0PE1UZPcD65PeePV8,580337
|
|
24
24
|
psr/factory/factorylib.py,sha256=o5Irbw6k-yIOJVUtDu2YYqw2x16P2LmCdouImwSssdw,28290
|
|
@@ -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=hCVH62HAZK_M9YUiHQgqCkMevN17utegjfRIw49MdvM,27542
|
|
35
35
|
psr/runner/version.py,sha256=mch2Y8anSXGMn9w72Z78PhSRhOyn55EwaoLAYhY4McE,194
|
|
36
|
-
psr_factory-5.0.
|
|
37
|
-
psr_factory-5.0.
|
|
38
|
-
psr_factory-5.0.
|
|
39
|
-
psr_factory-5.0.
|
|
40
|
-
psr_factory-5.0.
|
|
36
|
+
psr_factory-5.0.0b36.dist-info/licenses/LICENSE.txt,sha256=N6mqZK2Ft3iXGHj-by_MHC_dJo9qwn0URjakEPys3H4,1089
|
|
37
|
+
psr_factory-5.0.0b36.dist-info/METADATA,sha256=rKr2yS66SWjgNP54XAv_ed7aIL83LeecoBO8TgIlPpk,3996
|
|
38
|
+
psr_factory-5.0.0b36.dist-info/WHEEL,sha256=ZjXRCNaQ9YSypEK2TE0LRB0sy2OVXSszb4Sx1XjM99k,97
|
|
39
|
+
psr_factory-5.0.0b36.dist-info/top_level.txt,sha256=Jb393O96WQk3b5D1gMcrZBLKJJgZpzNjTPoldUi00ck,4
|
|
40
|
+
psr_factory-5.0.0b36.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|