Skip to content

Commit

Permalink
Add reusable path resolver
Browse files Browse the repository at this point in the history
  • Loading branch information
ahdamin committed Dec 12, 2024
1 parent d7567a0 commit bb8b172
Showing 1 changed file with 57 additions and 109 deletions.
166 changes: 57 additions & 109 deletions microSALT/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,154 +17,102 @@
app.config.setdefault("SQLALCHEMY_BINDS", None)
app.config.setdefault("SQLALCHEMY_TRACK_MODIFICATIONS", False)

# Reusable function for resolving paths
def resolve_path(path):
"""Resolve environment variables, user shortcuts, and absolute paths."""
if path:
path = os.path.expandvars(path) # Expand environment variables like $HOME
path = os.path.expanduser(path) # Expand user shortcuts like ~
path = os.path.abspath(path) # Convert to an absolute path
return path
return path

# Function to create directories if they do not exist
def ensure_directory(path, logger=None):
"""Ensure a directory exists; create it if missing."""
try:
if path and not pathlib.Path(path).exists():
os.makedirs(path, exist_ok=True)
if logger:
logger.info(f"Created path {path}")
except Exception as e:
if logger:
logger.error(f"Failed to create path {path}: {e}")
raise

# Initialize logger
logger = logging.getLogger("main_logger")
logger.setLevel(logging.INFO)
ch = logging.StreamHandler()
ch.setLevel(logging.INFO)
ch.setFormatter(logging.Formatter("%(levelname)s - %(message)s"))
logger.addHandler(ch)

# Keep track of microSALT installation
wd = os.path.dirname(os.path.realpath(__file__))

# Load configuration
preset_config = ""
logger = ""
default = os.path.join(os.environ["HOME"], ".microSALT/config.json")
default_config_path = resolve_path("$HOME/.microSALT/config.json")

if "MICROSALT_CONFIG" in os.environ:
try:
envvar = os.environ["MICROSALT_CONFIG"]
with open(envvar, "r") as conf:
preset_config = json.load(conf)
except Exception as e:
print("Config error: {}".format(str(e)))
pass
elif os.path.exists(default):
logger.error(f"Config error: {e}")
elif os.path.exists(default_config_path):
try:
with open(os.path.abspath(default), "r") as conf:
with open(default_config_path, "r") as conf:
preset_config = json.load(conf)
except Exception as e:
print("Config error: {}".format(str(e)))
pass
logger.error(f"Config error: {e}")

# Config dependent section:
if preset_config != "":
if preset_config:
try:
# Load flask info
# Load Flask info
app.config.update(preset_config["database"])

# Add extrapaths to config
preset_config["folders"]["expec"] = os.path.abspath(
os.path.join(
pathlib.Path(__file__).parent.parent, "unique_references/ExPEC.fsa"
)
preset_config["folders"]["expec"] = resolve_path(
os.path.join(pathlib.Path(__file__).parent.parent, "unique_references/ExPEC.fsa")
)

# Check if release install exists
for entry in os.listdir(get_python_lib()):
if "microSALT-" in entry:
preset_config["folders"]["expec"] = os.path.abspath(
preset_config["folders"]["expec"] = resolve_path(
os.path.join(os.path.expandvars("$CONDA_PREFIX"), "expec/ExPEC.fsa")
)
break
preset_config["folders"]["adapters"] = os.path.abspath(
os.path.join(
os.path.expandvars("$CONDA_PREFIX"),
"share/trimmomatic/adapters/",
)
)

# Initialize logger
logger = logging.getLogger("main_logger")
logger.setLevel(logging.INFO)
ch = logging.StreamHandler()
ch.setLevel(logging.INFO)
ch.setFormatter(logging.Formatter("%(levelname)s - %(message)s"))
logger.addHandler(ch)

# Create paths mentioned in config
db_file = re.search(
"sqlite:///(.+)",
preset_config["database"]["SQLALCHEMY_DATABASE_URI"],
).group(1)
for entry in preset_config.keys():
if entry != "_comment":
if (
isinstance(preset_config[entry], str)
and "/" in preset_config[entry]
and entry not in ["genologics"]
):
if not preset_config[entry].startswith("/"):
sys.exit(-1)
unmade_fldr = os.path.abspath(preset_config[entry])
if not pathlib.Path(unmade_fldr).exists():
os.makedirs(unmade_fldr)
logger.info("Created path {}".format(unmade_fldr))

# level two
elif isinstance(preset_config[entry], collections.Mapping):
for thing in preset_config[entry].keys():
if (
isinstance(preset_config[entry][thing], str)
and "/" in preset_config[entry][thing]
and entry not in ["genologics"]
):
# Special string, mangling
if thing == "log_file":
unmade_fldr = os.path.dirname(
preset_config[entry][thing]
)
bash_cmd = "touch {}".format(
preset_config[entry][thing]
)
proc = subprocess.Popen(
bash_cmd.split(), stdout=subprocess.PIPE
)
output, error = proc.communicate()
elif thing == "SQLALCHEMY_DATABASE_URI":
unmade_fldr = os.path.dirname(db_file)
bash_cmd = "touch {}".format(db_file)
proc = subprocess.Popen(
bash_cmd.split(), stdout=subprocess.PIPE
)
output, error = proc.communicate()
if proc.returncode != 0:
logger.error(
"Database writing failed! Invalid user access detected!"
)
sys.exit(-1)
else:
unmade_fldr = preset_config[entry][thing]
if not pathlib.Path(unmade_fldr).exists():
os.makedirs(unmade_fldr)
logger.info("Created path {}".format(unmade_fldr))

fh = logging.FileHandler(
os.path.expanduser(preset_config["folders"]["log_file"])
)
fh.setFormatter(
logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
preset_config["folders"]["adapters"] = resolve_path(
os.path.join(os.path.expandvars("$CONDA_PREFIX"), "share/trimmomatic/adapters/")
)
logger.addHandler(fh)

# Integrity check database
cmd = "sqlite3 {0}".format(db_file)
cmd = cmd.split()
cmd.append("pragma integrity_check;")
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
output, error = proc.communicate()
if not "ok" in str(output):
logger.error("Database integrity failed! Lock-state detected!")
sys.exit(-1)

# Load pubmlst configuration
if "pubmlst" not in preset_config:
raise KeyError("Missing 'pubmlst' section in configuration file.")
pubmlst_config = preset_config["pubmlst"]

# Set default for credentials_files_path if missing or empty
credentials_files_path = pubmlst_config.get("credentials_files_path")
if not credentials_files_path:
credentials_files_path = os.getcwd() # Default to current directory
# Set and resolve credentials file path
credentials_files_path = resolve_path(pubmlst_config.get("credentials_files_path", "$HOME/.microSALT"))
pubmlst_config["credentials_files_path"] = credentials_files_path

# Ensure the credentials directory exists
ensure_directory(credentials_files_path, logger)

# Update the app configuration
app.config["pubmlst"] = pubmlst_config

logger.info(f"PubMLST configuration loaded: {app.config['pubmlst']}")
# Log the resolved credentials file path
logger.info(f"PubMLST configuration loaded with credentials_files_path: {credentials_files_path}")

except KeyError as e:
logger.error(f"Configuration error: {e}")
sys.exit(1)
except Exception as e:
print("Config error: {}".format(str(e)))
pass
logger.error(f"Unexpected error: {e}")
sys.exit(1)

0 comments on commit bb8b172

Please sign in to comment.