Skip to content

Commit

Permalink
Convert hdd_output_dir to Path (Issue #210)
Browse files Browse the repository at this point in the history
This is another incremental change to refactor the code to use pathlib Path objects. In this commit, the hdd_output_dir path is converted, as well as paths that have it immediately on the RHS of their assignment. There are a few instances where this is propagated a bit further, but for the most part that is as far as it goes..

The commit also includes a change to remove the gen_dbg_str global function from IV_Swinger2.py. It is superseded by the print_dbg_str global function in IV_Swinger.py. That function is aliased to PRINT_DBG_STR in IV_Swinger2.py, IV_Swinger2_gui.py, and IV_Swinger2_sim.py (so far).

This commit is to the pathlib_refactor branch and will be merged to the default branch after all the other changes have been committed and thorough testing has been performed.
  • Loading branch information
csatt committed Jun 28, 2023
1 parent dab98c5 commit c316d58
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 60 deletions.
16 changes: 14 additions & 2 deletions python3/IV_Swinger.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@
import threading
import time
import traceback
from inspect import currentframe, getframeinfo
import warnings
import numpy

Expand Down Expand Up @@ -624,6 +625,17 @@ def sigfigs(number, figs):
return initial_result_str + "0" * num_added_zeros


def print_dbg_str(msg_str):
"""Global function to use when debugging. The supplied string is
printed, preceded by the file name and line number where it is
found in the code.
"""
frameinfo = getframeinfo(currentframe().f_back)
filename = Path(frameinfo.filename).name
linenumber = frameinfo.lineno
print(f"{filename}, line {linenumber}: {msg_str}")


#################
# Classes #
#################
Expand Down Expand Up @@ -651,7 +663,7 @@ def extract_date_time_str(input_str):
other string
"""
dt_file_re = re.compile(r"(\d{6}_\d{2}_\d{2}_\d{2})")
match = dt_file_re.search(input_str)
match = dt_file_re.search(str(input_str))
if match:
return match.group(1)
return "No match"
Expand All @@ -661,7 +673,7 @@ def is_date_time_str(input_str):
"""Method to test if a given string is a date/time string
"""
dt_file_re = re.compile(r"^(\d{6}_\d{2}_\d{2}_\d{2})$")
match = dt_file_re.search(input_str)
match = dt_file_re.search(str(input_str))
if match:
return True
return False
Expand Down
51 changes: 17 additions & 34 deletions python3/IV_Swinger2.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@
import subprocess
import sys
import time
from inspect import currentframe, getframeinfo
from PIL import Image
from PIL import __version__ as pillow_version
import serial
Expand Down Expand Up @@ -144,6 +143,7 @@
OHMS_INDEX = IV_Swinger.OHMS_INDEX
WATTS_INDEX = IV_Swinger.WATTS_INDEX
INFINITE_VAL = IV_Swinger.INFINITE_VAL
PRINT_DBG_STR = IV_Swinger.print_dbg_str

# From Arduino SPI.h:
SPI_CLOCK_DIV4 = 0x00
Expand Down Expand Up @@ -310,17 +310,6 @@ def sys_view_file(filename):
subprocess.call(("xdg-open", filename))


def gen_dbg_str(msg_str):
"""Global function to use when debugging. The supplied string is
returned, along with the file name and line number where it is
found in the code.
"""
cf = currentframe()
fi = getframeinfo(cf)
dbg_str = f"DEBUG({fi.filename}, line {cf.f_back.f_lineno}): {msg_str}"
return dbg_str


def write_csv_data_points_to_file(filename, data_points):
"""Global function that is a wrapper around the IV_Swinger function of
the same name.
Expand Down Expand Up @@ -2514,7 +2503,7 @@ def hdd_output_dir(self):

@hdd_output_dir.setter
def hdd_output_dir(self, value):
if value is not None and not os.path.isabs(value):
if value is not None and not value.is_absolute():
raise ValueError("hdd_output_dir must be an absolute path")
self._hdd_output_dir = value

Expand Down Expand Up @@ -3312,8 +3301,7 @@ def arduino_sketch_supports_bandgap_read(self):
def pdf_filename(self):
"""PDF file name"""
dts = extract_date_time_str(self.hdd_output_dir)
pdf_filename = os.path.join(self.hdd_output_dir,
f"{self.file_prefix}{dts}.pdf")
pdf_filename = self.hdd_output_dir / f"{self.file_prefix}{dts}.pdf"
return pdf_filename

# ---------------------------------
Expand All @@ -3323,8 +3311,8 @@ def sensor_info_filename(self):
compatibility"""
if self.hdd_output_dir is not None:
dts = extract_date_time_str(self.hdd_output_dir)
sensor_info_filename = os.path.join(self.hdd_output_dir,
f"sensor_info_{dts}.txt")
sensor_info_filename = (self.hdd_output_dir /
f"sensor_info_{dts}.txt")
else:
sensor_info_filename = None

Expand All @@ -3336,8 +3324,7 @@ def run_info_filename(self):
"""Run information (includes sensor info) file name"""
if self.hdd_output_dir is not None:
dts = extract_date_time_str(self.hdd_output_dir)
run_info_filename = os.path.join(self.hdd_output_dir,
f"run_info_{dts}.txt")
run_info_filename = self.hdd_output_dir / f"run_info_{dts}.txt"
else:
run_info_filename = None

Expand Down Expand Up @@ -4676,7 +4663,7 @@ def find_first_downward_deflection(self, adc_pairs):
if not deflect_begin_found:
dist -= 1
if retry == 0:
err_str = (f"{os.path.basename(self.hdd_output_dir)} "
err_str = (f"{self.hdd_output_dir.name} "
f"find_first_downward_deflection retried too "
f"many times")
self.logger.print_and_log(err_str)
Expand Down Expand Up @@ -4946,9 +4933,8 @@ def get_bias_batt_csv(self):
def remove_prev_bias_battery_csv(self):
"""Method to remove old bias battery CSV file(s) from the parent
directory"""
glob_pattern = "{}/bias_batt_adc_pairs*.csv"
run_dir = os.path.dirname(self.hdd_output_dir)
bb_files = glob.glob(glob_pattern.format(run_dir))
run_dir = self.hdd_output_dir.parent
bb_files = glob.glob(f"{run_dir}/bias_batt_adc_pairs*.csv")
for f in bb_files:
self.clean_up_file(f)

Expand Down Expand Up @@ -4985,16 +4971,15 @@ def create_hdd_output_dir(self, date_time_str, subdir=""):
"""Method to create the HDD output directory"""

# Create the HDD output directory
self.hdd_output_dir = os.path.join(self.root_dir, subdir,
date_time_str)
Path(self.hdd_output_dir).mkdir(parents=True)
self.hdd_output_dir = self.root_dir / subdir / date_time_str
self.hdd_output_dir.mkdir(parents=True)

# -------------------------------------------------------------------------
def copy_file_to_parent(self, filename):
"""Method to copy a file to the IV_Swinger2 directory (parent of
output directory)
"""
run_dir = os.path.dirname(self.hdd_output_dir)
run_dir = self.hdd_output_dir.parent
try:
shutil.copy(filename, run_dir)
except shutil.Error as e:
Expand Down Expand Up @@ -5290,12 +5275,11 @@ def get_csv_filenames(self, csv_dir, date_time_str):
csv_data_pt_leaf_name = f"{self.file_prefix}{date_time_str}.csv"

# Get the full-path names of the HDD output files
unfiltered_adc_csv = os.path.join(csv_dir,
unfiltered_adc_pairs_csv_leaf_name)
unfiltered_adc_csv = csv_dir / unfiltered_adc_pairs_csv_leaf_name
self.hdd_unfiltered_adc_pairs_csv_filename = unfiltered_adc_csv
adc_csv = os.path.join(csv_dir, adc_pairs_csv_leaf_name)
adc_csv = csv_dir / adc_pairs_csv_leaf_name
self.hdd_adc_pairs_csv_filename = adc_csv
csv = os.path.join(csv_dir, csv_data_pt_leaf_name)
csv = csv_dir / csv_data_pt_leaf_name
self.hdd_csv_data_point_filename = csv

# -------------------------------------------------------------------------
Expand Down Expand Up @@ -5504,8 +5488,7 @@ def gen_reference_curve(self):
if pv.cell_temp_c is not None and pv.irradiance is not None:
pv.run()
pv.get_data_points(PV_MODEL_CURVE_NUM_POINTS)
pv.csv_filename = os.path.join(self.hdd_output_dir,
"IV_Swinger2_PV_model.csv")
pv.csv_filename = self.hdd_output_dir / "IV_Swinger2_PV_model.csv"
pv.gen_data_points_csv()
else:
dts = extract_date_time_str(self.hdd_output_dir)
Expand Down Expand Up @@ -5786,7 +5769,7 @@ def main():
ivs2.logger.terminate_log()

# Open the PDF
if Path(ivs2.pdf_filename).exists():
if ivs2.pdf_filename.exists():
sys_view_file(ivs2.pdf_filename)

# Clean up files
Expand Down
35 changes: 12 additions & 23 deletions python3/IV_Swinger2_gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,6 @@
from tkinter.scrolledtext import ScrolledText
from tkinter.constants import N, S, E, W, LEFT, RIGHT, HORIZONTAL, Y, BOTH, END
import traceback
from inspect import currentframe, getframeinfo
from configparser import NoOptionError
import random
import zmq
Expand Down Expand Up @@ -183,6 +182,7 @@
RG_DEFAULT = IV_Swinger2.RG_DEFAULT
SHUNT_DEFAULT = IV_Swinger2.SHUNT_DEFAULT
INFINITE_VAL = IV_Swinger2.INFINITE_VAL
PRINT_DBG_STR = IV_Swinger2.PRINT_DBG_STR

# GUI-specific
VERSION_FILE = "version.txt"
Expand Down Expand Up @@ -250,17 +250,6 @@ def debug_memleak(msg_str):
print(f"{date_time_str}: Memory usage ({msg_str}): {mem_usage}")


def gen_dbg_str(msg_str):
"""Global function to use when debugging. The supplied string is
returned, along with the file name and line number where it is
found in the code.
"""
cf = currentframe()
fi = getframeinfo(cf)
dbg_str = f"DEBUG({fi.filename}, line {cf.f_back.f_lineno}): {msg_str}"
return dbg_str


def get_app_dir():
"""Global function to return the directory where the application is
located, regardless of whether it is a script or a frozen
Expand Down Expand Up @@ -1889,7 +1878,7 @@ def redisplay_img(self, reprocess_adc=False):
self.results_wiz.plot_overlay_and_display()
else:
remove_directory = False
if not Path(self.ivs2.hdd_output_dir).exists():
if not self.ivs2.hdd_output_dir.exists():
if self.ivs2.adc_pairs is None:
# Super obscure case: Generate PV model test curve (which
# has no adc_pairs). Delete run from Wizard. Then make
Expand All @@ -1899,7 +1888,7 @@ def redisplay_img(self, reprocess_adc=False):
# Directory may have been removed if looping so
# re-create it, but remove it after image is displayed
remove_directory = True
Path(self.ivs2.hdd_output_dir).mkdir(parents=True)
self.ivs2.hdd_output_dir.mkdir(parents=True)
reprocess_adc = True
rc = RC_SUCCESS
if reprocess_adc:
Expand Down Expand Up @@ -3232,8 +3221,8 @@ def get_run_dir(self, selection):
"""Method to determine the path to the run directory for the selection
and check that it is really a directory
"""
run_dir = os.path.join(self.results_dir, selection)
if not os.path.isdir(run_dir):
run_dir = self.results_dir / selection
if not run_dir.is_dir():
err_str = f"ERROR: directory {run_dir} does not exist"
self.master.ivs2.logger.print_and_log(err_str)
tkmsg.showerror(message=err_str)
Expand Down Expand Up @@ -3324,19 +3313,19 @@ def change_folder(self, event=None):
options[title_opt] = "Choose Folder"
new_dir = tkfiledialog.askdirectory(**options)
if new_dir:
self.results_dir = os.path.normpath(new_dir)
self.results_dir = Path(new_dir).resolve()
self.populate_tree()
if not self.tree.exists("overlays") and not self.dates:
# If there are no overlays or runs in the specified folder, but
# there is a subfolder named IV_Swinger2 or the parent
# directory is named IV_Swinger2, then assume the user meant to
# select the subfolder or parent folder respectively
ivs2_subdir = os.path.join(self.results_dir, APP_NAME)
parent_dir = os.path.dirname(self.results_dir)
if os.path.isdir(ivs2_subdir):
ivs2_subdir = self.results_dir / APP_NAME
parent_dir = self.results_dir.parent
if ivs2_subdir.is_dir():
self.results_dir = ivs2_subdir
self.populate_tree()
elif os.path.basename(parent_dir) == APP_NAME:
elif parent_dir.name == APP_NAME:
self.results_dir = parent_dir
self.populate_tree()
msg = f"(Wizard) changed folder to {self.results_dir}"
Expand Down Expand Up @@ -3646,15 +3635,15 @@ def get_selected_runs(self, include_whole_days=True):
individual_run = IV_Swinger2.is_date_time_str(selection)
is_date_group = re.compile(r"^(\d{6})$").search(selection)
if individual_run:
selected_runs.append(os.path.join(self.results_dir, selection))
selected_runs.append(self.results_dir / selection)
elif (include_whole_days and is_date_group and not
(IV_Swinger2.is_date_time_str(selections[0]) or
IV_Swinger2.is_date_time_str(selections[-1]))):
# Whole day (but not in the middle of a range of
# individual runs)
for child in self.tree.get_children(selection):
# Add all the day's runs to the list
selected_runs.append(os.path.join(self.results_dir, child))
selected_runs.append(self.results_dir / child)

# Return list with duplicates removed
return list(dict.fromkeys(selected_runs))
Expand Down
3 changes: 2 additions & 1 deletion python3/IV_Swinger2_sim.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@
SHUNT_DEFAULT = IV_Swinger2.SHUNT_DEFAULT
RC_SUCCESS = IV_Swinger2.RC_SUCCESS
RC_FAILURE = IV_Swinger2.RC_FAILURE
PRINT_DBG_STR = IV_Swinger2.PRINT_DBG_STR


########################
Expand Down Expand Up @@ -1345,7 +1346,7 @@ def set_plot_title(self):
def display_pdf(self):
"""Method to display the PDF of the simulated curve
"""
if Path(self.pdf_filename).exists():
if self.pdf_filename.exists():
IV_Swinger2.sys_view_file(self.pdf_filename)

# -------------------------------------------------------------------------
Expand Down

0 comments on commit c316d58

Please sign in to comment.