From 68ef09456ee3f89135412543006ff0fb4ea5e742 Mon Sep 17 00:00:00 2001 From: wajcha Date: Tue, 10 Oct 2023 12:14:19 +0200 Subject: [PATCH 01/11] Implement exception-free mode for Metadata Containers --- src/neptune/__init__.py | 39 ++++++++++++++-- src/neptune/envs.py | 3 ++ .../metadata_containers/safe_container.py | 46 +++++++++++++++++++ 3 files changed, 84 insertions(+), 4 deletions(-) create mode 100644 src/neptune/metadata_containers/safe_container.py diff --git a/src/neptune/__init__.py b/src/neptune/__init__.py index bbefe37b5..20b383fff 100644 --- a/src/neptune/__init__.py +++ b/src/neptune/__init__.py @@ -101,21 +101,52 @@ "__version__", ] +import os +from typing import ( + Any, + Union, +) from neptune.common.patches import apply_patches from neptune.constants import ANONYMOUS_API_TOKEN +from neptune.envs import NEPTUNE_SAFETY_MODE from neptune.metadata_containers import ( + MetadataContainer, Model, ModelVersion, Project, Run, ) +from neptune.metadata_containers.safe_container import SafeContainer from neptune.version import __version__ # Apply patches of external libraries apply_patches() -init_run = Run -init_model = Model -init_model_version = ModelVersion -init_project = Project + +def _init_safety(obj: MetadataContainer) -> Union[MetadataContainer, SafeContainer]: + safety_mode = os.environ.get(NEPTUNE_SAFETY_MODE) + if safety_mode is not None and bool(safety_mode) and str(safety_mode).lower() != "false" and int(safety_mode) != 0: + return obj + else: + return SafeContainer(obj) + + +def init_run(*args: Any, **kwargs: Any) -> Union[MetadataContainer, SafeContainer]: + obj = Run(*args, **kwargs) + return _init_safety(obj) + + +def init_model(*args: Any, **kwargs: Any) -> Union[MetadataContainer, SafeContainer]: + obj = Model(*args, **kwargs) + return _init_safety(obj) + + +def init_model_version(*args: Any, **kwargs: Any) -> Union[MetadataContainer, SafeContainer]: + obj = ModelVersion(*args, **kwargs) + return _init_safety(obj) + + +def init_project(*args: Any, **kwargs: Any) -> Union[MetadataContainer, SafeContainer]: + obj = Project(*args, **kwargs) + return _init_safety(obj) diff --git a/src/neptune/envs.py b/src/neptune/envs.py index 31bc2e144..9cec19ac5 100644 --- a/src/neptune/envs.py +++ b/src/neptune/envs.py @@ -19,6 +19,7 @@ "PROJECT_ENV_NAME", "CUSTOM_RUN_ID_ENV_NAME", "MONITORING_NAMESPACE", + "NEPTUNE_SAFETY_MODE", "NEPTUNE_ALLOW_SELF_SIGNED_CERTIFICATE", "NEPTUNE_NOTEBOOK_ID", "NEPTUNE_NOTEBOOK_PATH", @@ -48,6 +49,8 @@ MONITORING_NAMESPACE = "NEPTUNE_MONITORING_NAMESPACE" +NEPTUNE_SAFETY_MODE = "NEPTUNE_SAFETY_MODE" + NEPTUNE_ALLOW_SELF_SIGNED_CERTIFICATE = "NEPTUNE_ALLOW_SELF_SIGNED_CERTIFICATE" NEPTUNE_NOTEBOOK_ID = "NEPTUNE_NOTEBOOK_ID" diff --git a/src/neptune/metadata_containers/safe_container.py b/src/neptune/metadata_containers/safe_container.py new file mode 100644 index 000000000..f361a6907 --- /dev/null +++ b/src/neptune/metadata_containers/safe_container.py @@ -0,0 +1,46 @@ +# +# Copyright (c) 2022, Neptune Labs Sp. z o.o. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +__all__ = ["SafeContainer"] + +from typing import ( + Any, + Callable, +) + +from neptune.internal.utils.logger import logger +from neptune.metadata_containers import MetadataContainer + + +class SafeMethodWrapper: + def __init__(self, method: Callable): + self._method = method + + def __call__(self, *args: Any, **kwargs: Any) -> Any: + try: + return self._method(*args, **kwargs) + except Exception: + logger.exception(f"Exception in method {self._method}") + + def __getattr__(self, item: str) -> Any: + return getattr(self._api_method, item) + + +class SafeContainer: + def __init__(self, container: MetadataContainer): + self._container = container + + def __getattr__(self, item: str) -> Any: + return SafeMethodWrapper(getattr(self._container, item)) From ba146fee080a1aaa18c66b4f01167488cef157b2 Mon Sep 17 00:00:00 2001 From: wajcha Date: Tue, 10 Oct 2023 12:22:06 +0200 Subject: [PATCH 02/11] Fix condition --- src/neptune/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neptune/__init__.py b/src/neptune/__init__.py index 20b383fff..488485785 100644 --- a/src/neptune/__init__.py +++ b/src/neptune/__init__.py @@ -126,7 +126,7 @@ def _init_safety(obj: MetadataContainer) -> Union[MetadataContainer, SafeContainer]: safety_mode = os.environ.get(NEPTUNE_SAFETY_MODE) - if safety_mode is not None and bool(safety_mode) and str(safety_mode).lower() != "false" and int(safety_mode) != 0: + if safety_mode is None or not bool(safety_mode) or str(safety_mode).lower() == "false" or int(safety_mode) == 0: return obj else: return SafeContainer(obj) From 73ee90abe526fc74d361c20a040c435435a07dd5 Mon Sep 17 00:00:00 2001 From: Patryk Gala Date: Tue, 10 Oct 2023 13:50:03 +0200 Subject: [PATCH 03/11] Draft --- src/neptune/__init__.py | 50 +++++++++---------- .../metadata_containers/safe_container.py | 33 ++++++------ 2 files changed, 40 insertions(+), 43 deletions(-) diff --git a/src/neptune/__init__.py b/src/neptune/__init__.py index 488485785..3e1f3d475 100644 --- a/src/neptune/__init__.py +++ b/src/neptune/__init__.py @@ -104,7 +104,7 @@ import os from typing import ( Any, - Union, + Union, Optional, List, ) from neptune.common.patches import apply_patches @@ -117,36 +117,34 @@ Project, Run, ) -from neptune.metadata_containers.safe_container import SafeContainer +from neptune.metadata_containers.abstract import NeptuneObjectCallback +from neptune.metadata_containers.safe_container import decorator_safety +from neptune.types import GitRef +from neptune.types.atoms.git_ref import GitRefDisabled from neptune.version import __version__ # Apply patches of external libraries apply_patches() -def _init_safety(obj: MetadataContainer) -> Union[MetadataContainer, SafeContainer]: - safety_mode = os.environ.get(NEPTUNE_SAFETY_MODE) - if safety_mode is None or not bool(safety_mode) or str(safety_mode).lower() == "false" or int(safety_mode) == 0: - return obj - else: - return SafeContainer(obj) +def init_run(*args: Any, **kwargs: Any) -> Union[MetadataContainer, Run]: + @decorator_safety + class SafeRun(Run): + pass + obj = SafeRun(*args, **kwargs) + return obj -def init_run(*args: Any, **kwargs: Any) -> Union[MetadataContainer, SafeContainer]: - obj = Run(*args, **kwargs) - return _init_safety(obj) - - -def init_model(*args: Any, **kwargs: Any) -> Union[MetadataContainer, SafeContainer]: - obj = Model(*args, **kwargs) - return _init_safety(obj) - - -def init_model_version(*args: Any, **kwargs: Any) -> Union[MetadataContainer, SafeContainer]: - obj = ModelVersion(*args, **kwargs) - return _init_safety(obj) - - -def init_project(*args: Any, **kwargs: Any) -> Union[MetadataContainer, SafeContainer]: - obj = Project(*args, **kwargs) - return _init_safety(obj) +# def init_model(*args: Any, **kwargs: Any) -> Union[MetadataContainer, SafeContainer]: +# obj = Model(*args, **kwargs) +# return _init_safety(obj) +# +# +# def init_model_version(*args: Any, **kwargs: Any) -> Union[MetadataContainer, SafeContainer]: +# obj = ModelVersion(*args, **kwargs) +# return _init_safety(obj) +# +# +# def init_project(*args: Any, **kwargs: Any) -> Union[MetadataContainer, SafeContainer]: +# obj = Project(*args, **kwargs) +# return _init_safety(obj) diff --git a/src/neptune/metadata_containers/safe_container.py b/src/neptune/metadata_containers/safe_container.py index f361a6907..1c9f782e6 100644 --- a/src/neptune/metadata_containers/safe_container.py +++ b/src/neptune/metadata_containers/safe_container.py @@ -13,34 +13,33 @@ # See the License for the specific language governing permissions and # limitations under the License. # -__all__ = ["SafeContainer"] +__all__ = ["decorator_safety"] +import functools from typing import ( Any, Callable, ) from neptune.internal.utils.logger import logger -from neptune.metadata_containers import MetadataContainer +import inspect -class SafeMethodWrapper: - def __init__(self, method: Callable): - self._method = method - - def __call__(self, *args: Any, **kwargs: Any) -> Any: +def _safe_function(func): + @functools.wraps(func) + def wrapper(*args, **kwargs): try: - return self._method(*args, **kwargs) + return func(*args, **kwargs) except Exception: - logger.exception(f"Exception in method {self._method}") - - def __getattr__(self, item: str) -> Any: - return getattr(self._api_method, item) + logger.exception(f"Exception in method ") + return wrapper -class SafeContainer: - def __init__(self, container: MetadataContainer): - self._container = container - def __getattr__(self, item: str) -> Any: - return SafeMethodWrapper(getattr(self._container, item)) +def decorator_safety(cls): + for name, method in inspect.getmembers(cls): + if (not inspect.ismethod(method) and not inspect.isfunction(method)) or inspect.isbuiltin(method): + continue + print("Decorating function %s" % name) + setattr(cls, name, _safe_function(method)) + return cls From 3bbff8cbb010d3ca8ccd31164b26e3d6aca6eca6 Mon Sep 17 00:00:00 2001 From: Patryk Gala Date: Tue, 10 Oct 2023 14:33:48 +0200 Subject: [PATCH 04/11] chore: implement safe mode for all containers --- src/neptune/__init__.py | 67 +++++++++++++------ .../metadata_containers/safe_container.py | 15 ++--- 2 files changed, 53 insertions(+), 29 deletions(-) diff --git a/src/neptune/__init__.py b/src/neptune/__init__.py index 3e1f3d475..ee64e4740 100644 --- a/src/neptune/__init__.py +++ b/src/neptune/__init__.py @@ -104,7 +104,7 @@ import os from typing import ( Any, - Union, Optional, List, + Union, ) from neptune.common.patches import apply_patches @@ -118,7 +118,7 @@ Run, ) from neptune.metadata_containers.abstract import NeptuneObjectCallback -from neptune.metadata_containers.safe_container import decorator_safety +from neptune.metadata_containers.safe_container import safety_decorator from neptune.types import GitRef from neptune.types.atoms.git_ref import GitRefDisabled from neptune.version import __version__ @@ -126,25 +126,52 @@ # Apply patches of external libraries apply_patches() +SAFETY_MODE = os.getenv(NEPTUNE_SAFETY_MODE, "false").lower() in ("true", "1", "t") + def init_run(*args: Any, **kwargs: Any) -> Union[MetadataContainer, Run]: - @decorator_safety - class SafeRun(Run): - pass + if SAFETY_MODE: - obj = SafeRun(*args, **kwargs) - return obj + @safety_decorator + class SafeRun(Run): + pass -# def init_model(*args: Any, **kwargs: Any) -> Union[MetadataContainer, SafeContainer]: -# obj = Model(*args, **kwargs) -# return _init_safety(obj) -# -# -# def init_model_version(*args: Any, **kwargs: Any) -> Union[MetadataContainer, SafeContainer]: -# obj = ModelVersion(*args, **kwargs) -# return _init_safety(obj) -# -# -# def init_project(*args: Any, **kwargs: Any) -> Union[MetadataContainer, SafeContainer]: -# obj = Project(*args, **kwargs) -# return _init_safety(obj) + return SafeRun(*args, **kwargs) + else: + return Run(*args, **kwargs) + + +def init_model(*args: Any, **kwargs: Any) -> Union[MetadataContainer, Model]: + if SAFETY_MODE: + + @safety_decorator + class SafeModel(Model): + pass + + return SafeModel(*args, **kwargs) + else: + return Model(*args, **kwargs) + + +def init_model_version(*args: Any, **kwargs: Any) -> Union[MetadataContainer, ModelVersion]: + if SAFETY_MODE: + + @safety_decorator + class SafeModelVersion(ModelVersion): + pass + + return SafeModelVersion(*args, **kwargs) + else: + return ModelVersion(*args, **kwargs) + + +def init_project(*args: Any, **kwargs: Any) -> Union[MetadataContainer, Project]: + if SAFETY_MODE: + + @safety_decorator + class SafeProject(Project): + pass + + return SafeProject(*args, **kwargs) + else: + return Project(*args, **kwargs) diff --git a/src/neptune/metadata_containers/safe_container.py b/src/neptune/metadata_containers/safe_container.py index 1c9f782e6..1d1bb06ce 100644 --- a/src/neptune/metadata_containers/safe_container.py +++ b/src/neptune/metadata_containers/safe_container.py @@ -13,16 +13,13 @@ # See the License for the specific language governing permissions and # limitations under the License. # -__all__ = ["decorator_safety"] +__all__ = ["safety_decorator"] import functools -from typing import ( - Any, - Callable, -) +import inspect +from neptune.common.warnings import warn_once from neptune.internal.utils.logger import logger -import inspect def _safe_function(func): @@ -31,15 +28,15 @@ def wrapper(*args, **kwargs): try: return func(*args, **kwargs) except Exception: - logger.exception(f"Exception in method ") + warn_once(f"Exception in method {func}") + logger.debug("In safe mode exception is ignored", exc_info=True) return wrapper -def decorator_safety(cls): +def safety_decorator(cls): for name, method in inspect.getmembers(cls): if (not inspect.ismethod(method) and not inspect.isfunction(method)) or inspect.isbuiltin(method): continue - print("Decorating function %s" % name) setattr(cls, name, _safe_function(method)) return cls From 7fa5f98fad03d742801e467832952c930b5e2cf8 Mon Sep 17 00:00:00 2001 From: Patryk Gala Date: Tue, 10 Oct 2023 14:55:30 +0200 Subject: [PATCH 05/11] chore: implement safe mode for all containers --- src/neptune/__init__.py | 64 ++----------------- src/neptune/metadata_containers/model.py | 2 + .../metadata_containers/model_version.py | 2 + src/neptune/metadata_containers/project.py | 2 + src/neptune/metadata_containers/run.py | 2 + .../metadata_containers/safe_container.py | 24 ++++--- 6 files changed, 28 insertions(+), 68 deletions(-) diff --git a/src/neptune/__init__.py b/src/neptune/__init__.py index ee64e4740..bbefe37b5 100644 --- a/src/neptune/__init__.py +++ b/src/neptune/__init__.py @@ -101,77 +101,21 @@ "__version__", ] -import os -from typing import ( - Any, - Union, -) from neptune.common.patches import apply_patches from neptune.constants import ANONYMOUS_API_TOKEN -from neptune.envs import NEPTUNE_SAFETY_MODE from neptune.metadata_containers import ( - MetadataContainer, Model, ModelVersion, Project, Run, ) -from neptune.metadata_containers.abstract import NeptuneObjectCallback -from neptune.metadata_containers.safe_container import safety_decorator -from neptune.types import GitRef -from neptune.types.atoms.git_ref import GitRefDisabled from neptune.version import __version__ # Apply patches of external libraries apply_patches() -SAFETY_MODE = os.getenv(NEPTUNE_SAFETY_MODE, "false").lower() in ("true", "1", "t") - - -def init_run(*args: Any, **kwargs: Any) -> Union[MetadataContainer, Run]: - if SAFETY_MODE: - - @safety_decorator - class SafeRun(Run): - pass - - return SafeRun(*args, **kwargs) - else: - return Run(*args, **kwargs) - - -def init_model(*args: Any, **kwargs: Any) -> Union[MetadataContainer, Model]: - if SAFETY_MODE: - - @safety_decorator - class SafeModel(Model): - pass - - return SafeModel(*args, **kwargs) - else: - return Model(*args, **kwargs) - - -def init_model_version(*args: Any, **kwargs: Any) -> Union[MetadataContainer, ModelVersion]: - if SAFETY_MODE: - - @safety_decorator - class SafeModelVersion(ModelVersion): - pass - - return SafeModelVersion(*args, **kwargs) - else: - return ModelVersion(*args, **kwargs) - - -def init_project(*args: Any, **kwargs: Any) -> Union[MetadataContainer, Project]: - if SAFETY_MODE: - - @safety_decorator - class SafeProject(Project): - pass - - return SafeProject(*args, **kwargs) - else: - return Project(*args, **kwargs) +init_run = Run +init_model = Model +init_model_version = ModelVersion +init_project = Project diff --git a/src/neptune/metadata_containers/model.py b/src/neptune/metadata_containers/model.py index 69a17bce4..53f7827c6 100644 --- a/src/neptune/metadata_containers/model.py +++ b/src/neptune/metadata_containers/model.py @@ -55,9 +55,11 @@ from neptune.metadata_containers import MetadataContainer from neptune.metadata_containers.abstract import NeptuneObjectCallback from neptune.metadata_containers.metadata_containers_table import Table +from neptune.metadata_containers.safe_container import safety_decorator from neptune.types.mode import Mode +@safety_decorator class Model(MetadataContainer): """Class for registering a model to neptune.ai and retrieving information from it.""" diff --git a/src/neptune/metadata_containers/model_version.py b/src/neptune/metadata_containers/model_version.py index 2ac34c846..f071a56f4 100644 --- a/src/neptune/metadata_containers/model_version.py +++ b/src/neptune/metadata_containers/model_version.py @@ -47,10 +47,12 @@ from neptune.internal.utils.ping_background_job import PingBackgroundJob from neptune.metadata_containers import MetadataContainer from neptune.metadata_containers.abstract import NeptuneObjectCallback +from neptune.metadata_containers.safe_container import safety_decorator from neptune.types.mode import Mode from neptune.types.model_version_stage import ModelVersionStage +@safety_decorator class ModelVersion(MetadataContainer): """Class for managing a version of a neptune.ai model and retrieving information from it.""" diff --git a/src/neptune/metadata_containers/project.py b/src/neptune/metadata_containers/project.py index 055394921..c52ea1047 100644 --- a/src/neptune/metadata_containers/project.py +++ b/src/neptune/metadata_containers/project.py @@ -49,9 +49,11 @@ from neptune.metadata_containers import MetadataContainer from neptune.metadata_containers.abstract import NeptuneObjectCallback from neptune.metadata_containers.metadata_containers_table import Table +from neptune.metadata_containers.safe_container import safety_decorator from neptune.types.mode import Mode +@safety_decorator class Project(MetadataContainer): """Class for tracking and retrieving project-level metadata of a neptune.ai project.""" diff --git a/src/neptune/metadata_containers/run.py b/src/neptune/metadata_containers/run.py index 6033a3b24..dc1fa69d5 100644 --- a/src/neptune/metadata_containers/run.py +++ b/src/neptune/metadata_containers/run.py @@ -92,6 +92,7 @@ from neptune.internal.websockets.websocket_signals_background_job import WebsocketSignalsBackgroundJob from neptune.metadata_containers import MetadataContainer from neptune.metadata_containers.abstract import NeptuneObjectCallback +from neptune.metadata_containers.safe_container import safety_decorator from neptune.types import ( GitRef, StringSeries, @@ -100,6 +101,7 @@ from neptune.types.mode import Mode +@safety_decorator class Run(MetadataContainer): """Starts a tracked run that logs ML model-building metadata to neptune.ai.""" diff --git a/src/neptune/metadata_containers/safe_container.py b/src/neptune/metadata_containers/safe_container.py index 1d1bb06ce..31315e85e 100644 --- a/src/neptune/metadata_containers/safe_container.py +++ b/src/neptune/metadata_containers/safe_container.py @@ -17,14 +17,19 @@ import functools import inspect +import os +from typing import Any from neptune.common.warnings import warn_once +from neptune.envs import NEPTUNE_SAFETY_MODE from neptune.internal.utils.logger import logger +_SAFETY_MODE = os.getenv(NEPTUNE_SAFETY_MODE, "false").lower() in ("true", "1", "t") -def _safe_function(func): + +def _safe_function(func: Any) -> Any: @functools.wraps(func) - def wrapper(*args, **kwargs): + def wrapper(*args: Any, **kwargs: Any) -> Any: try: return func(*args, **kwargs) except Exception: @@ -34,9 +39,12 @@ def wrapper(*args, **kwargs): return wrapper -def safety_decorator(cls): - for name, method in inspect.getmembers(cls): - if (not inspect.ismethod(method) and not inspect.isfunction(method)) or inspect.isbuiltin(method): - continue - setattr(cls, name, _safe_function(method)) - return cls +def safety_decorator(cls: Any) -> Any: + if True: + for name, method in inspect.getmembers(cls): + if (not inspect.ismethod(method) and not inspect.isfunction(method)) or inspect.isbuiltin(method): + continue + setattr(cls, name, _safe_function(method)) + return cls + else: + return cls From c900cc1e370736e9c3eb49bcaccd1639d9fba02e Mon Sep 17 00:00:00 2001 From: Patryk Gala Date: Tue, 10 Oct 2023 14:57:02 +0200 Subject: [PATCH 06/11] chore: implement safe mode for all containers --- .github/workflows/e2e.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 3a7430d3f..3af7aaff1 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -16,6 +16,7 @@ env: ADMIN_USERNAME: ${{ secrets.E2E_ADMIN_USERNAME }} ADMIN_NEPTUNE_API_TOKEN: ${{ secrets.E2E_ADMIN_NEPTUNE_API_TOKEN }} SERVICE_ACCOUNT_NAME: ${{ secrets.E2E_SERVICE_ACCOUNT_NAME }} + NEPTUNE_SAFETY_MODE: "True" jobs: e2e: @@ -26,7 +27,7 @@ jobs: python-version: [ "3.7", "3.10" ] os: [ ubuntu, windows ] include: - - python-version: "3.7.16" + - python-version: "3.7.16" os: macos - python-version: "3.10" os: macos @@ -59,7 +60,7 @@ jobs: python-version: [ "3.7", "3.10" ] os: [ ubuntu, windows ] include: - - python-version: "3.7.16" + - python-version: "3.7.16" os: macos - python-version: "3.10" os: macos @@ -92,7 +93,7 @@ jobs: python-version: [ "3.7", "3.10" ] os: [ ubuntu, windows ] include: - - python-version: "3.7.16" + - python-version: "3.7.16" os: macos - python-version: "3.10" os: macos @@ -128,7 +129,7 @@ jobs: python-version: [ "3.7", "3.10" ] os: [ ubuntu, windows ] include: - - python-version: "3.7.16" + - python-version: "3.7.16" os: macos - python-version: "3.10" os: macos From 57a7f57bcc43d7d4acfb46263984a5f3312b1456 Mon Sep 17 00:00:00 2001 From: Patryk Gala Date: Tue, 10 Oct 2023 15:59:36 +0200 Subject: [PATCH 07/11] chore: implement safe mode for all containers --- src/neptune/metadata_containers/safe_container.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/neptune/metadata_containers/safe_container.py b/src/neptune/metadata_containers/safe_container.py index 31315e85e..b2657736e 100644 --- a/src/neptune/metadata_containers/safe_container.py +++ b/src/neptune/metadata_containers/safe_container.py @@ -32,15 +32,15 @@ def _safe_function(func: Any) -> Any: def wrapper(*args: Any, **kwargs: Any) -> Any: try: return func(*args, **kwargs) - except Exception: - warn_once(f"Exception in method {func}") + except Exception as ex: + warn_once(f"Exception in method {func}: {ex.__class__.__name__}") logger.debug("In safe mode exception is ignored", exc_info=True) return wrapper def safety_decorator(cls: Any) -> Any: - if True: + if _SAFETY_MODE: for name, method in inspect.getmembers(cls): if (not inspect.ismethod(method) and not inspect.isfunction(method)) or inspect.isbuiltin(method): continue From b950898f1650bc7361648889b832fe3257e5a99a Mon Sep 17 00:00:00 2001 From: Patryk Gala Date: Tue, 10 Oct 2023 16:20:36 +0200 Subject: [PATCH 08/11] chore: warn_once log up to 10k messages --- src/neptune/common/warnings.py | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/neptune/common/warnings.py b/src/neptune/common/warnings.py index dbcc509bf..b246e965e 100644 --- a/src/neptune/common/warnings.py +++ b/src/neptune/common/warnings.py @@ -21,6 +21,7 @@ "NeptuneUnsupportedType", ] +import hashlib import os import traceback import warnings @@ -55,16 +56,19 @@ def get_user_code_stack_level(): def warn_once(message: str, *, exception: type(Exception) = None): - if exception is None: - exception = NeptuneDeprecationWarning - - if message not in warned_once: - warnings.warn( - message=message, - category=exception, - stacklevel=get_user_code_stack_level(), - ) - warned_once.add(message) + if len(warned_once) < 1_000: + if exception is None: + exception = NeptuneDeprecationWarning + + message_hash = hashlib.sha256(message.encode("utf-8")).hexdigest() + + if message_hash not in warned_once: + warnings.warn( + message=message, + category=exception, + stacklevel=get_user_code_stack_level(), + ) + warned_once.add(message_hash) def warn_about_unsupported_type(type_str: str): From b22418a31d4a869bf0672e9d3f256dffb9a2d6d1 Mon Sep 17 00:00:00 2001 From: Patryk Gala Date: Tue, 10 Oct 2023 17:42:30 +0200 Subject: [PATCH 09/11] chore: warn_once ignore exceptions --- src/neptune/metadata_containers/safe_container.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/neptune/metadata_containers/safe_container.py b/src/neptune/metadata_containers/safe_container.py index b2657736e..4df9734b8 100644 --- a/src/neptune/metadata_containers/safe_container.py +++ b/src/neptune/metadata_containers/safe_container.py @@ -33,8 +33,11 @@ def wrapper(*args: Any, **kwargs: Any) -> Any: try: return func(*args, **kwargs) except Exception as ex: - warn_once(f"Exception in method {func}: {ex.__class__.__name__}") - logger.debug("In safe mode exception is ignored", exc_info=True) + try: + warn_once(f"Exception in method {func}: {ex.__class__.__name__}") + logger.debug("In safe mode exception is ignored", exc_info=True) + except Exception: + pass return wrapper From 43dc30c7c8b4576d14900c7df0e73293d8810d7c Mon Sep 17 00:00:00 2001 From: Patryk Gala Date: Tue, 10 Oct 2023 17:51:50 +0200 Subject: [PATCH 10/11] chore: warn_once sha256 to python hash --- src/neptune/common/warnings.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/neptune/common/warnings.py b/src/neptune/common/warnings.py index b246e965e..8ec22942b 100644 --- a/src/neptune/common/warnings.py +++ b/src/neptune/common/warnings.py @@ -21,7 +21,6 @@ "NeptuneUnsupportedType", ] -import hashlib import os import traceback import warnings @@ -60,7 +59,7 @@ def warn_once(message: str, *, exception: type(Exception) = None): if exception is None: exception = NeptuneDeprecationWarning - message_hash = hashlib.sha256(message.encode("utf-8")).hexdigest() + message_hash = hash(message) if message_hash not in warned_once: warnings.warn( From 2e93379b966fd980dd81f2c869fe5f4fbbefad12 Mon Sep 17 00:00:00 2001 From: Patryk Gala Date: Tue, 10 Oct 2023 17:55:32 +0200 Subject: [PATCH 11/11] chore: revert gh actions --- .github/workflows/e2e.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 3af7aaff1..3a7430d3f 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -16,7 +16,6 @@ env: ADMIN_USERNAME: ${{ secrets.E2E_ADMIN_USERNAME }} ADMIN_NEPTUNE_API_TOKEN: ${{ secrets.E2E_ADMIN_NEPTUNE_API_TOKEN }} SERVICE_ACCOUNT_NAME: ${{ secrets.E2E_SERVICE_ACCOUNT_NAME }} - NEPTUNE_SAFETY_MODE: "True" jobs: e2e: @@ -27,7 +26,7 @@ jobs: python-version: [ "3.7", "3.10" ] os: [ ubuntu, windows ] include: - - python-version: "3.7.16" + - python-version: "3.7.16" os: macos - python-version: "3.10" os: macos @@ -60,7 +59,7 @@ jobs: python-version: [ "3.7", "3.10" ] os: [ ubuntu, windows ] include: - - python-version: "3.7.16" + - python-version: "3.7.16" os: macos - python-version: "3.10" os: macos @@ -93,7 +92,7 @@ jobs: python-version: [ "3.7", "3.10" ] os: [ ubuntu, windows ] include: - - python-version: "3.7.16" + - python-version: "3.7.16" os: macos - python-version: "3.10" os: macos @@ -129,7 +128,7 @@ jobs: python-version: [ "3.7", "3.10" ] os: [ ubuntu, windows ] include: - - python-version: "3.7.16" + - python-version: "3.7.16" os: macos - python-version: "3.10" os: macos