ras-commander 0.35.0__py3-none-any.whl → 0.37.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.
@@ -1,3 +1,28 @@
1
+ """
2
+ RasExamples - Manage and load HEC-RAS example projects for testing and development
3
+
4
+ This module is part of the ras-commander library and uses a centralized logging configuration.
5
+
6
+ Logging Configuration:
7
+ - The logging is set up in the logging_config.py file.
8
+ - A @log_call decorator is available to automatically log function calls.
9
+ - Log levels: DEBUG, INFO, WARNING, ERROR, CRITICAL
10
+ - Logs are written to both console and a rotating file handler.
11
+ - The default log file is 'ras_commander.log' in the 'logs' directory.
12
+ - The default log level is INFO.
13
+
14
+ To use logging in this module:
15
+ 1. Use the @log_call decorator for automatic function call logging.
16
+ 2. For additional logging, use logger.[level]() calls (e.g., logger.info(), logger.debug()).
17
+ 3. Obtain the logger using: logger = logging.getLogger(__name__)
18
+
19
+ Example:
20
+ @log_call
21
+ def my_function():
22
+ logger = logging.getLogger(__name__)
23
+ logger.debug("Additional debug information")
24
+ # Function logic here
25
+ """
1
26
  import os
2
27
  import requests
3
28
  import zipfile
@@ -10,15 +35,10 @@ from datetime import datetime
10
35
  import logging
11
36
  import re
12
37
  from tqdm import tqdm
38
+ from ras_commander import get_logger
39
+ from ras_commander.logging_config import log_call
13
40
 
14
- # Configure logging
15
- logging.basicConfig(
16
- level=logging.INFO, # Set the logging level to INFO
17
- format='%(asctime)s - %(levelname)s - %(message)s', # Log message format
18
- handlers=[
19
- logging.StreamHandler() # Log to stderr
20
- ]
21
- )
41
+ logger = get_logger(__name__)
22
42
 
23
43
  class RasExamples:
24
44
  """
@@ -28,10 +48,8 @@ class RasExamples:
28
48
  It supports both default HEC-RAS example projects and custom projects from user-provided URLs.
29
49
  Additionally, it includes functionality to download FEMA's Base Level Engineering (BLE) models
30
50
  from CSV files provided by the FEMA Estimated Base Flood Elevation (BFE) Viewer.
31
-
32
- [Documentation as previously provided]
33
51
  """
34
-
52
+ @log_call
35
53
  def __init__(self):
36
54
  """
37
55
  Initialize the RasExamples class.
@@ -50,9 +68,10 @@ class RasExamples:
50
68
  self.csv_file_path = self.examples_dir / 'example_projects.csv'
51
69
 
52
70
  self.projects_dir.mkdir(parents=True, exist_ok=True)
53
- logging.info(f"Example projects folder: {self.projects_dir}")
71
+ logger.info(f"Example projects folder: {self.projects_dir}")
54
72
  self._load_project_data()
55
73
 
74
+ @log_call
56
75
  def _load_project_data(self):
57
76
  """
58
77
  Load project data from CSV if up-to-date, otherwise extract from zip.
@@ -60,43 +79,45 @@ class RasExamples:
60
79
  self._find_zip_file()
61
80
 
62
81
  if not self.zip_file_path:
63
- logging.info("No example projects zip file found. Downloading...")
82
+ logger.info("No example projects zip file found. Downloading...")
64
83
  self.get_example_projects()
65
84
 
66
85
  try:
67
86
  zip_modified_time = os.path.getmtime(self.zip_file_path)
68
87
  except FileNotFoundError:
69
- logging.error(f"Zip file not found at {self.zip_file_path}.")
88
+ logger.error(f"Zip file not found at {self.zip_file_path}.")
70
89
  return
71
90
 
72
91
  if self.csv_file_path.exists():
73
92
  csv_modified_time = os.path.getmtime(self.csv_file_path)
74
93
 
75
94
  if csv_modified_time >= zip_modified_time:
76
- logging.info("Loading project data from CSV...")
95
+ logger.info("Loading project data from CSV...")
77
96
  try:
78
97
  self.folder_df = pd.read_csv(self.csv_file_path)
79
- logging.info(f"Loaded {len(self.folder_df)} projects from CSV. Use list_categories() and list_projects() to explore them.")
98
+ logger.info(f"Loaded {len(self.folder_df)} projects from CSV. Use list_categories() and list_projects() to explore them.")
80
99
  except Exception as e:
81
- logging.error(f"Failed to read CSV file: {e}")
100
+ logger.error(f"Failed to read CSV file: {e}")
82
101
  self.folder_df = None
83
102
  return
84
103
 
85
- logging.info("Extracting folder structure from zip file...")
104
+ logger.info("Extracting folder structure from zip file...")
86
105
  self._extract_folder_structure()
87
106
  self._save_to_csv()
88
107
 
108
+ @log_call
89
109
  def _find_zip_file(self):
90
110
  """Locate the example projects zip file in the examples directory."""
91
111
  for version in self.valid_versions:
92
112
  potential_zip = self.examples_dir / f"Example_Projects_{version.replace('.', '_')}.zip"
93
113
  if potential_zip.exists():
94
114
  self.zip_file_path = potential_zip
95
- logging.info(f"Found zip file: {self.zip_file_path}")
115
+ logger.info(f"Found zip file: {self.zip_file_path}")
96
116
  break
97
117
  else:
98
- logging.warning("No existing example projects zip file found.")
118
+ logger.warning("No existing example projects zip file found.")
99
119
 
120
+ @log_call
100
121
  def _extract_folder_structure(self):
101
122
  """
102
123
  Extract folder structure from the zip file.
@@ -115,34 +136,36 @@ class RasExamples:
115
136
  })
116
137
 
117
138
  self.folder_df = pd.DataFrame(folder_data).drop_duplicates()
118
- logging.info(f"Extracted {len(self.folder_df)} projects.")
119
- logging.debug(f"folder_df:\n{self.folder_df}")
139
+ logger.info(f"Extracted {len(self.folder_df)} projects.")
140
+ logger.debug(f"folder_df:\n{self.folder_df}")
120
141
  except zipfile.BadZipFile:
121
- logging.error(f"The file {self.zip_file_path} is not a valid zip file.")
142
+ logger.error(f"The file {self.zip_file_path} is not a valid zip file.")
122
143
  self.folder_df = pd.DataFrame(columns=['Category', 'Project'])
123
144
  except Exception as e:
124
- logging.error(f"An error occurred while extracting the folder structure: {str(e)}")
145
+ logger.error(f"An error occurred while extracting the folder structure: {str(e)}")
125
146
  self.folder_df = pd.DataFrame(columns=['Category', 'Project'])
126
147
 
148
+ @log_call
127
149
  def _save_to_csv(self):
128
150
  """Save the extracted folder structure to CSV file."""
129
151
  if self.folder_df is not None and not self.folder_df.empty:
130
152
  try:
131
153
  self.folder_df.to_csv(self.csv_file_path, index=False)
132
- logging.info(f"Saved project data to {self.csv_file_path}")
154
+ logger.info(f"Saved project data to {self.csv_file_path}")
133
155
  except Exception as e:
134
- logging.error(f"Failed to save project data to CSV: {e}")
156
+ logger.error(f"Failed to save project data to CSV: {e}")
135
157
  else:
136
- logging.warning("No folder data to save to CSV.")
158
+ logger.warning("No folder data to save to CSV.")
137
159
 
160
+ @log_call
138
161
  def get_example_projects(self, version_number='6.5'):
139
162
  """
140
163
  Download and extract HEC-RAS example projects for a specified version.
141
164
  """
142
- logging.info(f"Getting example projects for version {version_number}")
165
+ logger.info(f"Getting example projects for version {version_number}")
143
166
  if version_number not in self.valid_versions:
144
167
  error_msg = f"Invalid version number. Valid versions are: {', '.join(self.valid_versions)}"
145
- logging.error(error_msg)
168
+ logger.error(error_msg)
146
169
  raise ValueError(error_msg)
147
170
 
148
171
  zip_url = f"{self.base_url}1.0.31/Example_Projects_{version_number.replace('.', '_')}.zip"
@@ -152,48 +175,51 @@ class RasExamples:
152
175
  self.zip_file_path = self.examples_dir / f"Example_Projects_{version_number.replace('.', '_')}.zip"
153
176
 
154
177
  if not self.zip_file_path.exists():
155
- logging.info(f"Downloading HEC-RAS Example Projects from {zip_url}. \nThe file is over 400 MB, so it may take a few minutes to download....")
178
+ logger.info(f"Downloading HEC-RAS Example Projects from {zip_url}. \nThe file is over 400 MB, so it may take a few minutes to download....")
156
179
  try:
157
180
  response = requests.get(zip_url, stream=True)
158
181
  response.raise_for_status()
159
182
  with open(self.zip_file_path, 'wb') as file:
160
183
  shutil.copyfileobj(response.raw, file)
161
- logging.info(f"Downloaded to {self.zip_file_path}")
184
+ logger.info(f"Downloaded to {self.zip_file_path}")
162
185
  except requests.exceptions.RequestException as e:
163
- logging.error(f"Failed to download the zip file: {e}")
186
+ logger.error(f"Failed to download the zip file: {e}")
164
187
  raise
165
188
  else:
166
- logging.info("HEC-RAS Example Projects zip file already exists. Skipping download.")
189
+ logger.info("HEC-RAS Example Projects zip file already exists. Skipping download.")
167
190
 
168
191
  self._load_project_data()
169
192
  return self.projects_dir
170
193
 
194
+ @log_call
171
195
  def list_categories(self):
172
196
  """
173
197
  List all categories of example projects.
174
198
  """
175
199
  if self.folder_df is None or 'Category' not in self.folder_df.columns:
176
- logging.warning("No categories available. Make sure the zip file is properly loaded.")
200
+ logger.warning("No categories available. Make sure the zip file is properly loaded.")
177
201
  return []
178
202
  categories = self.folder_df['Category'].unique()
179
- logging.info(f"Available categories: {', '.join(categories)}")
203
+ logger.info(f"Available categories: {', '.join(categories)}")
180
204
  return categories.tolist()
181
205
 
206
+ @log_call
182
207
  def list_projects(self, category=None):
183
208
  """
184
209
  List all projects or projects in a specific category.
185
210
  """
186
211
  if self.folder_df is None:
187
- logging.warning("No projects available. Make sure the zip file is properly loaded.")
212
+ logger.warning("No projects available. Make sure the zip file is properly loaded.")
188
213
  return []
189
214
  if category:
190
215
  projects = self.folder_df[self.folder_df['Category'] == category]['Project'].unique()
191
- logging.info(f"Projects in category '{category}': {', '.join(projects)}")
216
+ logger.info(f"Projects in category '{category}': {', '.join(projects)}")
192
217
  else:
193
218
  projects = self.folder_df['Project'].unique()
194
- logging.info(f"All available projects: {', '.join(projects)}")
219
+ logger.info(f"All available projects: {', '.join(projects)}")
195
220
  return projects.tolist()
196
221
 
222
+ @log_call
197
223
  def extract_project(self, project_names: Union[str, List[str]]):
198
224
  """
199
225
  Extract one or more specific HEC-RAS projects from the zip file.
@@ -204,28 +230,28 @@ class RasExamples:
204
230
  extracted_paths = []
205
231
 
206
232
  for project_name in project_names:
207
- logging.info("----- RasExamples Extracting Project -----")
208
- logging.info(f"Extracting project '{project_name}'")
233
+ logger.info("----- RasExamples Extracting Project -----")
234
+ logger.info(f"Extracting project '{project_name}'")
209
235
  project_path = self.projects_dir / project_name
210
236
 
211
237
  if project_path.exists():
212
- logging.info(f"Project '{project_name}' already exists. Deleting existing folder...")
238
+ logger.info(f"Project '{project_name}' already exists. Deleting existing folder...")
213
239
  try:
214
240
  shutil.rmtree(project_path)
215
- logging.info(f"Existing folder for project '{project_name}' has been deleted.")
241
+ logger.info(f"Existing folder for project '{project_name}' has been deleted.")
216
242
  except Exception as e:
217
- logging.error(f"Failed to delete existing project folder '{project_name}': {e}")
243
+ logger.error(f"Failed to delete existing project folder '{project_name}': {e}")
218
244
  continue
219
245
 
220
246
  if self.folder_df is None or self.folder_df.empty:
221
247
  error_msg = "No project information available. Make sure the zip file is properly loaded."
222
- logging.error(error_msg)
248
+ logger.error(error_msg)
223
249
  raise ValueError(error_msg)
224
250
 
225
251
  project_info = self.folder_df[self.folder_df['Project'] == project_name]
226
252
  if project_info.empty:
227
253
  error_msg = f"Project '{project_name}' not found in the zip file."
228
- logging.error(error_msg)
254
+ logger.error(error_msg)
229
255
  raise ValueError(error_msg)
230
256
 
231
257
  category = project_info['Category'].iloc[0]
@@ -248,40 +274,44 @@ class RasExamples:
248
274
  with zip_ref.open(file) as source, open(extract_path, "wb") as target:
249
275
  shutil.copyfileobj(source, target)
250
276
 
251
- logging.info(f"Successfully extracted project '{project_name}' to {project_path}")
277
+ logger.info(f"Successfully extracted project '{project_name}' to {project_path}")
252
278
  extracted_paths.append(project_path)
253
279
  except zipfile.BadZipFile:
254
- logging.error(f"Error: The file {self.zip_file_path} is not a valid zip file.")
280
+ logger.error(f"Error: The file {self.zip_file_path} is not a valid zip file.")
255
281
  except FileNotFoundError:
256
- logging.error(f"Error: The file {self.zip_file_path} was not found.")
282
+ logger.error(f"Error: The file {self.zip_file_path} was not found.")
257
283
  except Exception as e:
258
- logging.error(f"An unexpected error occurred while extracting the project: {str(e)}")
259
- logging.info("----- RasExamples Extraction Complete -----")
284
+ logger.error(f"An unexpected error occurred while extracting the project: {str(e)}")
285
+ logger.info("----- RasExamples Extraction Complete -----")
260
286
  return extracted_paths
261
287
 
288
+ @log_call
262
289
  def is_project_extracted(self, project_name):
263
290
  """
264
291
  Check if a specific project is already extracted.
265
292
  """
266
293
  project_path = self.projects_dir / project_name
267
294
  is_extracted = project_path.exists()
268
- logging.info(f"Project '{project_name}' extracted: {is_extracted}")
295
+ logger.info(f"Project '{project_name}' extracted: {is_extracted}")
269
296
  return is_extracted
270
297
 
298
+ @log_call
271
299
  def clean_projects_directory(self):
272
300
  """Remove all extracted projects from the example_projects directory."""
273
- logging.info(f"Cleaning projects directory: {self.projects_dir}")
301
+ logger.info(f"Cleaning projects directory: {self.projects_dir}")
274
302
  if self.projects_dir.exists():
275
303
  try:
276
304
  shutil.rmtree(self.projects_dir)
277
- logging.info("All projects have been removed.")
305
+ logger.info("All projects have been removed.")
278
306
  except Exception as e:
279
- logging.error(f"Failed to remove projects directory: {e}")
307
+ logger.error(f"Failed to remove projects directory: {e}")
280
308
  else:
281
- logging.warning("Projects directory does not exist.")
309
+ logger.warning("Projects directory does not exist.")
282
310
  self.projects_dir.mkdir(parents=True, exist_ok=True)
283
- logging.info("Projects directory cleaned and recreated.")
284
-
311
+ logger.info("Projects directory cleaned and recreated.")
312
+
313
+
314
+ @log_call
285
315
  def download_fema_ble_model(self, csv_file: Union[str, Path], output_base_dir: Union[str, Path] = None):
286
316
  """
287
317
  Download a single FEMA Base Level Engineering (BLE) model from a CSV file and organize it into folders.
@@ -316,37 +346,37 @@ class RasExamples:
316
346
  output_base_dir = Path(output_base_dir)
317
347
 
318
348
  if not csv_file.exists() or not csv_file.is_file():
319
- logging.error(f"The specified CSV file does not exist: {csv_file}")
349
+ logger.error(f"The specified CSV file does not exist: {csv_file}")
320
350
  raise FileNotFoundError(f"The specified CSV file does not exist: {csv_file}")
321
351
 
322
352
  output_base_dir.mkdir(parents=True, exist_ok=True)
323
- logging.info(f"BLE model will be organized in: {output_base_dir}")
353
+ logger.info(f"BLE model will be organized in: {output_base_dir}")
324
354
 
325
355
  try:
326
356
  # Extract region name from the filename (assuming format <AnyCharacters>_<Region>_DownloadIndex.csv)
327
357
  match = re.match(r'.+?_(.+?)_DownloadIndex\.csv', csv_file.name)
328
358
  if not match:
329
- logging.warning(f"Filename does not match expected pattern and will be skipped: {csv_file.name}")
359
+ logger.warning(f"Filename does not match expected pattern and will be skipped: {csv_file.name}")
330
360
  return
331
361
  region = match.group(1)
332
- logging.info(f"Processing region: {region}")
362
+ logger.info(f"Processing region: {region}")
333
363
 
334
364
  # Create folder for this region
335
365
  region_folder = output_base_dir / region
336
366
  region_folder.mkdir(parents=True, exist_ok=True)
337
- logging.info(f"Created/verified region folder: {region_folder}")
367
+ logger.info(f"Created/verified region folder: {region_folder}")
338
368
 
339
369
  # Read the CSV file
340
370
  try:
341
371
  df = pd.read_csv(csv_file, comment='#')
342
372
  except pd.errors.ParserError as e:
343
- logging.error(f"Error parsing CSV file {csv_file.name}: {e}")
373
+ logger.error(f"Error parsing CSV file {csv_file.name}: {e}")
344
374
  return
345
375
 
346
376
  # Verify required columns exist
347
377
  required_columns = {'URL', 'FileName', 'FileSize', 'Description', 'Details'}
348
378
  if not required_columns.issubset(df.columns):
349
- logging.warning(f"CSV file {csv_file.name} is missing required columns and will be skipped.")
379
+ logger.warning(f"CSV file {csv_file.name} is missing required columns and will be skipped.")
350
380
  return
351
381
 
352
382
  # Process each row in the CSV
@@ -360,7 +390,7 @@ class RasExamples:
360
390
  try:
361
391
  file_size = self._convert_size_to_bytes(file_size_str)
362
392
  except ValueError as e:
363
- logging.error(f"Error converting file size '{file_size_str}' to bytes: {e}")
393
+ logger.error(f"Error converting file size '{file_size_str}' to bytes: {e}")
364
394
  continue
365
395
 
366
396
  # Create a subfolder based on the safe description name
@@ -372,43 +402,45 @@ class RasExamples:
372
402
  downloaded_file = csv_folder / file_name
373
403
  if not downloaded_file.exists():
374
404
  try:
375
- logging.info(f"Downloading {file_name} from {download_url} to {csv_folder}")
405
+ logger.info(f"Downloading {file_name} from {download_url} to {csv_folder}")
376
406
  downloaded_file = self._download_file_with_progress(download_url, csv_folder, file_size)
377
- logging.info(f"Downloaded file to: {downloaded_file}")
407
+ logger.info(f"Downloaded file to: {downloaded_file}")
378
408
  except Exception as e:
379
- logging.error(f"Failed to download {download_url}: {e}")
409
+ logger.error(f"Failed to download {download_url}: {e}")
380
410
  continue
381
411
  else:
382
- logging.info(f"File {file_name} already exists in {csv_folder}, skipping download.")
412
+ logger.info(f"File {file_name} already exists in {csv_folder}, skipping download.")
383
413
 
384
414
  # If it's a zip file, unzip it to the description folder
385
415
  if downloaded_file.suffix == '.zip':
386
416
  # If the folder exists, delete it
387
417
  if description_folder.exists():
388
- logging.info(f"Folder {description_folder} already exists. Deleting it.")
418
+ logger.info(f"Folder {description_folder} already exists. Deleting it.")
389
419
  shutil.rmtree(description_folder)
390
420
 
391
421
  description_folder.mkdir(parents=True, exist_ok=True)
392
- logging.info(f"Created/verified description folder: {description_folder}")
422
+ logger.info(f"Created/verified description folder: {description_folder}")
393
423
 
394
- logging.info(f"Unzipping {downloaded_file} into {description_folder}")
424
+ logger.info(f"Unzipping {downloaded_file} into {description_folder}")
395
425
  try:
396
426
  with zipfile.ZipFile(downloaded_file, 'r') as zip_ref:
397
427
  zip_ref.extractall(description_folder)
398
- logging.info(f"Unzipped {downloaded_file} successfully.")
428
+ logger.info(f"Unzipped {downloaded_file} successfully.")
399
429
  except Exception as e:
400
- logging.error(f"Failed to extract {downloaded_file}: {e}")
430
+ logger.error(f"Failed to extract {downloaded_file}: {e}")
401
431
  except Exception as e:
402
- logging.error(f"An error occurred while processing {csv_file.name}: {e}")
432
+ logger.error(f"An error occurred while processing {csv_file.name}: {e}")
403
433
 
434
+ @log_call
404
435
  def _make_safe_folder_name(self, name: str) -> str:
405
436
  """
406
437
  Convert a string to a safe folder name by replacing unsafe characters with underscores.
407
438
  """
408
439
  safe_name = re.sub(r'[^a-zA-Z0-9_\-]', '_', name)
409
- logging.debug(f"Converted '{name}' to safe folder name '{safe_name}'")
440
+ logger.debug(f"Converted '{name}' to safe folder name '{safe_name}'")
410
441
  return safe_name
411
442
 
443
+ @log_call
412
444
  def _download_file_with_progress(self, url: str, dest_folder: Path, file_size: int) -> Path:
413
445
  """
414
446
  Download a file from a URL to a specified destination folder with progress bar.
@@ -427,15 +459,16 @@ class RasExamples:
427
459
  for chunk in r.iter_content(chunk_size=8192):
428
460
  size = f.write(chunk)
429
461
  progress_bar.update(size)
430
- logging.info(f"Successfully downloaded {url} to {local_filename}")
462
+ logger.info(f"Successfully downloaded {url} to {local_filename}")
431
463
  return local_filename
432
464
  except requests.exceptions.RequestException as e:
433
- logging.error(f"Request failed for {url}: {e}")
465
+ logger.error(f"Request failed for {url}: {e}")
434
466
  raise
435
467
  except Exception as e:
436
- logging.error(f"Failed to write file {local_filename}: {e}")
468
+ logger.error(f"Failed to write file {local_filename}: {e}")
437
469
  raise
438
470
 
471
+ @log_call
439
472
  def _convert_size_to_bytes(self, size_str: str) -> int:
440
473
  """
441
474
  Convert a human-readable file size to bytes.
@@ -453,7 +486,7 @@ class RasExamples:
453
486
  # ras_examples.download_fema_ble_models('/path/to/csv/files', '/path/to/output/folder')
454
487
  # extracted_paths = ras_examples.extract_project(["Bald Eagle Creek", "BaldEagleCrkMulti2D", "Muncie"])
455
488
  # for path in extracted_paths:
456
- # logging.info(f"Extracted to: {path}")
489
+ # logger.info(f"Extracted to: {path}")
457
490
 
458
491
 
459
492
  """
ras_commander/RasGeo.py CHANGED
@@ -1,21 +1,37 @@
1
1
  """
2
- Operations for handling geometry files in HEC-RAS projects.
2
+ RasGeo - Operations for handling geometry files in HEC-RAS projects
3
+
4
+ This module is part of the ras-commander library and uses a centralized logging configuration.
5
+
6
+ Logging Configuration:
7
+ - The logging is set up in the logging_config.py file.
8
+ - A @log_call decorator is available to automatically log function calls.
9
+ - Log levels: DEBUG, INFO, WARNING, ERROR, CRITICAL
10
+ - Logs are written to both console and a rotating file handler.
11
+ - The default log file is 'ras_commander.log' in the 'logs' directory.
12
+ - The default log level is INFO.
13
+
14
+ To use logging in this module:
15
+ 1. Use the @log_call decorator for automatic function call logging.
16
+ 2. For additional logging, use logger.[level]() calls (e.g., logger.info(), logger.debug()).
17
+ 3. Obtain the logger using: logger = logging.getLogger(__name__)
18
+
19
+ Example:
20
+ @log_call
21
+ def my_function():
22
+ logger = logging.getLogger(__name__)
23
+ logger.debug("Additional debug information")
24
+ # Function logic here
3
25
  """
26
+ import os
4
27
  from pathlib import Path
5
28
  from typing import List, Union
6
29
  from .RasPlan import RasPlan
7
30
  from .RasPrj import ras
8
- import logging
9
- import re
31
+ from ras_commander import get_logger
32
+ from ras_commander.logging_config import log_call
10
33
 
11
- # Configure logging at the module level
12
- logging.basicConfig(
13
- level=logging.INFO,
14
- format='%(asctime)s - %(levelname)s - %(message)s',
15
- # You can add a filename parameter here to log to a file
16
- # filename='rasgeo.log',
17
- # Uncomment the above line to enable file logging
18
- )
34
+ logger = get_logger(__name__)
19
35
 
20
36
  class RasGeo:
21
37
  """
@@ -23,6 +39,7 @@ class RasGeo:
23
39
  """
24
40
 
25
41
  @staticmethod
42
+ @log_call
26
43
  def clear_geompre_files(
27
44
  plan_files: Union[str, Path, List[Union[str, Path]]] = None,
28
45
  ras_object = None
@@ -58,11 +75,6 @@ class RasGeo:
58
75
  Note:
59
76
  This function updates the ras object's geometry dataframe after clearing the preprocessor files.
60
77
  """
61
- ## Explicit Function Steps
62
- # 1. Initialize the ras_object, defaulting to the global ras if not provided.
63
- # 2. Define a helper function to clear a single geometry preprocessor file.
64
- # 3. Determine the list of plan files to process based on the input.
65
- # 4. Iterate over each plan file and clear its geometry preprocessor file.
66
78
  ras_obj = ras_object or ras
67
79
  ras_obj.check_initialized()
68
80
 
@@ -72,38 +84,36 @@ class RasGeo:
72
84
  geom_preprocessor_file = plan_path.with_suffix(geom_preprocessor_suffix)
73
85
  if geom_preprocessor_file.exists():
74
86
  try:
75
- logging.info(f"Deleting geometry preprocessor file: {geom_preprocessor_file}")
76
87
  geom_preprocessor_file.unlink()
77
- logging.info("File deletion completed successfully.")
88
+ logger.info(f"Deleted geometry preprocessor file: {geom_preprocessor_file}")
78
89
  except PermissionError:
79
- logging.error(f"Permission denied: Unable to delete geometry preprocessor file: {geom_preprocessor_file}.")
90
+ logger.error(f"Permission denied: Unable to delete geometry preprocessor file: {geom_preprocessor_file}")
80
91
  raise PermissionError(f"Unable to delete geometry preprocessor file: {geom_preprocessor_file}. Permission denied.")
81
92
  except OSError as e:
82
- logging.error(f"Error deleting geometry preprocessor file: {geom_preprocessor_file}. {str(e)}")
93
+ logger.error(f"Error deleting geometry preprocessor file: {geom_preprocessor_file}. {str(e)}")
83
94
  raise OSError(f"Error deleting geometry preprocessor file: {geom_preprocessor_file}. {str(e)}")
84
95
  else:
85
- logging.warning(f"No geometry preprocessor file found for: {plan_file}")
96
+ logger.warning(f"No geometry preprocessor file found for: {plan_file}")
86
97
 
87
98
  if plan_files is None:
88
- logging.info("Clearing all geometry preprocessor files in the project directory.")
99
+ logger.info("Clearing all geometry preprocessor files in the project directory.")
89
100
  plan_files_to_clear = list(ras_obj.project_folder.glob(r'*.p*'))
90
101
  elif isinstance(plan_files, (str, Path)):
91
102
  plan_files_to_clear = [plan_files]
92
- logging.info(f"Clearing geometry preprocessor file for single plan: {plan_files}")
103
+ logger.info(f"Clearing geometry preprocessor file for single plan: {plan_files}")
93
104
  elif isinstance(plan_files, list):
94
105
  plan_files_to_clear = plan_files
95
- logging.info(f"Clearing geometry preprocessor files for multiple plans: {plan_files}")
106
+ logger.info(f"Clearing geometry preprocessor files for multiple plans: {plan_files}")
96
107
  else:
97
- logging.error("Invalid input type for plan_files.")
108
+ logger.error("Invalid input type for plan_files.")
98
109
  raise ValueError("Invalid input. Please provide a string, Path, list of paths, or None.")
99
110
 
100
111
  for plan_file in plan_files_to_clear:
101
112
  clear_single_file(plan_file, ras_obj)
102
113
 
103
- # Update the geometry dataframe
104
114
  try:
105
115
  ras_obj.geom_df = ras_obj.get_geom_entries()
106
- logging.info("Geometry dataframe updated successfully.")
116
+ logger.info("Geometry dataframe updated successfully.")
107
117
  except Exception as e:
108
- logging.error(f"Failed to update geometry dataframe: {str(e)}")
118
+ logger.error(f"Failed to update geometry dataframe: {str(e)}")
109
119
  raise