ras-commander 0.42.0__py3-none-any.whl → 0.44.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
@@ -44,7 +44,8 @@ from pathlib import Path
44
44
  import pandas as pd
45
45
  from typing import Union, Any, List, Dict, Tuple
46
46
  import logging
47
- from ras_commander.logging_config import get_logger, log_call
47
+ from ras_commander.LoggingConfig import get_logger
48
+ from ras_commander.Decorators import log_call
48
49
 
49
50
  logger = get_logger(__name__)
50
51
 
@@ -87,6 +88,7 @@ class RasPrj:
87
88
  logger.info(f"Plan entries: {len(self.plan_df)}, Flow entries: {len(self.flow_df)}, "
88
89
  f"Unsteady entries: {len(self.unsteady_df)}, Geometry entries: {len(self.geom_df)}, "
89
90
  f"Boundary conditions: {len(self.boundaries_df)}")
91
+ logger.info(f"Geometry HDF files found: {self.plan_df['Geom_File'].notna().sum()}")
90
92
 
91
93
  @log_call
92
94
  def _load_project_data(self):
@@ -100,7 +102,36 @@ class RasPrj:
100
102
  self.plan_df = self._get_prj_entries('Plan')
101
103
  self.flow_df = self._get_prj_entries('Flow')
102
104
  self.unsteady_df = self._get_prj_entries('Unsteady')
103
- self.geom_df = self._get_prj_entries('Geom')
105
+ self.geom_df = self.get_geom_entries() # Use get_geom_entries instead of _get_prj_entries
106
+
107
+ # Add Geom_File to plan_df
108
+ self.plan_df['Geom_File'] = self.plan_df.apply(lambda row: self._get_geom_file_for_plan(row['plan_number']), axis=1)
109
+
110
+ @log_call
111
+ def _get_geom_file_for_plan(self, plan_number):
112
+ """
113
+ Get the geometry file path for a given plan number.
114
+
115
+ Args:
116
+ plan_number (str): The plan number to find the geometry file for.
117
+
118
+ Returns:
119
+ str: The full path to the geometry HDF file, or None if not found.
120
+ """
121
+ plan_file_path = self.project_folder / f"{self.project_name}.p{plan_number}"
122
+ try:
123
+ with open(plan_file_path, 'r') as plan_file:
124
+ for line in plan_file:
125
+ if line.startswith("Geom File="):
126
+ geom_file = line.strip().split('=')[1]
127
+ geom_hdf_path = self.project_folder / f"{self.project_name}.{geom_file}.hdf"
128
+ if geom_hdf_path.exists():
129
+ return str(geom_hdf_path)
130
+ else:
131
+ return None
132
+ except Exception as e:
133
+ logger.error(f"Error reading plan file for geometry: {e}")
134
+ return None
104
135
 
105
136
  @log_call
106
137
  def _parse_plan_file(self, plan_file_path):
@@ -381,16 +412,31 @@ class RasPrj:
381
412
  @log_call
382
413
  def get_geom_entries(self):
383
414
  """
384
- Get all geometry entries from the HEC-RAS project.
415
+ Get geometry entries from the project file.
385
416
 
386
417
  Returns:
387
- pd.DataFrame: A DataFrame containing all geometry entries.
388
-
389
- Raises:
390
- RuntimeError: If the project has not been initialized.
418
+ pd.DataFrame: DataFrame containing geometry entries.
391
419
  """
392
- self.check_initialized()
393
- return self._get_prj_entries('Geom')
420
+ geom_pattern = re.compile(r'Geom File=(\w+)')
421
+ geom_entries = []
422
+
423
+ try:
424
+ with open(self.prj_file, 'r') as f:
425
+ for line in f:
426
+ match = geom_pattern.search(line)
427
+ if match:
428
+ geom_entries.append(match.group(1))
429
+
430
+ geom_df = pd.DataFrame({'geom_file': geom_entries})
431
+ geom_df['geom_number'] = geom_df['geom_file'].str.extract(r'(\d+)$')
432
+ geom_df['full_path'] = geom_df['geom_file'].apply(lambda x: str(self.project_folder / f"{self.project_name}.{x}"))
433
+ geom_df['hdf_path'] = geom_df['full_path'] + ".hdf"
434
+
435
+ logger.info(f"Found {len(geom_df)} geometry entries")
436
+ return geom_df
437
+ except Exception as e:
438
+ logger.error(f"Error reading geometry entries from project file: {e}")
439
+ raise
394
440
 
395
441
  @log_call
396
442
  def get_hdf_entries(self):
@@ -25,7 +25,8 @@ Example:
25
25
  import os
26
26
  from pathlib import Path
27
27
  from .RasPrj import ras
28
- from ras_commander.logging_config import get_logger, log_call
28
+ from .LoggingConfig import get_logger
29
+ from .Decorators import log_call
29
30
 
30
31
  logger = get_logger(__name__)
31
32
 
ras_commander/RasUtils.py CHANGED
@@ -24,13 +24,19 @@ Example:
24
24
  import os
25
25
  from pathlib import Path
26
26
  from .RasPrj import ras
27
- from typing import Union, Optional, Dict, Callable
27
+ from typing import Union, Optional, Dict, Callable, List, Tuple, Any
28
28
  import pandas as pd
29
29
  import numpy as np
30
30
  import shutil
31
- from ras_commander import get_logger
32
- from ras_commander.logging_config import get_logger, log_call
33
31
  import re
32
+ from scipy.spatial import KDTree
33
+ import datetime
34
+ import time
35
+ import h5py
36
+ from datetime import timedelta
37
+ from .LoggingConfig import get_logger
38
+ from .Decorators import log_call
39
+
34
40
 
35
41
  logger = get_logger(__name__)
36
42
  # Module code starts here
@@ -41,76 +47,6 @@ class RasUtils:
41
47
  When integrating new functions that do not clearly fit into other classes, add them here.
42
48
  """
43
49
 
44
- @staticmethod
45
- @log_call
46
- def create_backup(file_path: Path, backup_suffix: str = "_backup", ras_object=None) -> Path:
47
- """
48
- Create a backup of the specified file.
49
-
50
- Parameters:
51
- file_path (Path): Path to the file to be backed up
52
- backup_suffix (str): Suffix to append to the backup file name
53
- ras_object (RasPrj, optional): RAS object to use. If None, uses the default ras object.
54
-
55
- Returns:
56
- Path: Path to the created backup file
57
-
58
- Example:
59
- >>> backup_path = RasUtils.create_backup(Path("project.prj"))
60
- >>> print(f"Backup created at: {backup_path}")
61
- """
62
- ras_obj = ras_object or ras
63
- ras_obj.check_initialized()
64
-
65
- original_path = Path(file_path)
66
- backup_path = original_path.with_name(f"{original_path.stem}{backup_suffix}{original_path.suffix}")
67
- try:
68
- shutil.copy2(original_path, backup_path)
69
- logger.info(f"Backup created: {backup_path}")
70
- except Exception as e:
71
- logger.error(f"Failed to create backup for {original_path}: {e}")
72
- raise
73
- return backup_path
74
-
75
- @staticmethod
76
- @log_call
77
- def restore_from_backup(backup_path: Path, remove_backup: bool = True, ras_object=None) -> Path:
78
- """
79
- Restore a file from its backup.
80
-
81
- Parameters:
82
- backup_path (Path): Path to the backup file
83
- remove_backup (bool): Whether to remove the backup file after restoration
84
- ras_object (RasPrj, optional): RAS object to use. If None, uses the default ras object.
85
-
86
- Returns:
87
- Path: Path to the restored file
88
-
89
- Example:
90
- >>> restored_path = RasUtils.restore_from_backup(Path("project_backup.prj"))
91
- >>> print(f"File restored to: {restored_path}")
92
- """
93
- ras_obj = ras_object or ras
94
- ras_obj.check_initialized()
95
-
96
- backup_path = Path(backup_path)
97
- if '_backup' not in backup_path.stem:
98
- logger.error(f"Backup suffix '_backup' not found in {backup_path.name}")
99
- raise ValueError(f"Backup suffix '_backup' not found in {backup_path.name}")
100
-
101
- original_stem = backup_path.stem.rsplit('_backup', 1)[0]
102
- original_path = backup_path.with_name(f"{original_stem}{backup_path.suffix}")
103
- try:
104
- shutil.copy2(backup_path, original_path)
105
- logger.info(f"File restored: {original_path}")
106
- if remove_backup:
107
- backup_path.unlink()
108
- logger.info(f"Backup removed: {backup_path}")
109
- except Exception as e:
110
- logger.error(f"Failed to restore from backup {backup_path}: {e}")
111
- raise
112
- return original_path
113
-
114
50
  @staticmethod
115
51
  @log_call
116
52
  def create_directory(directory_path: Path, ras_object=None) -> Path:
@@ -738,3 +674,192 @@ class RasUtils:
738
674
  except Exception as e:
739
675
  logger.exception(f"Failed to update project file {prj_file}")
740
676
  raise
677
+
678
+
679
+
680
+
681
+ # From FunkShuns
682
+
683
+ @staticmethod
684
+ @log_call
685
+ def decode_byte_strings(dataframe: pd.DataFrame) -> pd.DataFrame:
686
+ """
687
+ Decodes byte strings in a DataFrame to regular string objects.
688
+
689
+ This function converts columns with byte-encoded strings (e.g., b'string') into UTF-8 decoded strings.
690
+
691
+ Args:
692
+ dataframe (pd.DataFrame): The DataFrame containing byte-encoded string columns.
693
+
694
+ Returns:
695
+ pd.DataFrame: The DataFrame with byte strings decoded to regular strings.
696
+
697
+ Example:
698
+ >>> df = pd.DataFrame({'A': [b'hello', b'world'], 'B': [1, 2]})
699
+ >>> decoded_df = RasUtils.decode_byte_strings(df)
700
+ >>> print(decoded_df)
701
+ A B
702
+ 0 hello 1
703
+ 1 world 2
704
+ """
705
+ str_df = dataframe.select_dtypes(['object'])
706
+ str_df = str_df.stack().str.decode('utf-8').unstack()
707
+ for col in str_df:
708
+ dataframe[col] = str_df[col]
709
+ return dataframe
710
+
711
+ @staticmethod
712
+ @log_call
713
+ def perform_kdtree_query(
714
+ reference_points: np.ndarray,
715
+ query_points: np.ndarray,
716
+ max_distance: float = 2.0
717
+ ) -> np.ndarray:
718
+ """
719
+ Performs a KDTree query between two datasets and returns indices with distances exceeding max_distance set to -1.
720
+
721
+ Args:
722
+ reference_points (np.ndarray): The reference dataset for KDTree.
723
+ query_points (np.ndarray): The query dataset to search against KDTree of reference_points.
724
+ max_distance (float, optional): The maximum distance threshold. Indices with distances greater than this are set to -1. Defaults to 2.0.
725
+
726
+ Returns:
727
+ np.ndarray: Array of indices from reference_points that are nearest to each point in query_points.
728
+ Indices with distances > max_distance are set to -1.
729
+
730
+ Example:
731
+ >>> ref_points = np.array([[0, 0], [1, 1], [2, 2]])
732
+ >>> query_points = np.array([[0.5, 0.5], [3, 3]])
733
+ >>> result = RasUtils.perform_kdtree_query(ref_points, query_points)
734
+ >>> print(result)
735
+ array([ 0, -1])
736
+ """
737
+ dist, snap = KDTree(reference_points).query(query_points, distance_upper_bound=max_distance)
738
+ snap[dist > max_distance] = -1
739
+ return snap
740
+
741
+ @staticmethod
742
+ @log_call
743
+ def find_nearest_neighbors(points: np.ndarray, max_distance: float = 2.0) -> np.ndarray:
744
+ """
745
+ Creates a self KDTree for dataset points and finds nearest neighbors excluding self,
746
+ with distances above max_distance set to -1.
747
+
748
+ Args:
749
+ points (np.ndarray): The dataset to build the KDTree from and query against itself.
750
+ max_distance (float, optional): The maximum distance threshold. Indices with distances
751
+ greater than max_distance are set to -1. Defaults to 2.0.
752
+
753
+ Returns:
754
+ np.ndarray: Array of indices representing the nearest neighbor in points for each point in points.
755
+ Indices with distances > max_distance or self-matches are set to -1.
756
+
757
+ Example:
758
+ >>> points = np.array([[0, 0], [1, 1], [2, 2], [10, 10]])
759
+ >>> result = RasUtils.find_nearest_neighbors(points)
760
+ >>> print(result)
761
+ array([1, 0, 1, -1])
762
+ """
763
+ dist, snap = KDTree(points).query(points, k=2, distance_upper_bound=max_distance)
764
+ snap[dist > max_distance] = -1
765
+
766
+ snp = pd.DataFrame(snap, index=np.arange(len(snap)))
767
+ snp = snp.replace(-1, np.nan)
768
+ snp.loc[snp[0] == snp.index, 0] = np.nan
769
+ snp.loc[snp[1] == snp.index, 1] = np.nan
770
+ filled = snp[0].fillna(snp[1])
771
+ snapped = filled.fillna(-1).astype(np.int64).to_numpy()
772
+ return snapped
773
+
774
+ @staticmethod
775
+ @log_call
776
+ def consolidate_dataframe(
777
+ dataframe: pd.DataFrame,
778
+ group_by: Optional[Union[str, List[str]]] = None,
779
+ pivot_columns: Optional[Union[str, List[str]]] = None,
780
+ level: Optional[int] = None,
781
+ n_dimensional: bool = False,
782
+ aggregation_method: Union[str, Callable] = 'list'
783
+ ) -> pd.DataFrame:
784
+ """
785
+ Consolidate rows in a DataFrame by merging duplicate values into lists or using a specified aggregation function.
786
+
787
+ Args:
788
+ dataframe (pd.DataFrame): The DataFrame to consolidate.
789
+ group_by (Optional[Union[str, List[str]]]): Columns or indices to group by.
790
+ pivot_columns (Optional[Union[str, List[str]]]): Columns to pivot.
791
+ level (Optional[int]): Level of multi-index to group by.
792
+ n_dimensional (bool): If True, use a pivot table for N-Dimensional consolidation.
793
+ aggregation_method (Union[str, Callable]): Aggregation method, e.g., 'list' to aggregate into lists.
794
+
795
+ Returns:
796
+ pd.DataFrame: The consolidated DataFrame.
797
+
798
+ Example:
799
+ >>> df = pd.DataFrame({'A': [1, 1, 2], 'B': [4, 5, 6], 'C': [7, 8, 9]})
800
+ >>> result = RasUtils.consolidate_dataframe(df, group_by='A')
801
+ >>> print(result)
802
+ B C
803
+ A
804
+ 1 [4, 5] [7, 8]
805
+ 2 [6] [9]
806
+ """
807
+ if aggregation_method == 'list':
808
+ agg_func = lambda x: tuple(x)
809
+ else:
810
+ agg_func = aggregation_method
811
+
812
+ if n_dimensional:
813
+ result = dataframe.pivot_table(group_by, pivot_columns, aggfunc=agg_func)
814
+ else:
815
+ result = dataframe.groupby(group_by, level=level).agg(agg_func).applymap(list)
816
+
817
+ return result
818
+
819
+ @staticmethod
820
+ @log_call
821
+ def find_nearest_value(array: Union[list, np.ndarray], target_value: Union[int, float]) -> Union[int, float]:
822
+ """
823
+ Finds the nearest value in a NumPy array to the specified target value.
824
+
825
+ Args:
826
+ array (Union[list, np.ndarray]): The array to search within.
827
+ target_value (Union[int, float]): The value to find the nearest neighbor to.
828
+
829
+ Returns:
830
+ Union[int, float]: The nearest value in the array to the specified target value.
831
+
832
+ Example:
833
+ >>> arr = np.array([1, 3, 5, 7, 9])
834
+ >>> result = RasUtils.find_nearest_value(arr, 6)
835
+ >>> print(result)
836
+ 5
837
+ """
838
+ array = np.asarray(array)
839
+ idx = (np.abs(array - target_value)).argmin()
840
+ return array[idx]
841
+
842
+ @classmethod
843
+ @log_call
844
+ def horizontal_distance(cls, coord1: np.ndarray, coord2: np.ndarray) -> float:
845
+ """
846
+ Calculate the horizontal distance between two coordinate points.
847
+
848
+ Args:
849
+ coord1 (np.ndarray): First coordinate point [X, Y].
850
+ coord2 (np.ndarray): Second coordinate point [X, Y].
851
+
852
+ Returns:
853
+ float: Horizontal distance.
854
+
855
+ Example:
856
+ >>> distance = RasUtils.horizontal_distance(np.array([0, 0]), np.array([3, 4]))
857
+ >>> print(distance)
858
+ 5.0
859
+ """
860
+ return np.linalg.norm(coord2 - coord1)
861
+
862
+
863
+
864
+
865
+
ras_commander/__init__.py CHANGED
@@ -1,5 +1,6 @@
1
1
  from importlib.metadata import version, PackageNotFoundError
2
- from .logging_config import setup_logging, get_logger, log_call
2
+ from .LoggingConfig import setup_logging, get_logger
3
+ from .Decorators import log_call, standardize_input
3
4
 
4
5
  try:
5
6
  __version__ = version("ras-commander")
@@ -11,19 +12,40 @@ except PackageNotFoundError:
11
12
  setup_logging()
12
13
 
13
14
  # Import all necessary functions and classes directly
14
- from .RasPrj import ras, init_ras_project, get_ras_exe
15
- from .RasPrj import RasPrj
15
+ from .RasPrj import RasPrj, init_ras_project, get_ras_exe, ras
16
16
  from .RasPlan import RasPlan
17
17
  from .RasGeo import RasGeo
18
18
  from .RasUnsteady import RasUnsteady
19
- from .RasCmdr import RasCmdr
20
19
  from .RasUtils import RasUtils
21
20
  from .RasExamples import RasExamples
22
- from .RasHdf import RasHdf
21
+ from .RasCmdr import RasCmdr
23
22
  from .RasGpt import RasGpt
24
23
 
24
+ # Import the Hdf* classes
25
+ from .HdfBase import HdfBase
26
+ from .HdfBndry import HdfBndry
27
+ from .HdfMesh import HdfMesh
28
+ from .HdfPlan import HdfPlan
29
+ from .HdfResultsMesh import HdfResultsMesh
30
+ from .HdfResultsPlan import HdfResultsPlan
31
+ from .HdfResultsXsec import HdfResultsXsec
32
+ from .HdfStruc import HdfStruc
33
+ from .HdfUtils import HdfUtils
34
+ from .HdfXsec import HdfXsec
35
+
25
36
  # Define __all__ to specify what should be imported when using "from ras_commander import *"
26
37
  __all__ = [
38
+ "HdfBase",
39
+ "HdfBndry",
40
+ "HdfMesh",
41
+ "HdfPlan",
42
+ "HdfResultsMesh",
43
+ "HdfResultsPlan",
44
+ "HdfResultsXsec",
45
+ "HdfStruc",
46
+ "HdfUtils",
47
+ "HdfXsec",
48
+ "standardize_input",
27
49
  "ras",
28
50
  "init_ras_project",
29
51
  "get_ras_exe",
@@ -34,8 +56,8 @@ __all__ = [
34
56
  "RasCmdr",
35
57
  "RasUtils",
36
58
  "RasExamples",
37
- "RasHdf",
38
- "RasGpt",
39
59
  "get_logger",
40
- "log_call"
41
- ]
60
+ "log_call",
61
+ ]
62
+
63
+ __version__ = "0.1.0"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ras-commander
3
- Version: 0.42.0
3
+ Version: 0.44.0
4
4
  Summary: A Python library for automating HEC-RAS operations
5
5
  Home-page: https://github.com/billk-FM/ras-commander
6
6
  Author: William M. Katzenmeyer
@@ -62,7 +62,7 @@ Create a virtual environment with conda or venv (ask ChatGPT if you need help)
62
62
  In your virtual environment, install ras-commander using pip:
63
63
  ```
64
64
  pip install h5py numpy pandas requests tqdm scipy
65
- pip install ras-commander
65
+ pip install --upgrade ras-commander
66
66
  ```
67
67
 
68
68
  If you have dependency issues with pip (especially if you have errors with numpy), try clearing your local pip packages 'C:\Users\your_username\AppData\Roaming\Python\' and then creating a new virtual environment.
@@ -299,6 +299,13 @@ These acknowledgments recognize the contributions and inspirations that have hel
299
299
  4. [HEC-Commander Tools](https://github.com/billk-FM/HEC-Commander) - Inspiration and initial code base for the development of RAS Commander.
300
300
 
301
301
 
302
+ ## Official RAS Commander AI-Generated Songs:
303
+
304
+ [No More Wait and See (Bluegrass)](https://suno.com/song/16889f3e-50f1-4afe-b779-a41738d7617a)
305
+
306
+ [No More Wait and See (Cajun Zydeco)](https://suno.com/song/4441c45d-f6cd-47b9-8fbc-1f7b277ee8ed)
307
+
308
+
302
309
  ## Contact
303
310
 
304
311
  For questions, suggestions, or support, please contact:
@@ -0,0 +1,26 @@
1
+ ras_commander/Decorators.py,sha256=i5AEQbe7JeI8Y3O_dQ5OO4Ab0KO5SiZTiysFBGxqTRU,4978
2
+ ras_commander/HdfBase.py,sha256=HV5ccV9QH2lz4ZRYqK2d7_S833cTSUcostzxxSPb4O4,7129
3
+ ras_commander/HdfBndry.py,sha256=LWaDMHeo0V_VOpx7D9q7W_0WvWsD6NQThiSLYPY8ApE,20761
4
+ ras_commander/HdfMesh.py,sha256=JKWn6S-FcdFs3fZQMQ8mkIEIFFxUdVjWb5r7jAh3ujw,12668
5
+ ras_commander/HdfPlan.py,sha256=nt1Q03cPNX_yVX0mOUqeWGPicqtusUnuBSTcBw8n0Vg,6967
6
+ ras_commander/HdfResultsMesh.py,sha256=Ke6HSpdKBd-TUa0QIuMaxhyj--lfuQGlMDlDuk2qrd8,28064
7
+ ras_commander/HdfResultsPlan.py,sha256=zkosLBpyXIkoWrqAXh8sRxcmKvca2F-urQUGCnT8PmQ,17293
8
+ ras_commander/HdfResultsXsec.py,sha256=sQokzqL5Fpnr7bsHppoygL6hrr07dTXiLvaecNOp64s,8426
9
+ ras_commander/HdfStruc.py,sha256=NNTSwUQmLMLn8SPyrLIKXaUaqKavTos_TDDB6Mja7-4,5595
10
+ ras_commander/HdfUtils.py,sha256=dUU9QkNO-FhaCjD_TEOv_FNNrZI3TUOQ6QjSiXrJGSc,18403
11
+ ras_commander/HdfXsec.py,sha256=ccJ-GAVKwS2Z-k6CCWAYvw974xCBTTF-5Hh1CnikVG4,11562
12
+ ras_commander/LoggingConfig.py,sha256=5bYd_5KMlf81bXsiu2mABBlw0USMhcu5uRv8DIYJSFE,2317
13
+ ras_commander/RasCmdr.py,sha256=qZtdvwQnZxOjhU3pZWRCJ80aH5QWOJD_F7P_05geSHA,25020
14
+ ras_commander/RasExamples.py,sha256=FDit6FWzTQbv42Xx0gtSJB17HDeol_eykxV0qVpnwIk,16688
15
+ ras_commander/RasGeo.py,sha256=x7eFvUQ_dPZxAVq2Gw_GIRzn-Cf7DLKZDTwk1fjrkf8,5395
16
+ ras_commander/RasGpt.py,sha256=1Nitlf5QyeBQo8Q8I8pJKaTtQ0GdsBQA71LIKUAOycA,839
17
+ ras_commander/RasPlan.py,sha256=_0EjxQnamd9FhzzKlYNqJ3chv2bvxfk0DXEwfHntXFo,40287
18
+ ras_commander/RasPrj.py,sha256=ePLcPNcKVMgijvJKkJIWwQslQi2D6zq2UTW-8XCFmto,36159
19
+ ras_commander/RasUnsteady.py,sha256=oBVC9QFQMrSx8LY2Cb1CjUyCQEUoIEnEuVJsATYiVYs,4649
20
+ ras_commander/RasUtils.py,sha256=NBMxTHWHoTH2MJzqJ0y1_00fgKSS1GnNuEikwZ3Pqzs,34153
21
+ ras_commander/__init__.py,sha256=3MuobRXVEQNvoGwf9AlbvuJg8meni3eWw_JZMFOuMt4,1630
22
+ ras_commander-0.44.0.dist-info/LICENSE,sha256=_pbd6qHnlsz1iQ-ozDW_49r86BZT6CRwO2iBtw0iN6M,457
23
+ ras_commander-0.44.0.dist-info/METADATA,sha256=zbNmO6OwnKbX-B3bIgdrPYnLA2aPFZ1PqfBstFzEkCA,15935
24
+ ras_commander-0.44.0.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
25
+ ras_commander-0.44.0.dist-info/top_level.txt,sha256=i76S7eKLFC8doKcXDl3aiOr9RwT06G8adI6YuKbQDaA,14
26
+ ras_commander-0.44.0.dist-info/RECORD,,