diff --git a/src/ifcopenshell-python/ifcopenshell/__init__.py b/src/ifcopenshell-python/ifcopenshell/__init__.py index 105cda7542..c8bca746d6 100644 --- a/src/ifcopenshell-python/ifcopenshell/__init__.py +++ b/src/ifcopenshell-python/ifcopenshell/__init__.py @@ -96,7 +96,18 @@ from .file import rocksdb_lazy_instance from .sql import sqlite, sqlite_entity get_log = ifcopenshell_wrapper.get_log -logger = getattr(ifcopenshell_wrapper, "logger", None) +logger = ifcopenshell_wrapper.logger if hasattr(ifcopenshell_wrapper, "logger") else None +if hasattr(ifcopenshell_wrapper, "logger_or_root"): + logger_or_root = ifcopenshell_wrapper.logger_or_root +else: + + def logger_or_root(_logger: ifcopenshell_wrapper.logger | None) -> None: + return None + + +# TODO: drop this function and all callsites after we migrate to the new build. +def optional_logger_args(logger: ifcopenshell_wrapper.logger | None) -> tuple[logger] | tuple[()]: + return (logger,) if logger is not None else () # explicitly specify available imported symbols # (it's a requirement for a typed library) @@ -209,8 +220,7 @@ def open( raise FileNotFoundError(f"Path does not exist: '{path}'.") if format is None: format = guess_format(path) - if logger is None and (logger_type := getattr(ifcopenshell_wrapper, "logger", None)): - logger = logger_type.root() + logger = logger_or_root(logger) if format == ".ifcXML": f = ifcopenshell_wrapper.parse_ifcxml(str(path.absolute()), *((logger,) if logger is not None else ())) if f: @@ -229,11 +239,9 @@ def open( if should_stream: return stream(path) if readonly: # Temporary conditional see #7131. Remove once newer builds don't segfault on Linux. - f = ifcopenshell_wrapper.open(str(path.absolute()), readonly, *((logger,) if logger is not None else ())) + f = ifcopenshell_wrapper.open(str(path.absolute()), readonly, *optional_logger_args(logger)) elif bypass_types: - f = ifcopenshell_wrapper.file( - ifcopenshell_wrapper.uninitialized_tag(), *((logger,) if logger is not None else ()) - ) + f = ifcopenshell_wrapper.file(ifcopenshell_wrapper.uninitialized_tag(), *optional_logger_args(logger)) for ty in bypass_types: f.bypass_type(ty) if mmap: @@ -248,7 +256,7 @@ def open( kwargs["logger"] = logger f = ifcopenshell_wrapper.open(str(path.absolute()), **kwargs) # ty: ignore[unknown-argument] else: - f = ifcopenshell_wrapper.open(str(path.absolute()), False, *((logger,) if logger is not None else ())) + f = ifcopenshell_wrapper.open(str(path.absolute()), False, *optional_logger_args(logger)) f.post_init() diff --git a/src/ifcopenshell-python/ifcopenshell/draw.py b/src/ifcopenshell-python/ifcopenshell/draw.py index cd37cf6a96..82a94b6e0e 100644 --- a/src/ifcopenshell-python/ifcopenshell/draw.py +++ b/src/ifcopenshell-python/ifcopenshell/draw.py @@ -106,8 +106,7 @@ def main( progress_function: Callable = DO_NOTHING, logger=None, ): - if logger is None and ifcopenshell.logger is not None: - logger = ifcopenshell.logger.root() + logger = ifcopenshell.logger_or_root(logger) def by_guid(g): for f in files: @@ -533,7 +532,7 @@ def main( arranged = W.arrange_polygons( *filter(None, (ARRANGE_POLYGON_SETTINGS,)), polies, # ty: ignore[too-many-positional-arguments] - *((logger,) if logger is not None else ()), + *ifcopenshell.optional_logger_args(logger), ) svg_data_3 = W.polygons_to_svg(arranged, False) dom3 = parseString(svg_data_3) diff --git a/src/ifcopenshell-python/ifcopenshell/geom/main.py b/src/ifcopenshell-python/ifcopenshell/geom/main.py index 5aca7d84f3..335e0a6f58 100644 --- a/src/ifcopenshell-python/ifcopenshell/geom/main.py +++ b/src/ifcopenshell-python/ifcopenshell/geom/main.py @@ -23,6 +23,8 @@ from collections.abc import Generator, Iterable from os import PathLike, fspath from typing import TYPE_CHECKING, Any, Literal, Optional, TypeVar, Union, cast, overload +import ifcopenshell + from .. import ifcopenshell_wrapper, open from .. import entity_instance from .. import file @@ -303,8 +305,7 @@ class iterator(ifcopenshell_wrapper.Iterator): logger=None, ): self.settings = settings - if logger is None and (logger_type := getattr(ifcopenshell_wrapper, "logger", None)): - logger = logger_type.root() + logger = ifcopenshell.logger_or_root(logger) if isinstance(file_or_filename, file): self.file = file file_or_filename = file_or_filename @@ -345,10 +346,10 @@ class iterator(ifcopenshell_wrapper.Iterator): include is not None, num_threads, ) - self.this = initializer(*args, *((logger,) if logger is not None else ())) + self.this = initializer(*args, *ifcopenshell.optional_logger_args(logger)) else: args = (geometry_library, self.settings, file_or_filename, num_threads) - self.this = ifcopenshell_wrapper.construct_iterator(*args, *((logger,) if logger is not None else ())) + self.this = ifcopenshell_wrapper.construct_iterator(*args, *ifcopenshell.optional_logger_args(logger)) if has_occ: @@ -509,9 +510,9 @@ def create_shape( return wrap_shape_creation( settings, ( - ifcopenshell_wrapper.create_shape(settings, inst, repr, geometry_library, *((logger,) if logger is not None else ()),) + ifcopenshell_wrapper.create_shape(settings, inst, repr, geometry_library, *ifcopenshell.optional_logger_args(logger),) if repr - else ifcopenshell_wrapper.create_shape(settings, inst, geometry_library, *((logger,) if logger is not None else ()),) + else ifcopenshell_wrapper.create_shape(settings, inst, geometry_library, *ifcopenshell.optional_logger_args(logger),) ), ) diff --git a/src/ifcopenshell-python/ifcopenshell/ifcopenshell_wrapper.pyi b/src/ifcopenshell-python/ifcopenshell/ifcopenshell_wrapper.pyi index 0bbea08b65..768419e5de 100644 --- a/src/ifcopenshell-python/ifcopenshell/ifcopenshell_wrapper.pyi +++ b/src/ifcopenshell-python/ifcopenshell/ifcopenshell_wrapper.pyi @@ -1074,6 +1074,52 @@ class line_segment: def size(self): ... def swap(self, v): ... +class log_message: + code: Any + instance: Any + message: Any + product: Any + severity: Any + timestamp: Any + + def __init__(self, *args): ... + @property + def severity_string(self): ... + def to_dict(self): ... + def to_tuple(self): ... + +class logger: + FMT_PLAIN: Literal[0] + FMT_JSON: Literal[1] + FMT_INMEMORY: Literal[2] + + LOG_PERF: Literal[0] + LOG_DEBUG: Literal[1] + LOG_NOTICE: Literal[2] + LOG_WARNING: Literal[3] + LOG_ERROR: Literal[4] + + @staticmethod + def root() -> logger: ... + def append(self, other): ... + def count(self, code): ... + def clear(self): ... + def error(self, *args): ... + def get_log(self): ... + def max_severity(self): ... + def message(self, *args): ... + def notice(self, *args): ... + def output_format(self, *args): ... + def print_performance_stats(self): ... + def print_performance_stats_on_element(self, *args): ... + def progress_bar(self, progress): ... + def set_output(self, *args): ... + def set_product(self, *args): ... + def status(self, message, new_line=True): ... + def verbosity(self, *args): ... + def warning(self, *args): ... + def log_messages(self) -> tuple[log_message, ...]: ... + class loft: axis: Any def calc_hash(self): ... diff --git a/src/ifcopenshell-python/test/test_create_shape.py b/src/ifcopenshell-python/test/test_create_shape.py index bda6767295..e40570d161 100644 --- a/src/ifcopenshell-python/test/test_create_shape.py +++ b/src/ifcopenshell-python/test/test_create_shape.py @@ -217,6 +217,7 @@ def test_iterator(): def test_logging(): + assert ifcopenshell.logger logger = ifcopenshell.logger() logger.OutputFormat(logger.FMT_INMEMORY) settings = ifcopenshell.geom.settings()