Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved param and rx docs #977

Open
wants to merge 28 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
f9faae2
improved docs
MarcSkovMadsen Nov 13, 2024
563ea82
pre-commit
MarcSkovMadsen Nov 13, 2024
c5f6167
document .param namespace
MarcSkovMadsen Nov 13, 2024
ed229c3
fix
MarcSkovMadsen Nov 13, 2024
896f94d
align rx docstring
MarcSkovMadsen Nov 13, 2024
755496d
add type
MarcSkovMadsen Nov 13, 2024
b712cc1
align rx docstring
MarcSkovMadsen Nov 13, 2024
25733d2
align docstrings
MarcSkovMadsen Nov 13, 2024
65ae984
fix
MarcSkovMadsen Nov 13, 2024
6a7be70
Update tests/testreactive.py
MarcSkovMadsen Nov 13, 2024
edda46b
Fix lint
hoxbro Nov 13, 2024
ecbd92b
Update param/parameterized.py
MarcSkovMadsen Nov 14, 2024
3a17a10
Update param/parameterized.py
MarcSkovMadsen Nov 14, 2024
b55ef26
Update param/parameterized.py
MarcSkovMadsen Nov 14, 2024
173ff9c
Update param/reactive.py
MarcSkovMadsen Nov 14, 2024
f7c92da
review feedback
MarcSkovMadsen Nov 14, 2024
ba18b87
Merge branch 'enhancement/rx-docs' of https://github.com/holoviz/para…
MarcSkovMadsen Nov 14, 2024
2d5b832
Update param/parameterized.py
MarcSkovMadsen Nov 14, 2024
63f96df
review feedback
MarcSkovMadsen Nov 14, 2024
aa1b61c
Update param/parameterized.py
MarcSkovMadsen Nov 23, 2024
f26a0e2
Update param/parameterized.py
MarcSkovMadsen Nov 23, 2024
44cbfed
review feedback
MarcSkovMadsen Nov 23, 2024
a52d39c
Merge branch 'enhancement/rx-docs' of https://github.com/holoviz/para…
MarcSkovMadsen Nov 23, 2024
27a11e5
review feedback
MarcSkovMadsen Nov 23, 2024
0092617
review feedback
MarcSkovMadsen Nov 23, 2024
930ca17
review feedback
MarcSkovMadsen Nov 23, 2024
8964a56
fix failing test
MarcSkovMadsen Nov 23, 2024
3237360
Merge branch 'main' of https://github.com/holoviz/param into enhancem…
MarcSkovMadsen Nov 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,4 @@ benchmarks/param
# pixi
.pixi
pixi.lock
script.*
MarcSkovMadsen marked this conversation as resolved.
Show resolved Hide resolved
226 changes: 218 additions & 8 deletions param/parameterized.py
Original file line number Diff line number Diff line change
Expand Up @@ -1320,6 +1320,44 @@ def schema(self, safe=False, subset=None, mode='json'):

@property
def rx(self):
"""The reactive namespace.

Provides reactive versions of the operations that cannot be made reactive through overloading, such as
`.rx.and_` and `.rx.bool`. Call it (`()`) to obtain a reactive expression.

Reference: https://param.holoviz.org/user_guide/Reactive_Expressions.html#special-methods-on-rx

Examples:
MarcSkovMadsen marked this conversation as resolved.
Show resolved Hide resolved

Turn your parameter into a reactive expression:

```python
import param

class MyClass(param.Parameterized):
value = param.Parameter()

my_instance = MyClass(value=0)
```

Get the current value:

```python
a = my_instance.rx.value
```

Set the current value:

```python
my_instance.rx.value = 1
```

Call it to get a reactive expression:

```python
rx_value = my_instance.rx()
```
"""
from .reactive import reactive_ops
return reactive_ops(self)

Expand Down Expand Up @@ -2260,12 +2298,50 @@ def set_default(self_,param_name,value):
cls = self_.cls
setattr(cls,param_name,value)

def add_parameter(self_, param_name, param_obj):
def add_parameter(self_, param_name: str, param_obj: Parameter):
MarcSkovMadsen marked this conversation as resolved.
Show resolved Hide resolved
"""
Add a new Parameter object into this object's class.

Should result in a Parameter equivalent to one declared
in the class's source code.

Parameters
----------
param_name : str
The name of the parameter to add.
param_obj : Parameter
The Parameter object to add.

Example
-------
MarcSkovMadsen marked this conversation as resolved.
Show resolved Hide resolved

```python
import param


class P(param.Parameterized):
a = param.Number()
b = param.String()


p = P()
```

Add a new parameter to the class via the class:
MarcSkovMadsen marked this conversation as resolved.
Show resolved Hide resolved
MarcSkovMadsen marked this conversation as resolved.
Show resolved Hide resolved

```python
P.param.add_parameter('c', param.Tuple(default=(1,2,3)))
print(p.c)
# (1, 2, 3)
```

Add a new parameter to the class via the instance:
MarcSkovMadsen marked this conversation as resolved.
Show resolved Hide resolved

```python
p.param.add_parameter('d', param.Tuple(default=(3,2,1)))
print(p.d)
# (3, 2, 1)
```
"""
# Could have just done setattr(cls,param_name,param_obj),
# which is supported by the metaclass's __setattr__ , but
Expand Down Expand Up @@ -2309,12 +2385,46 @@ def params(self_, parameter_name=None):

def update(self_, arg=Undefined, /, **kwargs):
"""
For the given dictionary or iterable or set of param=value
keyword arguments, sets the corresponding parameter of this
object or class to the given value.
Updates one or more parameters of this object or class.

This method allows you to set the parameters of the object or class using a dictionary,
an iterable, or keyword arguments in the form of param=value. The specified parameters
will be updated to the given values.

This method can also be used as a context manager to temporarily set and then reset
parameter values.

Reference: https://param.holoviz.org/user_guide/Parameters.html#other-parameterized-methods
MarcSkovMadsen marked this conversation as resolved.
Show resolved Hide resolved

Examples:
MarcSkovMadsen marked this conversation as resolved.
Show resolved Hide resolved

```python
import param

class P(param.Parameterized):
a = param.Number()
b = param.String()

p = P()
```

Update parameters permanently:

```python
p.param.update(a=1, b="Hello")
print(p.a, p.b)
# Output: 1 Hello
```

May also be used as a context manager to temporarily set and
then reset parameter values.
Update parameters temporarily:

```python
with p.param.update(a=2, b="World"):
print(p.a, p.b)
# Output: 2 World
print(p.a, p.b)
# Output: 1 Hello
```
"""
refs = {}
if self_.self is not None:
Expand Down Expand Up @@ -2597,7 +2707,45 @@ class or instance that contains an iterable collection of
for obj in sublist:
obj.param.set_dynamic_time_fn(time_fn,sublistattr)

def serialize_parameters(self_, subset=None, mode='json'):
def serialize_parameters(self_, subset=None, mode='json')->str:
MarcSkovMadsen marked this conversation as resolved.
Show resolved Hide resolved
"""Returns the serialized parameters of the Parameterized object.

Parameters
----------
subset (list, optional):
MarcSkovMadsen marked this conversation as resolved.
Show resolved Hide resolved
A list of parameter names to serialize. If None, all parameters will be serialized. Defaults to None.
mode (str, optional):
The serialization format. By default, only 'json' is supported. Defaults to 'json'.

Raises:
ValueError: If the `mode` is not valid.
MarcSkovMadsen marked this conversation as resolved.
Show resolved Hide resolved

Returns
-------
dict: The serialized string
MarcSkovMadsen marked this conversation as resolved.
Show resolved Hide resolved

Reference
---------
For more details visit https://param.holoviz.org/user_guide/Serialization_and_Persistence.html#serializing-with-json

Example
-------
MarcSkovMadsen marked this conversation as resolved.
Show resolved Hide resolved

```python
import param

class P(param.Parameterized):
a = param.Number()
b = param.String()


p = P(a=1, b="hello")

serialized_data = p.param.serialize_parameters()
print(type(serialized_data))
# {"name": "P00002", "a": 1, "b": "hello"}
```
"""
self_or_cls = self_.self_or_cls
if mode not in Parameter._serializers:
raise ValueError(f'Mode {mode!r} not in available serialization formats {list(Parameter._serializers.keys())!r}')
Expand All @@ -2611,7 +2759,38 @@ def serialize_value(self_, pname, mode='json'):
serializer = Parameter._serializers[mode]
return serializer.serialize_parameter_value(self_or_cls, pname)

def deserialize_parameters(self_, serialization, subset=None, mode='json'):
def deserialize_parameters(self_, serialization, subset=None, mode='json') -> dict:
MarcSkovMadsen marked this conversation as resolved.
Show resolved Hide resolved
"""
Deserialize the given serialized data. You may use the deserialized to create a Parameteried object or
update the parameters of a Parameterized object.

Parameters:
MarcSkovMadsen marked this conversation as resolved.
Show resolved Hide resolved
- serialization (str): The serialized parameter data as a JSON string.
- subset (list, optional): A list of parameter names to deserialize. If None, all parameters will be deserialized. Defaults to None.
- mode (str, optional): The serialization format. By default, only 'json' is supported. Defaults to 'json'.

Returns:
dict: A dictionary with parameter names as keys and deserialized values.

Reference: https://param.holoviz.org/user_guide/Serialization_and_Persistence.html#serializing-with-json

Example:

```python
import param

class P(param.Parameterized):
a = param.Number()
b = param.String()

serialized_data = '{"a": 1, "b": "hello"}'
deserialized_data = P.param.deserialize_parameters(serialized_data)
print(deserialized_data)
# Output: {'a': 1, 'b': 'hello'}

instance = P(**deserialized_data)
```
"""
self_or_cls = self_.self_or_cls
serializer = Parameter._serializers[mode]
return serializer.deserialize_parameters(self_or_cls, serialization, subset=subset)
Expand Down Expand Up @@ -4206,6 +4385,37 @@ def __init__(self, **params):

@property
def param(self):
"""
The `.param` namespace for Parameterized classes and instances.

This namespace provides access to powerful methods and properties for managing parameters in a `Parameterized` object.
It includes utilities for adding parameters, updating parameters, debugging, serialization, logging, and more.

Reference: https://param.holoviz.org/user_guide/Parameters.html#parameter-objects-and-instances

Example:

```python
import param

class MyClass(param.Parameterized):
value = param.Parameter()

my_instance = MyClass(value=0)
```

Access the `value` parameter of `my_instance`:

```python
my_instance.param.value # the Parameter instance
```

Note this is different from the current `value` of `my_instance`:

```python
my_instance.value # 0, the current parameter value
```
"""
return Parameters(self.__class__, self=self)

#PARAM3_DEPRECATION
Expand Down
77 changes: 72 additions & 5 deletions param/reactive.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,11 +180,39 @@ class NestedResolver(Resolver):


class reactive_ops:
"""
Namespace for reactive operators.
"""The reactive namespace.

Provides reactive versions of the operations that cannot be made reactive through overloading, such as
`.rx.and_` and `.rx.bool`. Call it (`()`) to obtain a reactive expression.

Reference: https://param.holoviz.org/user_guide/Reactive_Expressions.html#special-methods-on-rx

Examples:

Lets create a Parameterized instance:

```python
import param

class P(param.Parameterized):
a = param.Number()
b = param.String()

Implements operators that cannot be implemented using regular
Python syntax.

p = P(a=1, b="hello")
```

Get the current value:

```python
a = p.param.a.rx.value
```

Call it to get a reactive expression:

```python
rx_value = p.param.a.rx()
```
"""

def __init__(self, reactive):
Expand All @@ -194,6 +222,7 @@ def _as_rx(self):
return self._reactive if isinstance(self._reactive, rx) else self()

def __call__(self):
"""Creates a reactive expression."""
rxi = self._reactive
return rxi if isinstance(rx, rx) else rx(rxi)

Expand Down Expand Up @@ -755,14 +784,52 @@ def __init__(
]
self._setup_invalidations(depth)
self._kwargs = kwargs
self.rx = reactive_ops(self)
self._rx = reactive_ops(self)
MarcSkovMadsen marked this conversation as resolved.
Show resolved Hide resolved
self._init = True
for name, accessor in _display_accessors.items():
setattr(self, name, accessor(self))
for name, (accessor, predicate) in rx._accessors.items():
if predicate is None or predicate(self._current):
setattr(self, name, accessor(self))

@property
def rx(self) -> reactive_ops:
"""The reactive namespace.

Provides reactive versions of the operations that cannot be made reactive through overloading, such as
`.rx.and_` and `.rx.bool`. Call it (`()`) to obtain a reactive expression.

Reference: https://param.holoviz.org/user_guide/Reactive_Expressions.html#special-methods-on-rx

Examples:
MarcSkovMadsen marked this conversation as resolved.
Show resolved Hide resolved

Lets create a Parameterized instance:

```python
import param

class P(param.Parameterized):
a = param.Number()
b = param.String()


p = P(a=1, b="hello")
```

Get the current value:

```python
a = p.param.a.rx.value
```

Call it to get a reactive expression:

```python
rx_value = p.param.a.rx()
```
"""
return self._rx

@property
def _obj(self):
if self._shared_obj is None:
Expand Down
Loading