From 5c18390bf29760208bd0fc081b74884ad39d22ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Tue, 25 Feb 2025 10:47:58 +0100 Subject: [PATCH 1/7] Don't update signature when not in IPython environment --- param/parameterized.py | 4 ++++ tests/conftest.py | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/param/parameterized.py b/param/parameterized.py index 964cc390..0d17915d 100644 --- a/param/parameterized.py +++ b/param/parameterized.py @@ -10,6 +10,7 @@ import asyncio import copy +import builtins import datetime as dt import html import inspect @@ -996,6 +997,9 @@ def _modified_slots_defaults(cls): @classmethod def __init_subclass__(cls): super().__init_subclass__() + # Only update signature in an IPython environment + if not hasattr(builtins, "__IPYTHON__"): + return # _update_signature has been tested against the Parameters available # in Param, we don't want to break the Parameters created elsewhere # so wrapping this in a loose try/except. diff --git a/tests/conftest.py b/tests/conftest.py index b172cd70..2ffe1096 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,3 +1,7 @@ +import builtins + +builtins.__IPYTHON__ = True # To force signature in _ParameterBase.__init_subclass__ + import param import pytest From 7662693d8d767c5c65061c88b5db7c6b8787301b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Tue, 25 Feb 2025 11:08:33 +0100 Subject: [PATCH 2/7] Fix test with coverage enabled --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 5bba09eb..6d90cff6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -120,7 +120,7 @@ asyncio_mode = "auto" asyncio_default_fixture_loop_scope="function" [tool.coverage.report] -omit = ["param/version.py"] +omit = ["param/version.py", "tests/testimports.py"] [tool.ruff] fix = true From 42e582393f790219ea85912a1e24a9788cdbc1b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Thu, 27 Feb 2025 11:49:46 +0100 Subject: [PATCH 3/7] dont call get_ipython --- param/_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/param/_utils.py b/param/_utils.py index 9c393ea1..b22cfcaa 100644 --- a/param/_utils.py +++ b/param/_utils.py @@ -663,7 +663,7 @@ def exceptions_summarized(): def _in_ipython(): try: - get_ipython() + get_ipython return True except NameError: return False From 23f11779eb646e9de0e74e3ecbeac753d74c056d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Thu, 27 Feb 2025 12:09:42 +0100 Subject: [PATCH 4/7] Also make it possible to use environment variable for signature --- param/parameterized.py | 14 ++++++++++---- pixi.toml | 3 +++ tests/conftest.py | 4 ++-- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/param/parameterized.py b/param/parameterized.py index 0d17915d..1cbf77d3 100644 --- a/param/parameterized.py +++ b/param/parameterized.py @@ -10,13 +10,13 @@ import asyncio import copy -import builtins import datetime as dt import html import inspect import logging import numbers import operator +import os import re import sys import types @@ -26,7 +26,7 @@ from collections import defaultdict, namedtuple, OrderedDict from collections.abc import Callable, Iterable -from functools import partial, wraps, reduce +from functools import lru_cache, partial, wraps, reduce from html import escape from itertools import chain from operator import itemgetter, attrgetter @@ -982,6 +982,13 @@ def __getattribute__(mcs,name): return type.__getattribute__(mcs,name) +@lru_cache() +def _update_signature(): + # Only update signature in an IPython environment + # or if PARAM_SIGNATURE environment variable is set + return _in_ipython() or os.getenv("PARAM_SIGNATURE") + + class _ParameterBase(metaclass=ParameterMetaclass): """ Base Parameter class used to dynamically update the signature of all @@ -997,8 +1004,7 @@ def _modified_slots_defaults(cls): @classmethod def __init_subclass__(cls): super().__init_subclass__() - # Only update signature in an IPython environment - if not hasattr(builtins, "__IPYTHON__"): + if not _update_signature(): return # _update_signature has been tested against the Parameters available # in Param, we don't want to break the Parameters created elsewhere diff --git a/pixi.toml b/pixi.toml index 582c522d..bfe7e3ef 100644 --- a/pixi.toml +++ b/pixi.toml @@ -90,6 +90,9 @@ nbval = "*" [feature.doc] channels = ["pyviz"] +[feature.doc.activation.env] +PARAM_SIGNATURE = "1" + [feature.doc.dependencies] graphviz = "*" nbsite = ">=0.8.4,<0.9.0" diff --git a/tests/conftest.py b/tests/conftest.py index 2ffe1096..35e820d4 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,6 +1,6 @@ -import builtins +import os -builtins.__IPYTHON__ = True # To force signature in _ParameterBase.__init_subclass__ +os.environ["PARAM_SIGNATURE"] = "1" # To force signature in _ParameterBase.__init_subclass__ import param import pytest From 10c60c1bbcdb1cb2dc5b9e47513c1e176f47d96d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Thu, 27 Feb 2025 12:27:06 +0100 Subject: [PATCH 5/7] Make it a constant --- param/parameterized.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/param/parameterized.py b/param/parameterized.py index 1cbf77d3..fb3aa53a 100644 --- a/param/parameterized.py +++ b/param/parameterized.py @@ -26,7 +26,7 @@ from collections import defaultdict, namedtuple, OrderedDict from collections.abc import Callable, Iterable -from functools import lru_cache, partial, wraps, reduce +from functools import partial, wraps, reduce from html import escape from itertools import chain from operator import itemgetter, attrgetter @@ -982,11 +982,7 @@ def __getattribute__(mcs,name): return type.__getattribute__(mcs,name) -@lru_cache() -def _update_signature(): - # Only update signature in an IPython environment - # or if PARAM_SIGNATURE environment variable is set - return _in_ipython() or os.getenv("PARAM_SIGNATURE") +_UDPATE_SIGNATURE = _in_ipython() or os.getenv("PARAM_SIGNATURE") class _ParameterBase(metaclass=ParameterMetaclass): @@ -1004,7 +1000,7 @@ def _modified_slots_defaults(cls): @classmethod def __init_subclass__(cls): super().__init_subclass__() - if not _update_signature(): + if not _UDPATE_SIGNATURE: return # _update_signature has been tested against the Parameters available # in Param, we don't want to break the Parameters created elsewhere From c0601937993a480da2cd8db9c39a81c0fa30a915 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Thu, 27 Feb 2025 13:22:35 +0100 Subject: [PATCH 6/7] Apply suggestions from code review Co-authored-by: Maxime Liquet <35924738+maximlt@users.noreply.github.com> --- param/parameterized.py | 4 ++-- pixi.toml | 2 +- tests/conftest.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/param/parameterized.py b/param/parameterized.py index fb3aa53a..2f6b1356 100644 --- a/param/parameterized.py +++ b/param/parameterized.py @@ -982,7 +982,7 @@ def __getattribute__(mcs,name): return type.__getattribute__(mcs,name) -_UDPATE_SIGNATURE = _in_ipython() or os.getenv("PARAM_SIGNATURE") +_UDPATE_PARAM_SIGNATURE = _in_ipython() or (os.getenv("PARAM_PARAMETER_SIGNATURE", "false").lower() in ("1" , "true")) class _ParameterBase(metaclass=ParameterMetaclass): @@ -1000,7 +1000,7 @@ def _modified_slots_defaults(cls): @classmethod def __init_subclass__(cls): super().__init_subclass__() - if not _UDPATE_SIGNATURE: + if not _UDPATE_PARAMETER_SIGNATURE: return # _update_signature has been tested against the Parameters available # in Param, we don't want to break the Parameters created elsewhere diff --git a/pixi.toml b/pixi.toml index bfe7e3ef..b402830a 100644 --- a/pixi.toml +++ b/pixi.toml @@ -91,7 +91,7 @@ nbval = "*" channels = ["pyviz"] [feature.doc.activation.env] -PARAM_SIGNATURE = "1" +PARAM_PARAMETER_SIGNATURE = "1" [feature.doc.dependencies] graphviz = "*" diff --git a/tests/conftest.py b/tests/conftest.py index 35e820d4..3c1627b7 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,6 +1,6 @@ import os -os.environ["PARAM_SIGNATURE"] = "1" # To force signature in _ParameterBase.__init_subclass__ +os.environ["PARAM_PARAMETER_SIGNATURE"] = "1" # To force signature in _ParameterBase.__init_subclass__ import param import pytest From d601bb3b7e1c0846d681c06fa16a7ac7596a15e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Thu, 27 Feb 2025 13:24:49 +0100 Subject: [PATCH 7/7] Apply suggestions from code review --- param/parameterized.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/param/parameterized.py b/param/parameterized.py index 2f6b1356..6d4423a9 100644 --- a/param/parameterized.py +++ b/param/parameterized.py @@ -982,7 +982,7 @@ def __getattribute__(mcs,name): return type.__getattribute__(mcs,name) -_UDPATE_PARAM_SIGNATURE = _in_ipython() or (os.getenv("PARAM_PARAMETER_SIGNATURE", "false").lower() in ("1" , "true")) +_UDPATE_PARAMETER_SIGNATURE = _in_ipython() or (os.getenv("PARAM_PARAMETER_SIGNATURE", "false").lower() in ("1" , "true")) class _ParameterBase(metaclass=ParameterMetaclass):