Skip to content

Commit 20590fe

Browse files
authored
Merge pull request #19 from MC-kit/devel
Devel
2 parents 04b0212 + 8641be6 commit 20590fe

20 files changed

+502
-87
lines changed

dev/reset-pyenv

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
#!/bin/bash
22

3-
set -exu
3+
# set -exu
44

55
pyenv virtualenv-delete -f mapstp
6-
pyenv virtualenv 3.9.7 mapstp
6+
pyenv virtualenv 3.10.0 mapstp
77
poetry install
88
pyenv rehash
99
mapstp --version

poetry.lock

+35-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "mapstp"
3-
version = "0.3.1"
3+
version = "0.3.2"
44
description = "Transfers meta information from STP to MCNP"
55
authors = ["dvp <[email protected]>"]
66
homepage = "https://github.com/MC-kit/map-stp"
@@ -38,6 +38,7 @@ click = "^8.0.1"
3838
pandas = "^1.3.4"
3939
openpyxl = "^3.0.9"
4040
numpy = "^1.21.4"
41+
loguru = "^0.5.3"
4142

4243
[tool.poetry.dev-dependencies]
4344
pytest = "^6.2.5"

src/mapstp/cli/logging.py

+45
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,15 @@
33
See https://github.com/Delgan/loguru
44
55
"""
6+
from typing import Final, Optional
7+
68
import logging
9+
import sys
10+
11+
from pathlib import Path
712

813
from loguru import logger
14+
from mapstp.config import env
915

1016
# class PropagateHandler(logging.Handler):
1117
# """Send events from loguru to standard logging"""
@@ -47,3 +53,42 @@ def emit(self, record: logging.LogRecord) -> None:
4753
# log.setLevel(0)
4854
log.addHandler(InterceptHandler())
4955
# logging.basicConfig(handlers=[InterceptHandler()], level=0, style='{')
56+
57+
# from loguru._defaults.py
58+
# "<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | "
59+
# "<level>{level: <8}</level> | "
60+
# "<cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>",
61+
62+
MAPSTP_CONSOLE_LOG_FORMAT: Final[str] = env(
63+
"MAPSTP_CONSOLE_LOG_FORMAT",
64+
default="<green>{time:YYYY-MM-DD HH:mm:ss}</green> | "
65+
"<level>{level: <8}</level> | "
66+
"<level>{message}</level>",
67+
)
68+
MAPSTP_FILE_LOG_PATH: Final[Path] = env(
69+
"MAPSTP_FILE_LOG_PATH", type_=Path, default="mapstp.log"
70+
)
71+
72+
73+
def init_logger(
74+
*,
75+
stderr_format: Optional[str] = MAPSTP_CONSOLE_LOG_FORMAT,
76+
log_path: Optional[Path] = MAPSTP_FILE_LOG_PATH,
77+
) -> None:
78+
"""Configure logger with given parameters.
79+
80+
Args:
81+
stderr_format: log message format for stderr handler, if None, no stderr logging.
82+
log_path: path to file for logging, if None, no file logging.
83+
"""
84+
logger.remove()
85+
if stderr_format:
86+
logger.add(
87+
sys.stderr,
88+
format=stderr_format,
89+
level="INFO",
90+
backtrace=False,
91+
diagnose=False,
92+
)
93+
if log_path:
94+
logger.add(log_path, rotation="100 MB", backtrace=True, diagnose=True)

src/mapstp/cli/runner.py

+9-50
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
of STP paths to STP components, corresponding to cells
55
in MCNP model, would it be generated from the STP with SuperMC.
66
7-
The excel also contains material numbers, densities, correction factors,
7+
The Excel also contains material numbers, densities, correction factors,
88
and RWCL id. The values can be specified in the names of STP
99
components as special tags. A tag is denoted with bracket enclosed
1010
specification at the end of component name: "Component name [<spec>]".
@@ -27,42 +27,15 @@
2727

2828
from mapstp import __name__ as package_name
2929
from mapstp import __summary__, __version__
30+
from mapstp.cli.logging import init_logger, logger
3031
from mapstp.excel import create_excel
3132
from mapstp.materials import get_used_materials, load_materials_map
3233
from mapstp.merge import correct_start_cell_number, join_paths, merge_paths
3334
from mapstp.utils.io import can_override, select_output
34-
35-
# TODO dvp: add customized configuring from a configuration toml-file.
3635
from mapstp.workflow import create_path_info
3736

38-
# from .logging import logger
39-
# from click_loguru import ClickLoguru
40-
41-
42-
# LOG_FILE_RETENTION = 3
43-
# NO_LEVEL_BELOW = 30
44-
#
45-
#
46-
# def stderr_log_format_func(msg_dict):
47-
# """Do level-sensitive formatting.
48-
#
49-
# Just a copy from click-loguru so far."""
50-
#
51-
# if msg_dict["level"].no < NO_LEVEL_BELOW:
52-
# return "<level>{message}</level>\n"
53-
# return "<level>{level}</level>: <level>{message}</level>\n"
54-
#
55-
#
56-
# click_loguru = ClickLoguru(
57-
# NAME,
58-
# VERSION,
59-
# stderr_format_func=stderr_log_format_func,
60-
# retention=LOG_FILE_RETENTION,
61-
# log_dir_parent=".logs",
62-
# timer_log_level="info",
63-
# )
64-
6537

38+
# TODO dvp: add customized configuring from a configuration toml-file.
6639
@dataclass
6740
class Config:
6841
override: bool = False
@@ -83,13 +56,7 @@ class Config:
8356
"""
8457

8558

86-
# @click_loguru.logging_options
87-
# @click.group(help=meta.__summary__, name=NAME)
88-
89-
9059
@click.command(help=_USAGE, name=package_name)
91-
# @click_loguru.init_logger()
92-
# @click_loguru.stash_subcommand()
9360
@click.option(
9461
"--override/--no-override",
9562
default=False,
@@ -154,9 +121,8 @@ class Config:
154121
required=False,
155122
)
156123
@click.version_option(__version__, prog_name=package_name)
157-
# @logger.catch(reraise=True)
124+
@click.help_option()
158125
@click.pass_context
159-
# ctx, verbose: bool, quiet: bool, logfile: bool, profile_mem: bool, override: bool
160126
def mapstp(
161127
ctx,
162128
override: bool,
@@ -190,16 +156,9 @@ def mapstp(
190156
raise click.UsageError(
191157
"Nor `excel`, neither `mcnp` parameter is specified - nothing to do"
192158
)
193-
# if quiet:
194-
# logger.level("WARNING")
195-
# if verbose:
196-
# logger.level("TRACE")
197-
# logger.info("Running {}", NAME)
198-
# logger.debug("Working dir {}", Path(".").absolute())
199-
200-
#
159+
init_logger()
160+
logger.info("Running mapstp {}", __version__)
201161
cfg = ctx.ensure_object(Config)
202-
# obj["DEBUG"] = debug
203162
cfg.override = override
204163
paths, path_info = create_path_info(materials_index, stp)
205164
materials_map = load_materials_map(materials) if materials else None
@@ -208,6 +167,7 @@ def mapstp(
208167
)
209168
if mcnp:
210169
_mcnp = Path(mcnp)
170+
logger.info("Tagging model {}", mcnp)
211171
with select_output(override, output) as _output:
212172
joined_paths = join_paths(paths, separator)
213173
merge_paths(_output, joined_paths, path_info, _mcnp, used_materials_text)
@@ -216,9 +176,8 @@ def mapstp(
216176
_excel = Path(excel)
217177
can_override(_excel, override)
218178
create_excel(_excel, paths, path_info, separator, start_cell_number)
219-
220-
221-
# TODO dvp: add logging
179+
logger.info("Accompanying excel is saved to {}", _excel)
180+
logger.success("mapstp finished")
222181

223182

224183
if __name__ == "__main__":

src/mapstp/config.py

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
"""Configuration tools."""
2+
3+
from typing import Any, Type
4+
5+
from os import environ
6+
7+
8+
def _make_bool(key: str, val: str) -> bool:
9+
val = val.lower()
10+
if val in ["1", "true", "yes", "y", "ok", "on"]:
11+
return True
12+
if val in ["0", "false", "no", "n", "nok", "off"]:
13+
return False
14+
raise ValueError(
15+
f"Invalid environment variable '{key}': expected a boolean, found '{val}'"
16+
)
17+
18+
19+
def _make_int(key: str, val: str) -> int:
20+
try:
21+
return int(val)
22+
except ValueError:
23+
raise ValueError(
24+
f"Invalid environment variable '{key}': expected an integer, found '{val}'"
25+
) from None
26+
27+
28+
def _make_float(key: str, val: str) -> float:
29+
try:
30+
return float(val)
31+
except ValueError:
32+
raise ValueError(
33+
f"Invalid environment variable '{key}': expected a float, found '{val}'"
34+
) from None
35+
36+
37+
def env(key: str, type_: Type[Any] = str, default: Any = None) -> Any:
38+
"""Retrieve environment variable and convert to specified type with proper diagnostics.
39+
40+
Args:
41+
key: environment variable name
42+
type_: type to convert to
43+
default: value to use, if there are no variable with the name `key`
44+
45+
Returns:
46+
Loaded value converted to `type_` or default.
47+
48+
Raises:
49+
ValueError: if conversion is not possible.
50+
"""
51+
if key not in environ:
52+
return default
53+
54+
val = environ[key]
55+
56+
if type_ == str:
57+
return val
58+
59+
if type_ == bool:
60+
return _make_bool(key, val)
61+
62+
if type_ == int:
63+
return _make_int(key, val)
64+
65+
if type_ == float:
66+
return _make_float(key, val)
67+
68+
try:
69+
return type_(val)
70+
except ValueError:
71+
raise ValueError(
72+
f"Invalid environment variable '{key}': conversion {type_.__name__}({val}) failed."
73+
) from None
74+
75+
76+
# MAPSTP_AUTOINIT: Final[bool] = env("MAPSTP_AUTOINIT", bool, True)

0 commit comments

Comments
 (0)