Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .github/workflows/python-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
strategy:
max-parallel: 4
matrix:
python-version: ['3.9', '3.10', '3.11']
python-version: ['3.9', '3.10', '3.11', '3.12']
os: [ubuntu-latest, macos-latest, windows-latest]

runs-on: ${{ matrix.os }}
Expand Down
2 changes: 1 addition & 1 deletion Examples/fitting/plot_constraints.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
This example shows the usages of the different constraints.
"""

from easyscience.fitting import Constraints
from easyscience import Constraints
from easyscience.Objects.ObjectClasses import Parameter

p1 = Parameter('p1', 1)
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ classifiers = [
"Programming Language :: Python :: 3.12",
"Development Status :: 3 - Alpha"
]
requires-python = ">=3.9,<3.12"
requires-python = ">=3.9,<3.13"
dependencies = [
"asteval",
"bumps",
Expand Down
File renamed without changes.
19 changes: 11 additions & 8 deletions src/easyscience/Objects/Groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from typing import Union

from easyscience.global_object.undo_redo import NotarizedDict
from easyscience.Objects.new_variable.descriptor_base import DescriptorBase
from easyscience.Objects.ObjectClasses import BasedBase
from easyscience.Objects.ObjectClasses import Descriptor

Expand All @@ -40,6 +41,7 @@ def __init__(
name: str,
*args: Union[B, V],
interface: Optional[iF] = None,
unique_name: Optional[str] = None,
**kwargs,
):
"""
Expand All @@ -51,7 +53,7 @@ def __init__(
:param _kwargs: Fields which this class should contain
:type _kwargs: dict
"""
BasedBase.__init__(self, name)
BasedBase.__init__(self, name, unique_name=unique_name)
kwargs = {key: kwargs[key] for key in kwargs.keys() if kwargs[key] is not None}
_args = []
for item in args:
Expand All @@ -67,7 +69,7 @@ def __init__(
_kwargs[key] = item
kwargs = _kwargs
for item in list(kwargs.values()) + _args:
if not issubclass(type(item), (Descriptor, BasedBase)):
if not issubclass(type(item), (Descriptor, DescriptorBase, BasedBase)):
raise AttributeError('A collection can only be formed from easyscience objects.')
args = _args
_kwargs = {}
Expand All @@ -83,10 +85,11 @@ def __init__(
for key in kwargs.keys():
if key in self.__dict__.keys() or key in self.__slots__:
raise AttributeError(f'Given kwarg: `{key}`, is an internal attribute. Please rename.')
self._global_object.map.add_edge(self, kwargs[key])
self._global_object.map.reset_type(kwargs[key], 'created_internal')
if interface is not None:
kwargs[key].interface = interface
if kwargs[key]: # Might be None (empty tuple or list)
self._global_object.map.add_edge(self, kwargs[key])
self._global_object.map.reset_type(kwargs[key], 'created_internal')
if interface is not None:
kwargs[key].interface = interface
# TODO wrap getter and setter in Logger
if interface is not None:
self.interface = interface
Expand All @@ -104,7 +107,7 @@ def insert(self, index: int, value: Union[V, B]) -> None:
:rtype: None
"""
t_ = type(value)
if issubclass(t_, (BasedBase, Descriptor)):
if issubclass(t_, (BasedBase, Descriptor, DescriptorBase)):
update_key = list(self._kwargs.keys())
values = list(self._kwargs.values())
# Update the internal dict
Expand Down Expand Up @@ -165,7 +168,7 @@ def __setitem__(self, key: int, value: Union[B, V]) -> None:
if isinstance(value, Number): # noqa: S3827
item = self.__getitem__(key)
item.value = value
elif issubclass(type(value), BasedBase) or issubclass(type(value), Descriptor):
elif issubclass(type(value), (BasedBase, Descriptor, DescriptorBase)):
update_key = list(self._kwargs.keys())
values = list(self._kwargs.values())
old_item = values[key]
Expand Down
14 changes: 11 additions & 3 deletions src/easyscience/Objects/ObjectClasses.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
from .Variable import Parameter

if TYPE_CHECKING:
from easyscience.fitting.Constraints import C
from easyscience.Constraints import C
from easyscience.Objects.Inferface import iF
from easyscience.Objects.Variable import V

Expand Down Expand Up @@ -186,7 +186,7 @@ def _get_linkable_attributes(self) -> List[V]:
for key, item in self._kwargs.items():
if hasattr(item, '_get_linkable_attributes'):
item_list = [*item_list, *item._get_linkable_attributes()]
elif issubclass(type(item), Descriptor) or issubclass(type(item), DescriptorBase):
elif issubclass(type(item), (Descriptor, DescriptorBase)):
item_list.append(item)
return item_list

Expand Down Expand Up @@ -215,6 +215,12 @@ def __dir__(self) -> Iterable[str]:
new_class_objs = list(k for k in dir(self.__class__) if not k.startswith('_'))
return sorted(new_class_objs)

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


if TYPE_CHECKING:
B = TypeVar('B', bound=BasedBase)
Expand Down Expand Up @@ -346,7 +352,9 @@ def getter(obj: BV) -> BV:
@staticmethod
def __setter(key: str) -> Callable[[BV], None]:
def setter(obj: BV, value: float) -> None:
if issubclass(obj._kwargs[key].__class__, Descriptor) and not issubclass(value.__class__, Descriptor):
if issubclass(obj._kwargs[key].__class__, (Descriptor, DescriptorBase)) and not issubclass(
value.__class__, (Descriptor, DescriptorBase)
):
obj._kwargs[key].value = value
else:
obj._kwargs[key] = value
Expand Down
4 changes: 2 additions & 2 deletions src/easyscience/Objects/Variable.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@
from easyscience import global_object
from easyscience import pint
from easyscience import ureg
from easyscience.fitting.Constraints import SelfConstraint
from easyscience.Constraints import SelfConstraint
from easyscience.global_object.undo_redo import property_stack_deco
from easyscience.Objects.core import ComponentSerializer
from easyscience.Utils.classTools import addProp
from easyscience.Utils.Exceptions import CoreSetException

if TYPE_CHECKING:
from easyscience.fitting.Constraints import C
from easyscience.Constraints import C

Q_ = ureg.Quantity
M_ = ureg.Measurement
Expand Down
15 changes: 11 additions & 4 deletions src/easyscience/Objects/new_variable/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
from .descriptor_bool import DescriptorBool # noqa: F401
from .descriptor_number import DescriptorNumber # noqa: F401
from .descriptor_str import DescriptorStr # noqa: F401
from .parameter import Parameter # noqa: F401
from .descriptor_bool import DescriptorBool
from .descriptor_number import DescriptorNumber
from .descriptor_str import DescriptorStr
from .parameter import Parameter

__all__ = [
DescriptorBool,
DescriptorNumber,
DescriptorStr,
Parameter,
]
12 changes: 5 additions & 7 deletions src/easyscience/Objects/new_variable/descriptor_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ class DescriptorBase(ComponentSerializer, metaclass=abc.ABCMeta):
# Used by serializer
_REDIRECT = {'parent': None}

_global_object = global_object

def __init__(
self,
Expand Down Expand Up @@ -55,7 +54,7 @@ def __init__(
"""

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

if not isinstance(name, str):
Expand All @@ -80,10 +79,10 @@ def __init__(

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

@property
def name(self) -> str:
Expand Down Expand Up @@ -187,7 +186,7 @@ def unique_name(self, new_unique_name: str):
if not isinstance(new_unique_name, str):
raise TypeError('Unique name has to be a string.')
self._unique_name = new_unique_name
self._global_object.map.add_vertex(self)
global_object.map.add_vertex(self)

@property
@abc.abstractmethod
Expand All @@ -205,7 +204,6 @@ def __repr__(self) -> str:

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