ras-commander 0.64.0__py3-none-any.whl → 0.66.0__py3-none-any.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.
ras_commander/RasPrj.py CHANGED
@@ -160,93 +160,96 @@ class RasPrj:
160
160
  Load project data from the HEC-RAS project file.
161
161
 
162
162
  This method initializes DataFrames for plan, flow, unsteady, and geometry entries
163
- by calling the _get_prj_entries method for each entry type.
164
- Also extracts unsteady_number and geometry_number from plan files and adds them to plan_df.
163
+ and ensures all required columns are present with appropriate paths.
165
164
  """
166
- # Load unsteady first to ensure consistent handling of unsteady numbers
167
- self.unsteady_df = self._get_prj_entries('Unsteady')
168
- self.plan_df = self._get_prj_entries('Plan')
169
- self.flow_df = self._get_prj_entries('Flow')
170
- self.geom_df = self.get_geom_entries()
165
+ try:
166
+ # Load data frames
167
+ self.unsteady_df = self._get_prj_entries('Unsteady')
168
+ self.plan_df = self._get_prj_entries('Plan')
169
+ self.flow_df = self._get_prj_entries('Flow')
170
+ self.geom_df = self.get_geom_entries()
171
+
172
+ # Ensure required columns exist
173
+ self._ensure_required_columns()
174
+
175
+ # Set paths for geometry and flow files
176
+ self._set_file_paths()
177
+
178
+ except Exception as e:
179
+ logger.error(f"Error loading project data: {e}")
180
+ raise
181
+
182
+ def _ensure_required_columns(self):
183
+ """Ensure all required columns exist in plan_df."""
184
+ required_columns = [
185
+ 'plan_number', 'unsteady_number', 'geometry_number',
186
+ 'Geom File', 'Geom Path', 'Flow File', 'Flow Path', 'full_path'
187
+ ]
171
188
 
172
- # Initialize Geom_File column
173
- self.plan_df['Geom_File'] = None
189
+ for col in required_columns:
190
+ if col not in self.plan_df.columns:
191
+ self.plan_df[col] = None
174
192
 
175
- # Set geometry HDF paths
193
+ if not self.plan_df['full_path'].any():
194
+ self.plan_df['full_path'] = self.plan_df['plan_number'].apply(
195
+ lambda x: str(self.project_folder / f"{self.project_name}.p{x}")
196
+ )
197
+
198
+ def _set_file_paths(self):
199
+ """Set geometry and flow paths in plan_df."""
176
200
  for idx, row in self.plan_df.iterrows():
177
201
  try:
178
- plan_file_path = row['full_path']
179
- geom_number, geom_hdf_path = self._get_geom_file_from_plan(plan_file_path)
180
- if geom_number:
181
- self.plan_df.at[idx, 'Geom_File'] = geom_hdf_path
182
- if not self.suppress_logging:
183
- logger.info(f"Plan {row['plan_number']} uses geometry file {geom_number}")
202
+ self._set_geom_path(idx, row)
203
+ self._set_flow_path(idx, row)
204
+
205
+ if not self.suppress_logging:
206
+ logger.info(f"Plan {row['plan_number']} paths set up")
184
207
  except Exception as e:
185
208
  logger.error(f"Error processing plan file {row['plan_number']}: {e}")
186
209
 
187
- def _get_geom_file_from_plan(self, plan_file_path):
188
- """
189
- Extract the geometry number from a plan file by finding the Geom File value
190
- and stripping the leading 'g'.
191
-
192
- Parameters:
193
- -----------
194
- plan_file_path : str or Path
195
- Path to the plan file.
196
-
197
- Returns:
198
- --------
199
- tuple: (str, str)
200
- A tuple containing (geometry_number, full_hdf_path) or (None, None) if not found.
201
- geometry_number is the number after 'g' in the Geom File value
202
- full_hdf_path is the path to the geometry HDF file
203
- """
204
- content, encoding = read_file_with_fallback_encoding(plan_file_path)
205
-
206
- if content is None:
207
- return None, None
208
-
209
- try:
210
- match = re.search(r'Geom File=g(\d+)', content)
211
- if match:
212
- geom_number = match.group(1) # This gets just the number after 'g'
213
- geom_file = f"g{geom_number}"
214
- geom_hdf_path = self.project_folder / f"{self.project_name}.{geom_file}.hdf"
215
- if geom_hdf_path.exists():
216
- return geom_number, str(geom_hdf_path)
217
- except Exception as e:
218
- logger.error(f"Error extracting geometry number from {plan_file_path}: {e}")
219
-
220
- return None, None
210
+ def _set_geom_path(self, idx: int, row: pd.Series):
211
+ """Set geometry path for a plan entry."""
212
+ if pd.notna(row['Geom File']):
213
+ geom_path = self.project_folder / f"{self.project_name}.g{row['Geom File']}"
214
+ self.plan_df.at[idx, 'Geom Path'] = str(geom_path)
221
215
 
222
- def _get_flow_file_from_plan(self, plan_file_path):
216
+ def _set_flow_path(self, idx: int, row: pd.Series):
217
+ """Set flow path for a plan entry."""
218
+ if pd.notna(row['Flow File']):
219
+ prefix = 'u' if pd.notna(row['unsteady_number']) else 'f'
220
+ flow_path = self.project_folder / f"{self.project_name}.{prefix}{row['Flow File']}"
221
+ self.plan_df.at[idx, 'Flow Path'] = str(flow_path)
222
+
223
+ def _get_geom_file_for_plan(self, plan_number):
223
224
  """
224
- Extract the Flow File value from a plan file.
225
+ Get the geometry file path for a given plan number.
225
226
 
226
- Parameters:
227
- -----------
228
- plan_file_path : str or Path
229
- Path to the plan file.
227
+ Args:
228
+ plan_number (str): The plan number to find the geometry file for.
230
229
 
231
230
  Returns:
232
- --------
233
- str or None
234
- The Flow File value or None if not found.
231
+ str: The full path to the geometry HDF file, or None if not found.
235
232
  """
233
+ plan_file_path = self.project_folder / f"{self.project_name}.p{plan_number}"
236
234
  content, encoding = read_file_with_fallback_encoding(plan_file_path)
237
235
 
238
236
  if content is None:
239
237
  return None
240
238
 
241
239
  try:
242
- match = re.search(r'Flow File=([^\s]+)', content)
243
- if match:
244
- return match.group(1)
240
+ for line in content.splitlines():
241
+ if line.startswith("Geom File="):
242
+ geom_file = line.strip().split('=')[1]
243
+ geom_hdf_path = self.project_folder / f"{self.project_name}.{geom_file}.hdf"
244
+ if geom_hdf_path.exists():
245
+ return str(geom_hdf_path)
246
+ else:
247
+ return None
245
248
  except Exception as e:
246
- logger.error(f"Error extracting Flow File from {plan_file_path}: {e}")
247
-
249
+ logger.error(f"Error reading plan file for geometry: {e}")
248
250
  return None
249
251
 
252
+
250
253
  @staticmethod
251
254
  @log_call
252
255
  def get_plan_value(
@@ -431,80 +434,106 @@ class RasPrj:
431
434
 
432
435
  Returns:
433
436
  pd.DataFrame: A DataFrame containing the extracted entries.
437
+
438
+ Raises:
439
+ Exception: If there's an error reading or processing the project file.
434
440
  """
435
441
  entries = []
436
442
  pattern = re.compile(rf"{entry_type} File=(\w+)")
437
443
 
438
444
  try:
439
- with open(self.prj_file, 'r') as file:
445
+ with open(self.prj_file, 'r', encoding='utf-8') as file:
440
446
  for line in file:
441
447
  match = pattern.match(line.strip())
442
448
  if match:
443
449
  file_name = match.group(1)
444
450
  full_path = str(self.project_folder / f"{self.project_name}.{file_name}")
445
- entry_number = file_name[1:] # Extract number portion without prefix
451
+ entry_number = file_name[1:]
446
452
 
447
453
  entry = {
448
454
  f'{entry_type.lower()}_number': entry_number,
449
455
  'full_path': full_path
450
456
  }
451
457
 
458
+ # Handle Unsteady entries
452
459
  if entry_type == 'Unsteady':
453
- entry['unsteady_number'] = entry_number
454
- unsteady_info = self._parse_unsteady_file(Path(full_path))
455
- entry.update(unsteady_info)
460
+ entry.update(self._process_unsteady_entry(entry_number, full_path))
456
461
  else:
457
- entry.update({
458
- 'unsteady_number': None,
459
- 'geometry_number': None,
460
- 'Short Identifier': None,
461
- 'Simulation Date': None
462
- })
462
+ entry.update(self._process_default_entry())
463
463
 
464
+ # Handle Plan entries
464
465
  if entry_type == 'Plan':
465
- plan_info = self._parse_plan_file(Path(full_path))
466
- if plan_info:
467
- # Handle Flow File (unsteady) number
468
- flow_file = plan_info.get('Flow File')
469
- if flow_file and flow_file.startswith('u'):
470
- entry['unsteady_number'] = flow_file[1:]
471
- else:
472
- entry['unsteady_number'] = flow_file
473
-
474
- # Handle Geom File number
475
- geom_file = plan_info.get('Geom File')
476
- if geom_file and geom_file.startswith('g'):
477
- entry['geometry_number'] = geom_file[1:]
478
- else:
479
- entry['geometry_number'] = geom_file
480
-
481
- entry['Short Identifier'] = plan_info.get('Short Identifier')
482
- entry['Simulation Date'] = plan_info.get('Simulation Date')
483
-
484
- # Update remaining fields
485
- for key, value in plan_info.items():
486
- if key not in ['unsteady_number', 'geometry_number', 'Short Identifier',
487
- 'Simulation Date', 'Flow File', 'Geom File']:
488
- entry[key] = value
466
+ entry.update(self._process_plan_entry(entry_number, full_path))
489
467
 
490
- # Add HDF results path
491
- hdf_results_path = self.project_folder / f"{self.project_name}.p{entry_number}.hdf"
492
- entry['HDF_Results_Path'] = str(hdf_results_path) if hdf_results_path.exists() else None
493
-
494
468
  entries.append(entry)
495
-
496
- df = pd.DataFrame(entries)
497
-
498
- if not df.empty and entry_type == 'Plan':
499
- first_cols = [f'{entry_type.lower()}_number', 'unsteady_number', 'geometry_number',
500
- 'Short Identifier', 'Simulation Date']
501
- other_cols = [col for col in df.columns if col not in first_cols]
502
- df = df[first_cols + other_cols]
503
469
 
504
- return df
470
+ df = pd.DataFrame(entries)
471
+ return self._format_dataframe(df, entry_type)
472
+
505
473
  except Exception as e:
474
+ logger.error(f"Error in _get_prj_entries for {entry_type}: {e}")
506
475
  raise
507
476
 
477
+ def _process_unsteady_entry(self, entry_number: str, full_path: str) -> dict:
478
+ """Process unsteady entry data."""
479
+ entry = {'unsteady_number': entry_number}
480
+ unsteady_info = self._parse_unsteady_file(Path(full_path))
481
+ entry.update(unsteady_info)
482
+ return entry
483
+
484
+ def _process_default_entry(self) -> dict:
485
+ """Process default entry data."""
486
+ return {
487
+ 'unsteady_number': None,
488
+ 'geometry_number': None
489
+ }
490
+
491
+ def _process_plan_entry(self, entry_number: str, full_path: str) -> dict:
492
+ """Process plan entry data."""
493
+ entry = {}
494
+ plan_info = self._parse_plan_file(Path(full_path))
495
+
496
+ if plan_info:
497
+ entry.update(self._process_flow_file(plan_info))
498
+ entry.update(self._process_geom_file(plan_info))
499
+
500
+ # Add remaining plan info
501
+ for key, value in plan_info.items():
502
+ if key not in ['Flow File', 'Geom File']:
503
+ entry[key] = value
504
+
505
+ # Add HDF results path
506
+ hdf_results_path = self.project_folder / f"{self.project_name}.p{entry_number}.hdf"
507
+ entry['HDF_Results_Path'] = str(hdf_results_path) if hdf_results_path.exists() else None
508
+
509
+ return entry
510
+
511
+ def _process_flow_file(self, plan_info: dict) -> dict:
512
+ """Process flow file information from plan info."""
513
+ flow_file = plan_info.get('Flow File')
514
+ if flow_file and flow_file.startswith('u'):
515
+ return {
516
+ 'unsteady_number': flow_file[1:],
517
+ 'Flow File': flow_file[1:]
518
+ }
519
+ return {
520
+ 'unsteady_number': None,
521
+ 'Flow File': flow_file[1:] if flow_file and flow_file.startswith('f') else None
522
+ }
523
+
524
+ def _process_geom_file(self, plan_info: dict) -> dict:
525
+ """Process geometry file information from plan info."""
526
+ geom_file = plan_info.get('Geom File')
527
+ if geom_file and geom_file.startswith('g'):
528
+ return {
529
+ 'geometry_number': geom_file[1:],
530
+ 'Geom File': geom_file[1:]
531
+ }
532
+ return {
533
+ 'geometry_number': None,
534
+ 'Geom File': None
535
+ }
536
+
508
537
  def _parse_unsteady_file(self, unsteady_file_path):
509
538
  """
510
539
  Parse an unsteady flow file and extract critical information.
@@ -895,27 +924,135 @@ class RasPrj:
895
924
  return bc_info, unparsed_lines
896
925
 
897
926
  @log_call
898
- def get_unsteady_numbers_from_plans(self):
927
+ def _format_dataframe(self, df, entry_type):
899
928
  """
900
- Get all plans that use unsteady flow files.
929
+ Format the DataFrame according to the desired column structure.
930
+
931
+ Args:
932
+ df (pd.DataFrame): The DataFrame to format.
933
+ entry_type (str): The type of entry (e.g., 'Plan', 'Flow', 'Unsteady', 'Geom').
901
934
 
902
935
  Returns:
903
- --------
904
- pd.DataFrame
905
- A DataFrame containing only plan entries that use unsteady flow files.
936
+ pd.DataFrame: The formatted DataFrame.
937
+ """
938
+ if df.empty:
939
+ return df
906
940
 
907
- Raises:
908
- -------
909
- RuntimeError: If the project has not been initialized.
941
+ if entry_type == 'Plan':
942
+ # Define column groups
943
+ first_cols = ['plan_number', 'unsteady_number', 'geometry_number']
944
+ plan_key_cols = [
945
+ 'Plan Title', 'Program Version', 'Short Identifier', 'Simulation Date',
946
+ 'Computation Interval', 'Mapping Interval', 'Run HTab', 'Run UNet',
947
+ 'Run Sediment', 'Run PostProcess', 'Run WQNet', 'UNET Use Existing IB Tables',
948
+ 'HDF_Results_Path', 'UNET 1D Methodology'
949
+ ]
950
+ file_path_cols = ['Geom File', 'Geom Path', 'Flow File', 'Flow Path']
951
+
952
+ # Build column list
953
+ all_cols = first_cols.copy()
954
+ all_cols.extend([col for col in plan_key_cols if col in df.columns])
955
+ all_cols.extend([col for col in df.columns if col not in all_cols + file_path_cols + ['full_path']])
956
+ all_cols.extend(file_path_cols)
957
+
958
+ # Rename and fill missing columns
959
+ df = df.rename(columns={f'{entry_type.lower()}_number': 'plan_number'})
960
+ for col in all_cols:
961
+ if col not in df.columns:
962
+ df[col] = None
963
+
964
+ # Add full_path if present
965
+ if 'full_path' in df.columns:
966
+ all_cols.append('full_path')
967
+
968
+ return df[[col for col in all_cols if col in df.columns]]
969
+
970
+ return df
971
+
972
+ @log_call
973
+ def _get_prj_entries(self, entry_type):
910
974
  """
911
- self.check_initialized()
975
+ Extract entries of a specific type from the HEC-RAS project file.
976
+ """
977
+ entries = []
978
+ pattern = re.compile(rf"{entry_type} File=(\w+)")
979
+
980
+ try:
981
+ with open(self.prj_file, 'r') as file:
982
+ for line in file:
983
+ match = pattern.match(line.strip())
984
+ if match:
985
+ file_name = match.group(1)
986
+ full_path = str(self.project_folder / f"{self.project_name}.{file_name}")
987
+ entry = self._create_entry(entry_type, file_name, full_path)
988
+ entries.append(entry)
912
989
 
913
- # Filter plan_df to only include plans with unsteady_number not None
914
- unsteady_plans = self.plan_df[self.plan_df['unsteady_number'].notna()].copy()
990
+ return self._format_dataframe(pd.DataFrame(entries), entry_type)
915
991
 
916
- logger.info(f"Found {len(unsteady_plans)} plans using unsteady flow files")
992
+ except Exception as e:
993
+ logger.error(f"Error in _get_prj_entries for {entry_type}: {e}")
994
+ raise
995
+
996
+ def _create_entry(self, entry_type, file_name, full_path):
997
+ """Helper method to create entry dictionary."""
998
+ entry_number = file_name[1:]
999
+ entry = {
1000
+ f'{entry_type.lower()}_number': entry_number,
1001
+ 'full_path': full_path,
1002
+ 'unsteady_number': None,
1003
+ 'geometry_number': None
1004
+ }
1005
+
1006
+ if entry_type == 'Unsteady':
1007
+ entry['unsteady_number'] = entry_number
1008
+ entry.update(self._parse_unsteady_file(Path(full_path)))
1009
+ elif entry_type == 'Plan':
1010
+ self._update_plan_entry(entry, entry_number, full_path)
917
1011
 
918
- return unsteady_plans
1012
+ return entry
1013
+
1014
+ def _update_plan_entry(self, entry, entry_number, full_path):
1015
+ """Helper method to update plan entry with additional information."""
1016
+ plan_info = self._parse_plan_file(Path(full_path))
1017
+ if plan_info:
1018
+ # Handle Flow File
1019
+ flow_file = plan_info.get('Flow File')
1020
+ if flow_file:
1021
+ if flow_file.startswith('u'):
1022
+ entry.update({'unsteady_number': flow_file[1:], 'Flow File': flow_file[1:]})
1023
+ else:
1024
+ entry['Flow File'] = flow_file[1:] if flow_file.startswith('f') else None
1025
+
1026
+ # Handle Geom File
1027
+ geom_file = plan_info.get('Geom File')
1028
+ if geom_file and geom_file.startswith('g'):
1029
+ entry.update({'geometry_number': geom_file[1:], 'Geom File': geom_file[1:]})
1030
+
1031
+ # Add remaining plan info
1032
+ entry.update({k: v for k, v in plan_info.items() if k not in ['Flow File', 'Geom File']})
1033
+
1034
+ # Add HDF results path
1035
+ hdf_path = self.project_folder / f"{self.project_name}.p{entry_number}.hdf"
1036
+ entry['HDF_Results_Path'] = str(hdf_path) if hdf_path.exists() else None
1037
+
1038
+ def _set_plan_paths(self):
1039
+ """Helper method to set paths in plan_df."""
1040
+ if not self.plan_df['full_path'].any():
1041
+ self.plan_df['full_path'] = self.plan_df['plan_number'].apply(
1042
+ lambda x: str(self.project_folder / f"{self.project_name}.p{x}")
1043
+ )
1044
+
1045
+ for idx, row in self.plan_df.iterrows():
1046
+ if pd.notna(row['Geom File']) and pd.isna(row.get('Geom Path')):
1047
+ self.plan_df.at[idx, 'Geom Path'] = str(self.project_folder / f"{self.project_name}.g{row['Geom File']}")
1048
+
1049
+ if pd.notna(row['Flow File']) and pd.isna(row.get('Flow Path')):
1050
+ prefix = 'u' if pd.notna(row['unsteady_number']) else 'f'
1051
+ self.plan_df.at[idx, 'Flow Path'] = str(self.project_folder / f"{self.project_name}.{prefix}{row['Flow File']}")
1052
+
1053
+ if not self.suppress_logging:
1054
+ logger.info(f"Plan {row['plan_number']} paths set up")
1055
+
919
1056
 
920
1057
  # Create a global instance named 'ras'
921
1058
  # Defining the global instance allows the init_ras_project function to initialize the project.
@@ -987,7 +1124,7 @@ def get_ras_exe(ras_version=None):
987
1124
  Args:
988
1125
  ras_version (str, optional): Either a version number or a full path to the HEC-RAS executable.
989
1126
  If None, the function will first check the global 'ras' object for a path.
990
- If the global 'ras' object is not initialized or doesn't have a path, a default path will be used.
1127
+ or a default path.
991
1128
 
992
1129
  Returns:
993
1130
  str: The full path to the HEC-RAS executable.
ras_commander/RasUtils.py CHANGED
@@ -216,30 +216,49 @@ class RasUtils:
216
216
  Returns:
217
217
  Path: Full path to the plan file
218
218
 
219
+ Raises:
220
+ ValueError: If plan number is not between 1 and 99
221
+ TypeError: If input type is invalid
222
+ FileNotFoundError: If the plan file does not exist
223
+
219
224
  Example:
220
225
  >>> plan_path = RasUtils.get_plan_path(1)
221
226
  >>> print(f"Plan file path: {plan_path}")
222
227
  >>> plan_path = RasUtils.get_plan_path("path/to/plan.p01")
223
228
  >>> print(f"Plan file path: {plan_path}")
224
229
  """
225
-
230
+ # Validate RAS object
226
231
  ras_obj = ras_object or ras
227
232
  ras_obj.check_initialized()
228
233
 
234
+ # Handle direct file path input
229
235
  plan_path = Path(current_plan_number_or_path)
230
236
  if plan_path.is_file():
231
237
  logger.info(f"Using provided plan file path: {plan_path}")
232
238
  return plan_path
233
239
 
240
+ # Handle plan number input
234
241
  try:
235
- current_plan_number = f"{int(current_plan_number_or_path):02d}" # Ensure two-digit format
242
+ plan_num = int(current_plan_number_or_path)
243
+ if not 1 <= plan_num <= 99:
244
+ raise ValueError(f"Plan number must be between 1 and 99, got: {plan_num}")
245
+ current_plan_number = f"{plan_num:02d}" # Ensure two-digit format
236
246
  logger.debug(f"Converted plan number to two-digit format: {current_plan_number}")
237
- except ValueError:
247
+ except (ValueError, TypeError) as e:
248
+ if isinstance(e, TypeError):
249
+ logger.error(f"Invalid input type: {type(current_plan_number_or_path)}. Expected string, number, or Path.")
250
+ raise TypeError(f"Invalid input type: {type(current_plan_number_or_path)}. Expected string, number, or Path.")
238
251
  logger.error(f"Invalid plan number: {current_plan_number_or_path}. Expected a number from 1 to 99.")
239
252
  raise ValueError(f"Invalid plan number: {current_plan_number_or_path}. Expected a number from 1 to 99.")
240
253
 
254
+ # Construct and validate plan path
241
255
  plan_name = f"{ras_obj.project_name}.p{current_plan_number}"
242
256
  full_plan_path = ras_obj.project_folder / plan_name
257
+
258
+ if not full_plan_path.exists():
259
+ logger.error(f"Plan file does not exist: {full_plan_path}")
260
+ raise FileNotFoundError(f"Plan file does not exist: {full_plan_path}")
261
+
243
262
  logger.info(f"Constructed plan file path: {full_plan_path}")
244
263
  return full_plan_path
245
264
 
ras_commander/__init__.py CHANGED
@@ -10,7 +10,7 @@ try:
10
10
  __version__ = version("ras-commander")
11
11
  except PackageNotFoundError:
12
12
  # package is not installed
13
- __version__ = "0.64.0"
13
+ __version__ = "0.66.0"
14
14
 
15
15
  # Set up logging
16
16
  setup_logging()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: ras-commander
3
- Version: 0.64.0
3
+ Version: 0.66.0
4
4
  Summary: A Python library for automating HEC-RAS 6.x operations
5
5
  Home-page: https://github.com/gpt-cmdr/ras-commander
6
6
  Author: William M. Katzenmeyer, P.E., C.F.M.
@@ -21,14 +21,14 @@ ras_commander/RasExamples.py,sha256=6IZ96LcAsk5LYFehdD0zDW5wyZWxQa6OQu2N9upxWXA,
21
21
  ras_commander/RasGeo.py,sha256=M0sVNKlWmmbve8iMXLWq25WgbxqLWBo7_1oDg_rALzU,5607
22
22
  ras_commander/RasGpt.py,sha256=N_7p2nucWrBBXdB2k2ZKvOeOdXNmFD9dIY3W7_5i5nw,1206
23
23
  ras_commander/RasMapper.py,sha256=LO_blvQnd4pwkEU8A30-RoE-CYIoU3s_fNLHBoM8ljw,613
24
- ras_commander/RasPlan.py,sha256=TYxFh3d6ZDqeytFcwEmtlo8TQ79wLmalo7HohBUYf40,62118
25
- ras_commander/RasPrj.py,sha256=KVDz4SKq-axe4AZv27H1ACrPov-ERHM9esl51p6Crfc,42560
24
+ ras_commander/RasPlan.py,sha256=0THxeB9ldeDuS4of2ruYG7Abbc5jz2729y5qOHntMuI,61664
25
+ ras_commander/RasPrj.py,sha256=gQoGG1Mqsoj5W1oVlulqhA0kQ5eD69vI96uihnY-kLE,47744
26
26
  ras_commander/RasToGo.py,sha256=TKujfaV1xQhFaOddF4g2ogGy6ky-CLlfelSMPD2J3Nk,1223
27
27
  ras_commander/RasUnsteady.py,sha256=KfCXAag-_bPwwS3JbPZH-s4hbaoHACO0mlRnGrzbFgA,32092
28
- ras_commander/RasUtils.py,sha256=P2-aBL61kdRINsjnBpstZVD6VVc7hI_D3RUXqr6ldmc,34863
29
- ras_commander/__init__.py,sha256=KGJQL7tKKaKdvY8Gtfm1QUsCX3vVxXZXF5EVStGVyk8,2001
30
- ras_commander-0.64.0.dist-info/LICENSE,sha256=_pbd6qHnlsz1iQ-ozDW_49r86BZT6CRwO2iBtw0iN6M,457
31
- ras_commander-0.64.0.dist-info/METADATA,sha256=u9uEBRrgkNsXiKrPRZDXAmhtUdCn1nVEQzIHRDDUe8c,26233
32
- ras_commander-0.64.0.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
33
- ras_commander-0.64.0.dist-info/top_level.txt,sha256=i76S7eKLFC8doKcXDl3aiOr9RwT06G8adI6YuKbQDaA,14
34
- ras_commander-0.64.0.dist-info/RECORD,,
28
+ ras_commander/RasUtils.py,sha256=0fm4IIs0LH1dgDj3pGd66mR82DhWLEkRKUvIo2M_5X0,35886
29
+ ras_commander/__init__.py,sha256=KICL5peRDDjE2BXEFVDMmtDZ4TKHtNhHh5eQgTSdqqs,2001
30
+ ras_commander-0.66.0.dist-info/LICENSE,sha256=_pbd6qHnlsz1iQ-ozDW_49r86BZT6CRwO2iBtw0iN6M,457
31
+ ras_commander-0.66.0.dist-info/METADATA,sha256=-jPNaFlPs0iCcscfGjO31DwF3-LT632rbiunJQmYzoM,26233
32
+ ras_commander-0.66.0.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
33
+ ras_commander-0.66.0.dist-info/top_level.txt,sha256=i76S7eKLFC8doKcXDl3aiOr9RwT06G8adI6YuKbQDaA,14
34
+ ras_commander-0.66.0.dist-info/RECORD,,