Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 4 additions & 3 deletions docs/docs/api-reference/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ This section contains the reference detailing the functions and modules
available in EasyScience.

- [base_classes](base_classes.md) – Core abstract and helper base
classes used to build EasyScience objects (e.g. `ObjBase`,
`ModelBase`).
classes used to build EasyScience objects (e.g. `NewBase`,
`ModelBase`, `EasyList`).
- [fitting](fitting.md) – Fitting utilities and interfaces, including
`Fitter` and available minimizers.
- [global_object](global_object.md) – Global singleton providing shared
Expand All @@ -23,4 +23,5 @@ available in EasyScience.
- [utils](utils.md) – Miscellaneous utility functions and helpers (class
tools, decorators, type helpers).
- [variable](variable.md) – Descriptor types and variable abstractions
(e.g. `DescriptorNumber`, `Parameter`, `DescriptorArray`).
(e.g. `DescriptorNumber`, `Parameter`, `DescriptorArray`). All of them
are `NewBase` objects, serialized with `to_dict`/`from_dict`.
6 changes: 3 additions & 3 deletions src/easyscience/base_classes/based_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,11 +239,11 @@ def __dir__(self) -> Iterable[str]:

def __copy__(self) -> BasedBase:
"""Return a copy of the object."""
temp = self.as_dict(skip=['unique_name'])
temp = self.to_dict(skip=['unique_name'])
new_obj = self.__class__.from_dict(temp)
return new_obj

def as_dict(self, skip: Optional[List[str]] = None) -> Dict[str, Any]:
def to_dict(self, skip: Optional[List[str]] = None) -> Dict[str, Any]:
"""
Convert an object into a full dictionary using
``SerializerDict``. This is a shortcut for
Expand All @@ -266,4 +266,4 @@ def as_dict(self, skip: Optional[List[str]] = None) -> Dict[str, Any]:
skip = []
if 'unique_name' not in skip:
skip.append('unique_name')
return super().as_dict(skip=skip)
return super().to_dict(skip=skip)
5 changes: 4 additions & 1 deletion src/easyscience/base_classes/easy_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,10 @@ def __init__(
Initial items to add to the list.
protected_types : list[Type[NewBase]] | Type[NewBase] | None, default=None
Types that are allowed in the list. Can be a single NewBase
subclass or a list of them. If None,. By default, None.
subclass or a list of them. If None, any ``NewBase`` object
is accepted, including descriptors and parameters. Note that
only ``ModelBase`` items contribute to ``get_all_variables``
and hence to fitting. By default, None.
unique_name : Optional[str], default=None
Optional unique name for the list. By default, None.
display_name : Optional[str], default=None
Expand Down
8 changes: 8 additions & 0 deletions src/easyscience/base_classes/new_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,14 @@ def to_dict(self, skip: Optional[List[str]] = None) -> Dict[str, Any]:
Dict[str, Any]
Encoded object containing all information to reform an
EasyScience object.

Notes
-----
A ``unique_name`` that was generated automatically is not
written; only an explicitly supplied one is, so that a
deserialized object gets a fresh name instead of clashing with
the original. Likewise ``display_name`` is omitted when it is
``None``. Pass ``skip`` to drop further fields.
"""
serializer = SerializerBase()
if skip is None:
Expand Down
3 changes: 2 additions & 1 deletion src/easyscience/fitting/multi_fitter.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import numpy as np

from ..base_classes import EasyList
from ..base_classes import ModelBase
from .fitter import Fitter
from .minimizers import FitResults

Expand Down Expand Up @@ -38,7 +39,7 @@ def __init__(
# Aggregate the fit objects so a single object can be sent to Fitter.
# *-unpacking keeps any sequence (list, tuple, etc) working, as the
# old CollectionBase container did.
self._fit_objects = EasyList(*fit_objects)
self._fit_objects = EasyList(*fit_objects, protected_types=ModelBase)
self._fit_functions = list(fit_functions)
# Initialize with the first of the fit_functions, without this it is
# not possible to change the fitting engine. With no functions given
Expand Down
4 changes: 2 additions & 2 deletions src/easyscience/io/serializer_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,13 +215,13 @@ def runner(o):
err = False
if err:
raise NotImplementedError(
'Unable to automatically determine as_dict '
'Unable to automatically determine to_dict '
'format from class. MSONAble requires all '
'args to be present as either self.argname or '
'self._argname, and kwargs to be present under'
'a self.kwargs variable to automatically '
'determine the dict format. Alternatively, '
'you can implement both as_dict and from_dict.'
'you can implement both to_dict and from_dict.'
)
d[c] = self._recursive_encoder(
a, skip=skip, encoder=self, full_encode=full_encode, **kwargs
Expand Down
4 changes: 2 additions & 2 deletions src/easyscience/io/serializer_component.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"""

def __deepcopy__(self, memo):
return self.from_dict(self.as_dict())
return self.from_dict(self.to_dict())

Check warning on line 29 in src/easyscience/io/serializer_component.py

View check run for this annotation

Codecov / codecov/patch

src/easyscience/io/serializer_component.py#L29

Added line #L29 was not covered by tests

def encode(
self, skip: Optional[List[str]] = None, encoder: Optional[SerializerBase] = None, **kwargs
Expand Down Expand Up @@ -82,7 +82,7 @@
decoder = SerializerDict
return decoder.decode(obj)

def as_dict(self, skip: Optional[List[str]] = None) -> Dict[str, Any]:
def to_dict(self, skip: Optional[List[str]] = None) -> Dict[str, Any]:
"""
Convert an EasyScience object into a full dictionary using
``SerializerDict``. This is a shortcut for
Expand Down
4 changes: 2 additions & 2 deletions src/easyscience/job/theoreticalmodel.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@
def __str__(self):
raise NotImplementedError('Copy not implemented')

def as_dict(self, skip: list = []) -> dict:
this_dict = super().as_dict(skip=skip)
def to_dict(self, skip: list = []) -> dict:
this_dict = super().to_dict(skip=skip)

Check warning on line 22 in src/easyscience/job/theoreticalmodel.py

View check run for this annotation

Codecov / codecov/patch

src/easyscience/job/theoreticalmodel.py#L21-L22

Added lines #L21 - L22 were not covered by tests
return this_dict
12 changes: 5 additions & 7 deletions src/easyscience/variable/descriptor_any_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,16 @@ def __init__(
description: Optional[str] = None,
url: Optional[str] = None,
display_name: Optional[str] = None,
parent: Optional[Any] = None,
):
"""
Constructor for the DescriptorAnyType class.

param name: Name of the descriptor param value: Value of the
descriptor param description: Description of the descriptor
param url: URL of the descriptor param display_name: Display
name of the descriptor param parent: Parent of the descriptor ..
note:: Undo/Redo functionality is implemented for the attributes
``variance``, ``error``, ``unit`` and ``value``.
name of the descriptor .. note:: Undo/Redo functionality is
implemented for the attributes ``variance``, ``error``,
``unit`` and ``value``.
"""

self._value = value
Expand All @@ -55,7 +54,6 @@ def __init__(
description=description,
url=url,
display_name=display_name,
parent=parent,
)

@property
Expand Down Expand Up @@ -99,7 +97,7 @@ def __repr__(self) -> str:

return f"<{self.__class__.__name__} '{self._name}': {value_repr}>"

def as_dict(self, skip: Optional[List[str]] = None) -> Dict[str, Any]:
raw_dict = super().as_dict(skip=skip)
def to_dict(self, skip: Optional[List[str]] = None) -> Dict[str, Any]:
raw_dict = super().to_dict(skip=skip)
raw_dict['value'] = self._value
return raw_dict
16 changes: 7 additions & 9 deletions src/easyscience/variable/descriptor_array.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ def __init__(
description: Optional[str] = None,
url: Optional[str] = None,
display_name: Optional[str] = None,
parent: Optional[Any] = None,
dimensions: Optional[list] = None,
):
"""
Expand All @@ -52,11 +51,11 @@ def __init__(
the values of the descriptor param unit: Unit of the descriptor
param variance: Variances of the descriptor param description:
Description of the descriptor param url: URL of the descriptor
param display_name: Display name of the descriptor param parent:
Parent of the descriptor param dimensions: List of dimensions to
pass to scipp. Will be autogenerated if not supplied. .. note::
Undo/Redo functionality is implemented for the attributes
``variance``, ``error``, ``unit`` and ``value``.
param display_name: Display name of the descriptor param
dimensions: List of dimensions to pass to scipp. Will be
autogenerated if not supplied. .. note:: Undo/Redo functionality
is implemented for the attributes ``variance``, ``error``,
``unit`` and ``value``.
"""

if not isinstance(value, (list, np.ndarray)):
Expand Down Expand Up @@ -104,7 +103,6 @@ def __init__(
description=description,
url=url,
display_name=display_name,
parent=parent,
)

# Call convert_unit during initialization to ensure that the unit has no numbers in it, and to ensure unit consistency.
Expand Down Expand Up @@ -472,14 +470,14 @@ def __repr__(self) -> str:
string = string.replace('\n', ',')
return string

def as_dict(self, skip: Optional[List[str]] = None) -> Dict[str, Any]:
def to_dict(self, skip: Optional[List[str]] = None) -> Dict[str, Any]:
"""
Dict representation of the current DescriptorArray.

The dict contains the value, unit and variances, in addition to
the properties of DescriptorBase.
"""
raw_dict = super().as_dict(skip=skip)
raw_dict = super().to_dict(skip=skip)
raw_dict['value'] = self._array.values
raw_dict['unit'] = str(self._array.unit)
raw_dict['variance'] = self._array.variances
Expand Down
73 changes: 11 additions & 62 deletions src/easyscience/variable/descriptor_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@

import abc
from typing import Any
from typing import Dict
from typing import List
from typing import Optional

from easyscience import global_object
from easyscience.base_classes.new_base import NewBase
from easyscience.global_object.undo_redo import property_stack
from easyscience.io import SerializerComponent


class DescriptorBase(SerializerComponent, metaclass=abc.ABCMeta):
class DescriptorBase(NewBase, metaclass=abc.ABCMeta):
"""
This is the base of all variable descriptions for models.

Expand All @@ -29,7 +31,7 @@ class DescriptorBase(SerializerComponent, metaclass=abc.ABCMeta):

_global_object = global_object
# Used by serializer
_REDIRECT = {'parent': None}
_REDIRECT = {}

def __init__(
self,
Expand All @@ -38,7 +40,6 @@ def __init__(
description: Optional[str] = None,
url: Optional[str] = None,
display_name: Optional[str] = None,
parent: Optional[Any] = None,
):
"""
This is the base of variables for models.
Expand All @@ -63,9 +64,6 @@ def __init__(
Lookup url for documentation/information. By default, None.
display_name : Optional[str], default=None
A pretty name for the object. By default, None.
parent : Optional[Any], default=None
The object which this descriptor is attached to. By default,
None.

Raises
------
Expand All @@ -74,17 +72,12 @@ def __init__(
has an invalid type.
"""

if unique_name is None:
unique_name = global_object.generate_unique_name(self.__class__.__name__)
self._unique_name = unique_name

if not isinstance(name, str):
raise TypeError('Name must be a string')
self._name: str = name

if display_name is not None and not isinstance(display_name, str):
raise TypeError('Display name must be a string or None')
self._display_name: str = display_name
super().__init__(unique_name=unique_name, display_name=display_name)

self._name: str = name

if description is not None and not isinstance(description, str):
raise TypeError('Description must be a string or None')
Expand All @@ -98,13 +91,6 @@ def __init__(
url = ''
self._url: str = url

# Let the collective know we've been assimilated
self._parent = parent
global_object.map.add_vertex(self, obj_type='created')
# Make the connection between self and parent
if parent is not None:
global_object.map.add_edge(parent, self)

@property
def name(self) -> str:
"""
Expand Down Expand Up @@ -142,6 +128,9 @@ def display_name(self) -> str:
"""
Get a pretty display name.

Unlike ``NewBase`` the fallback is the ``name`` of the
descriptor rather than its ``unique_name``.

Returns
-------
str
Expand Down Expand Up @@ -234,40 +223,6 @@ def url(self, url: Optional[str]) -> None:
raise TypeError('url must be a string')
self._url = url

@property
def unique_name(self) -> str:
"""
Get the unique name of this object.

Returns
-------
str
Unique name of this object.
"""
return self._unique_name

@unique_name.setter
def unique_name(self, new_unique_name: str):
"""
Set a new unique name for the object.

The old name is still kept in the map.

Parameters
----------
new_unique_name : str
New unique name for the object.

Raises
------
TypeError
If ``new_unique_name`` is not a string.
"""
if not isinstance(new_unique_name, str):
raise TypeError('Unique name has to be a string.')
self._unique_name = new_unique_name
global_object.map.add_vertex(self)

@property
@abc.abstractmethod
def value(self) -> Any:
Expand All @@ -281,9 +236,3 @@ def value(self, value: Any) -> None:
@abc.abstractmethod
def __repr__(self) -> str:
"""Return printable representation of the object."""

def __copy__(self) -> DescriptorBase:
"""Return a copy of the object."""
temp = self.as_dict(skip=['unique_name'])
new_obj = self.__class__.from_dict(temp)
return new_obj
3 changes: 0 additions & 3 deletions src/easyscience/variable/descriptor_bool.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

from __future__ import annotations

from typing import Any
from typing import Optional

from easyscience.global_object.undo_redo import property_stack
Expand All @@ -22,7 +21,6 @@ def __init__(
description: Optional[str] = None,
url: Optional[str] = None,
display_name: Optional[str] = None,
parent: Optional[Any] = None,
):
if not isinstance(value, bool):
raise ValueError(f'{value=} must be type bool')
Expand All @@ -32,7 +30,6 @@ def __init__(
description=description,
url=url,
display_name=display_name,
parent=parent,
)
if not isinstance(value, bool):
raise TypeError(f'{value=} must be type bool')
Expand Down
Loading