diff --git a/README.md b/README.md index 51263d6..6ccce5c 100644 --- a/README.md +++ b/README.md @@ -217,7 +217,7 @@ for your patience on that one. ## :wave: Getting Help -Security reports go through [private vulnerability reporting](https://github.com/deeplime-io/onecode/security/advisories/new). See [SECURITY.md](SECURITY.md). Security fixes are published for the maintained `1.x` line. +Security reports go through [private vulnerability reporting](https://github.com/deeplime-io/onecode/security/advisories/new). See [SECURITY.md](https://github.com/deeplime-io/onecode/security/policy). Security fixes are published for the maintained `1.x` line. Issues labeled [`cra-vulnerability`](https://github.com/deeplime-io/onecode/issues?q=is%3Aissue+is%3Aopen+label%3Acra-vulnerability) come from the dependency scan. They are not the place to disclose a new flaw. diff --git a/docs/changelogs/1.3.0.md b/docs/changelogs/1.3.0.md index 5d34ce2..eccc4b2 100644 --- a/docs/changelogs/1.3.0.md +++ b/docs/changelogs/1.3.0.md @@ -1,4 +1,4 @@ - + ## Bug Fixes diff --git a/onecode/base/logger.py b/onecode/base/logger.py index 02857bf..e0f6968 100644 --- a/onecode/base/logger.py +++ b/onecode/base/logger.py @@ -82,14 +82,19 @@ def format( class Logger(metaclass=Singleton): """ Single Logger object to handle Python logging within OneCode projects. - The default logging level is INFO. See [`set_level()`][onecode.Logger.set_level] to change it. - Use the static methods [`debug()`][onecode.Logger.debug], [`info()`][onecode.Logger.info], - [`warning()`][onecode.Logger.warning], [`error()`][onecode.Logger.error], and - [`critical()`][onecode.Logger.critical] to conveniently log your messages with the - corresponding logging level. + The default logging level is INFO. See + [`set_level()`][onecode.base.logger.Logger.set_level] to change it. + Use the static methods + [`debug()`][onecode.base.logger.Logger.debug], + [`info()`][onecode.base.logger.Logger.info], + [`warning()`][onecode.base.logger.Logger.warning], + [`error()`][onecode.base.logger.Logger.error], and + [`critical()`][onecode.base.logger.Logger.critical] + to conveniently log your messages with the corresponding logging level. By default, the ColoredFormatter is used. You may add other logging handlers using - [`add_handler()`][onecode.Logger.add_handler], for instance to redirect logs to a file. + [`add_handler()`][onecode.base.logger.Logger.add_handler], + for instance to redirect logs to a file. !!! example ```py @@ -194,9 +199,12 @@ def logger( ) -> logging.Logger: """ Get the Python Logger object corresponding to the given stack level. Preferentially use - convenience methods [`debug()`][onecode.Logger.debug], [`info()`][onecode.Logger.info], - [`warning()`][onecode.Logger.warning], [`error()`][onecode.Logger.error], and - [`critical()`][onecode.Logger.critical]. + convenience methods + [`debug()`][onecode.base.logger.Logger.debug], + [`info()`][onecode.base.logger.Logger.info], + [`warning()`][onecode.base.logger.Logger.warning], + [`error()`][onecode.base.logger.Logger.error], and + [`critical()`][onecode.base.logger.Logger.critical]. Args: stacklevel: Number of hops back in the function call stack to tie the logger to. @@ -214,7 +222,7 @@ def logger( def _flush() -> None: """ Force flush to stdout if `ConfigOption.FLUSH_STDOUT` is True. See - [Project.config][onecode.Project.config] for more information. + [Project.config][onecode.base.project.Project.config] for more information. """ if Project().get_config(ConfigOption.FLUSH_STDOUT): diff --git a/onecode/base/project.py b/onecode/base/project.py index 9240e68..7f2bdda 100644 --- a/onecode/base/project.py +++ b/onecode/base/project.py @@ -20,7 +20,7 @@ class Project(metaclass=Singleton): parameter values, registered elements, flow currently running, current running mode, etc. - See [`reset()`][onecode.Project.reset] for Project default's initialization. + See [`reset()`][onecode.base.project.Project.reset] for Project default's initialization. Attributes: registered_elements: List of elements registered for processing. @@ -182,8 +182,9 @@ def current_flow( @property def data_root(self) -> str: """ - Get the path to the root of the data folder. See [`reset()`][onecode.Project.reset] to know - how the data path is initialized. + Get the path to the root of the data folder. See + [`reset()`][onecode.base.project.Project.reset] + to know how the data path is initialized. """ return self._data_root diff --git a/pyproject.toml b/pyproject.toml index e6c6ded..6a2acbf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -88,6 +88,11 @@ onecode-check = 'onecode.cli.check:main' requires = ["poetry-core>=1.0.0"] build-backend = "poetry.core.masonry.api" +[tool.pytest.ini_options] +# datatest 0.11's plugin probes pytest internals that moved in pytest 7+ and +# warns on every xdist worker. Tests only use datatest.working_directory. +addopts = "-p no:datatest" + [tool.ruff] line-length = 100 target-version = "py311" diff --git a/tests/unit/base/test_run_project.py b/tests/unit/base/test_run_project.py index a743c37..373204e 100644 --- a/tests/unit/base/test_run_project.py +++ b/tests/unit/base/test_run_project.py @@ -80,14 +80,15 @@ def write_output(data, flow_name): def _process_class(): - # Linux 3.14's default fork server keeps the environment from the first - # worker, so a later run still sees a deleted data path. Fork sees the - # current ONECODE_PROJECT_DATA. Every other platform keeps Process, which - # is the start method these tests have always used. + # Fork from this multi-threaded pytest process warns, and can deadlock. + # Linux 3.14's fork server also keeps ONECODE_PROJECT_DATA from the first + # worker. Spawn starts a fresh interpreter with the current environment. + # Windows and macOS already default to spawn; a second spawn context drops + # workers there, so those platforms keep Process. ctx = multiprocessing.get_context() - if type(ctx).__name__ == "ForkServerContext": - return multiprocessing.get_context("fork").Process - return multiprocessing.Process + if type(ctx).__name__ == "SpawnContext": + return multiprocessing.Process + return multiprocessing.get_context("spawn").Process def run(): @@ -148,14 +149,15 @@ def write_output(data, flow_name): def _process_class(): - # Linux 3.14's default fork server keeps the environment from the first - # worker, so a later run still sees a deleted data path. Fork sees the - # current ONECODE_PROJECT_DATA. Every other platform keeps Process, which - # is the start method these tests have always used. + # Fork from this multi-threaded pytest process warns, and can deadlock. + # Linux 3.14's fork server also keeps ONECODE_PROJECT_DATA from the first + # worker. Spawn starts a fresh interpreter with the current environment. + # Windows and macOS already default to spawn; a second spawn context drops + # workers there, so those platforms keep Process. ctx = multiprocessing.get_context() - if type(ctx).__name__ == "ForkServerContext": - return multiprocessing.get_context("fork").Process - return multiprocessing.Process + if type(ctx).__name__ == "SpawnContext": + return multiprocessing.Process + return multiprocessing.get_context("spawn").Process def run():