Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
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
Loading