steer-core 0.1.18__py3-none-any.whl → 0.1.20__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- steer_core/Data/database.db +0 -0
- steer_core/Decorators/Electrochemical.py +3 -7
- steer_core/Decorators/General.py +1 -0
- steer_core/Mixins/Dunder.py +164 -0
- steer_core/Mixins/TypeChecker.py +26 -3
- steer_core/__init__.py +1 -1
- {steer_core-0.1.18.dist-info → steer_core-0.1.20.dist-info}/METADATA +1 -1
- {steer_core-0.1.18.dist-info → steer_core-0.1.20.dist-info}/RECORD +11 -10
- /steer_core/Mixins/{Serializer.py → serializer.py} +0 -0
- {steer_core-0.1.18.dist-info → steer_core-0.1.20.dist-info}/WHEEL +0 -0
- {steer_core-0.1.18.dist-info → steer_core-0.1.20.dist-info}/top_level.txt +0 -0
steer_core/Data/database.db
CHANGED
|
Binary file
|
|
@@ -1,19 +1,16 @@
|
|
|
1
1
|
from functools import wraps
|
|
2
2
|
|
|
3
|
-
|
|
4
3
|
def calculate_half_cell_curve(func):
|
|
5
4
|
"""
|
|
6
5
|
Decorator to recalculate half-cell curve properties after a method call.
|
|
7
6
|
This is useful for methods that modify the half-cell curve data.
|
|
8
7
|
"""
|
|
9
|
-
|
|
10
8
|
@wraps(func)
|
|
11
9
|
def wrapper(self, *args, **kwargs):
|
|
12
10
|
result = func(self, *args, **kwargs)
|
|
13
|
-
if hasattr(self,
|
|
11
|
+
if hasattr(self, '_update_properties') and self._update_properties:
|
|
14
12
|
self._calculate_half_cell_curve()
|
|
15
13
|
return result
|
|
16
|
-
|
|
17
14
|
return wrapper
|
|
18
15
|
|
|
19
16
|
|
|
@@ -22,12 +19,11 @@ def calculate_half_cell_curves_properties(func):
|
|
|
22
19
|
Decorator to recalculate half-cell curves properties after a method call.
|
|
23
20
|
This is useful for methods that modify the half-cell curves data.
|
|
24
21
|
"""
|
|
25
|
-
|
|
26
22
|
@wraps(func)
|
|
27
23
|
def wrapper(self, *args, **kwargs):
|
|
28
24
|
result = func(self, *args, **kwargs)
|
|
29
|
-
if hasattr(self,
|
|
25
|
+
if hasattr(self, '_update_properties') and self._update_properties:
|
|
30
26
|
self._calculate_half_cell_curves_properties()
|
|
31
27
|
return result
|
|
32
|
-
|
|
33
28
|
return wrapper
|
|
29
|
+
|
steer_core/Decorators/General.py
CHANGED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class DunderMixin:
|
|
7
|
+
|
|
8
|
+
def _get_comparable_properties(self):
|
|
9
|
+
"""Get all comparable properties from the class hierarchy."""
|
|
10
|
+
properties = []
|
|
11
|
+
for cls in self.__class__.__mro__:
|
|
12
|
+
for name, value in cls.__dict__.items():
|
|
13
|
+
if isinstance(value, property):
|
|
14
|
+
if not self._should_exclude_property(name):
|
|
15
|
+
properties.append(name)
|
|
16
|
+
return properties
|
|
17
|
+
|
|
18
|
+
def _should_exclude_property(self, name):
|
|
19
|
+
"""Check if a property should be excluded from comparison."""
|
|
20
|
+
return (
|
|
21
|
+
name.endswith('_trace') or
|
|
22
|
+
name.endswith('_range') or
|
|
23
|
+
name in {'last_updated', 'properties'}
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
def _is_plotly_trace(self, obj):
|
|
27
|
+
"""Check if object is a Plotly trace object."""
|
|
28
|
+
return (
|
|
29
|
+
hasattr(obj, '__module__') and
|
|
30
|
+
obj.__module__ and
|
|
31
|
+
obj.__module__.startswith('plotly.graph_objs')
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
def _compare_none_values(self, self_value, other_value):
|
|
35
|
+
"""Compare None values. Returns (should_continue, result)."""
|
|
36
|
+
if self_value is None and other_value is None:
|
|
37
|
+
return True, True # Continue, values are equal
|
|
38
|
+
elif self_value is None or other_value is None:
|
|
39
|
+
return False, False # Stop, values are not equal
|
|
40
|
+
return True, None # Continue, not None values
|
|
41
|
+
|
|
42
|
+
def _compare_plotly_traces(self, self_value, other_value):
|
|
43
|
+
"""Compare Plotly trace objects. Returns (should_continue, result)."""
|
|
44
|
+
if self._is_plotly_trace(self_value) or self._is_plotly_trace(other_value):
|
|
45
|
+
return True, True # Skip Plotly traces, continue
|
|
46
|
+
return True, None # Continue, not Plotly traces
|
|
47
|
+
|
|
48
|
+
def _compare_numpy_arrays(self, self_value, other_value):
|
|
49
|
+
"""Compare NumPy arrays. Returns (should_continue, result)."""
|
|
50
|
+
if isinstance(self_value, np.ndarray) and isinstance(other_value, np.ndarray):
|
|
51
|
+
return False, np.array_equal(self_value, other_value, equal_nan=True)
|
|
52
|
+
elif isinstance(self_value, np.ndarray) or isinstance(other_value, np.ndarray):
|
|
53
|
+
return False, False # One is numpy array, other is not
|
|
54
|
+
return True, None # Continue, not numpy arrays
|
|
55
|
+
|
|
56
|
+
def _compare_dataframes(self, self_value, other_value):
|
|
57
|
+
"""Compare pandas DataFrames/Series. Returns (should_continue, result)."""
|
|
58
|
+
if hasattr(self_value, 'equals') and hasattr(other_value, 'equals'):
|
|
59
|
+
return False, self_value.equals(other_value)
|
|
60
|
+
elif hasattr(self_value, 'equals') or hasattr(other_value, 'equals'):
|
|
61
|
+
return False, False # Only one is a DataFrame/Series
|
|
62
|
+
return True, None # Continue, not DataFrames
|
|
63
|
+
|
|
64
|
+
def _compare_dictionaries(self, self_value, other_value):
|
|
65
|
+
"""Compare dictionaries by comparing keys and values separately. Returns (should_continue, result)."""
|
|
66
|
+
if isinstance(self_value, dict) and isinstance(other_value, dict):
|
|
67
|
+
# Compare keys first (order-independent)
|
|
68
|
+
if list(self_value.keys()) == list(other_value.keys()) and list(self_value.values()) == list(other_value.values()):
|
|
69
|
+
return False, True # Quick path: both keys and values match in order
|
|
70
|
+
|
|
71
|
+
# Compare values for each key
|
|
72
|
+
for key in self_value.keys():
|
|
73
|
+
if self_value[key] != other_value[key]:
|
|
74
|
+
return False, False
|
|
75
|
+
|
|
76
|
+
return False, True # Dictionaries are equal
|
|
77
|
+
elif isinstance(self_value, dict) or isinstance(other_value, dict):
|
|
78
|
+
return False, False # One is dict, other is not
|
|
79
|
+
return True, None # Continue, not dictionaries
|
|
80
|
+
|
|
81
|
+
def _compare_sequences(self, self_value, other_value):
|
|
82
|
+
"""Compare lists and tuples. Returns (should_continue, result)."""
|
|
83
|
+
if isinstance(self_value, (list, tuple)) and isinstance(other_value, (list, tuple)):
|
|
84
|
+
return False, type(self_value) == type(other_value) and self_value == other_value
|
|
85
|
+
elif isinstance(self_value, (list, tuple)) or isinstance(other_value, (list, tuple)):
|
|
86
|
+
return False, False # One is sequence, other is not
|
|
87
|
+
return True, None # Continue, not sequences
|
|
88
|
+
|
|
89
|
+
def _compare_other_types(self, self_value, other_value):
|
|
90
|
+
"""Compare all other types. Returns (should_continue, result)."""
|
|
91
|
+
return False, self_value == other_value
|
|
92
|
+
|
|
93
|
+
def __eq__(self, other):
|
|
94
|
+
"""
|
|
95
|
+
Compare two instances based on all their @property decorated attributes.
|
|
96
|
+
|
|
97
|
+
Returns True if all properties have equal values, False otherwise.
|
|
98
|
+
Returns False if other is not an instance of the same class.
|
|
99
|
+
"""
|
|
100
|
+
# Quick identity check first (performance optimization)
|
|
101
|
+
if self is other:
|
|
102
|
+
return True
|
|
103
|
+
|
|
104
|
+
# Check if other is the same type
|
|
105
|
+
if type(other) != type(self):
|
|
106
|
+
return False
|
|
107
|
+
|
|
108
|
+
# Cache properties to avoid repeated computation (performance optimization)
|
|
109
|
+
if not hasattr(self, '_cached_properties'):
|
|
110
|
+
self._cached_properties = self._get_comparable_properties()
|
|
111
|
+
|
|
112
|
+
# Define comparison methods in order of priority/frequency
|
|
113
|
+
comparison_methods = [
|
|
114
|
+
self._compare_none_values,
|
|
115
|
+
self._compare_plotly_traces,
|
|
116
|
+
self._compare_numpy_arrays,
|
|
117
|
+
self._compare_dataframes,
|
|
118
|
+
self._compare_dictionaries,
|
|
119
|
+
self._compare_sequences,
|
|
120
|
+
self._compare_other_types,
|
|
121
|
+
]
|
|
122
|
+
|
|
123
|
+
# Compare all property values
|
|
124
|
+
for prop_name in self._cached_properties:
|
|
125
|
+
|
|
126
|
+
try:
|
|
127
|
+
self_value = getattr(self, prop_name)
|
|
128
|
+
other_value = getattr(other, prop_name)
|
|
129
|
+
|
|
130
|
+
# Execute comparison methods until one handles the values
|
|
131
|
+
for method in comparison_methods:
|
|
132
|
+
should_continue, result = method(self_value, other_value)
|
|
133
|
+
if not should_continue:
|
|
134
|
+
if not result:
|
|
135
|
+
return False
|
|
136
|
+
break # Values are equal, continue to next property
|
|
137
|
+
|
|
138
|
+
except (AttributeError, Exception):
|
|
139
|
+
# If property doesn't exist or comparison fails
|
|
140
|
+
return False
|
|
141
|
+
|
|
142
|
+
return True
|
|
143
|
+
|
|
144
|
+
def __hash__(self):
|
|
145
|
+
"""
|
|
146
|
+
Simple, robust hash based on object identity.
|
|
147
|
+
|
|
148
|
+
Uses id() for a fast, guaranteed-unique hash that won't fail.
|
|
149
|
+
Objects are only equal if they're the same instance.
|
|
150
|
+
"""
|
|
151
|
+
return hash(id(self))
|
|
152
|
+
|
|
153
|
+
def __str__(self):
|
|
154
|
+
"""
|
|
155
|
+
String representation of the instance showing all @property decorated attributes and their values.
|
|
156
|
+
"""
|
|
157
|
+
return f"{self.__class__.__name__}, {self.__name__}"
|
|
158
|
+
|
|
159
|
+
def __repr__(self):
|
|
160
|
+
"""
|
|
161
|
+
Official string representation of the instance.
|
|
162
|
+
"""
|
|
163
|
+
return self.__str__()
|
|
164
|
+
|
steer_core/Mixins/TypeChecker.py
CHANGED
|
@@ -1,12 +1,37 @@
|
|
|
1
1
|
from typing import Type
|
|
2
2
|
import pandas as pd
|
|
3
3
|
import numpy as np
|
|
4
|
+
import plotly.graph_objects as go
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
ALLOWED_REFERENCE = ["Na/Na+", "Li/Li+"]
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
class ValidationMixin:
|
|
11
|
+
|
|
12
|
+
@staticmethod
|
|
13
|
+
def validate_plotly_trace(value: object, name: str) -> None:
|
|
14
|
+
"""
|
|
15
|
+
Validate that a value is a Plotly trace object.
|
|
16
|
+
|
|
17
|
+
Parameters
|
|
18
|
+
----------
|
|
19
|
+
value : object
|
|
20
|
+
The value to validate.
|
|
21
|
+
name : str
|
|
22
|
+
The name of the parameter for error messages.
|
|
23
|
+
|
|
24
|
+
Raises
|
|
25
|
+
------
|
|
26
|
+
TypeError
|
|
27
|
+
If the value is not a Plotly trace object.
|
|
28
|
+
"""
|
|
29
|
+
return (
|
|
30
|
+
hasattr(value, '__module__') and
|
|
31
|
+
value.__module__ and
|
|
32
|
+
value.__module__.startswith('plotly.graph_objs')
|
|
33
|
+
)
|
|
34
|
+
|
|
10
35
|
@staticmethod
|
|
11
36
|
def validate_type(value: Type, expected_type: Type, name: str) -> None:
|
|
12
37
|
"""
|
|
@@ -27,9 +52,7 @@ class ValidationMixin:
|
|
|
27
52
|
If the value is not of the expected type.
|
|
28
53
|
"""
|
|
29
54
|
if not isinstance(value, expected_type):
|
|
30
|
-
raise TypeError(
|
|
31
|
-
f"{name} must be of type {expected_type.__name__}. Provided: {type(value).__name__}."
|
|
32
|
-
)
|
|
55
|
+
raise TypeError(f"{name} must be of type {expected_type.__name__}. Provided: {type(value).__name__}.")
|
|
33
56
|
|
|
34
57
|
@staticmethod
|
|
35
58
|
def validate_percentage(value: float, name: str) -> None:
|
steer_core/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.1.
|
|
1
|
+
__version__ = "0.1.20"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
steer_core/DataManager.py,sha256=06TrnBa4SLGvLeH2DacCxwGZ4zjLZslwNcwIlmfhxtA,10943
|
|
2
|
-
steer_core/__init__.py,sha256=
|
|
2
|
+
steer_core/__init__.py,sha256=8XalsVoLEfXslFvdtUEmkNOuYShzOzYOcFbgmOz1oSk,23
|
|
3
3
|
steer_core/Apps/ContextManagers.py,sha256=-ImT0O8BdmPKOd_e7wS6AWJMMQme7nGDEUdxTi_wv8s,1870
|
|
4
4
|
steer_core/Apps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
5
|
steer_core/Apps/Components/MaterialSelectors.py,sha256=LBf2PvHkyAXUoZgEhoJCfo5shEfaloa6l3PeOJAakFk,35707
|
|
@@ -15,20 +15,21 @@ steer_core/Constants/Universal.py,sha256=5FWdrex5NiI2DResDmwO7GIvGN2B0DNtdlG1l-y
|
|
|
15
15
|
steer_core/Constants/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
16
|
steer_core/ContextManagers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
17
|
steer_core/Data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
18
|
-
steer_core/Data/database.db,sha256=
|
|
18
|
+
steer_core/Data/database.db,sha256=y8cJv-W2T1EXoULbd8cT6AlN_yUIaTAkObX0pMDB4Oc,13615104
|
|
19
19
|
steer_core/Decorators/Coordinates.py,sha256=MxUWXQNrR9Q0_p4gGAywS4qnPAztajJzSay1Cu6lCRQ,1441
|
|
20
|
-
steer_core/Decorators/Electrochemical.py,sha256=
|
|
21
|
-
steer_core/Decorators/General.py,sha256=
|
|
20
|
+
steer_core/Decorators/Electrochemical.py,sha256=nrNnTG4weyQOq1VLybjWWcbgGoth8ndvy3muN51xpwU,986
|
|
21
|
+
steer_core/Decorators/General.py,sha256=lc7YdvxU-JDo8b4kunVzSjxcB3_8C185458HrXQq-lk,970
|
|
22
22
|
steer_core/Decorators/Objects.py,sha256=aYaRQBFgdSE0IB4QgBVfb6GhEPagoU6TRNrW_pOaqQI,506
|
|
23
23
|
steer_core/Decorators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
24
24
|
steer_core/Mixins/Colors.py,sha256=vbo44Fr0oeziwHJ-tu7ojG-GzqFc2LBcT_hH4szvPFc,6796
|
|
25
25
|
steer_core/Mixins/Coordinates.py,sha256=irdrrXIm7lmjMqgXyRXmu-x5swNQHhR7S0EZTBhvV8U,12824
|
|
26
26
|
steer_core/Mixins/Data.py,sha256=2SXRIExCmd98N5JtNEFCQ9poi94fRF_GV5TNYjEGy6o,1363
|
|
27
|
+
steer_core/Mixins/Dunder.py,sha256=591oDGiRPdLH1bDIc1FUw33eeRtSc4pC7UbKEIGPm1I,7035
|
|
27
28
|
steer_core/Mixins/Plotter.py,sha256=zYj-P9ryhSUe5mHoIyjasZSOnY5sDCFKx6u73E8rFZc,5424
|
|
28
|
-
steer_core/Mixins/
|
|
29
|
-
steer_core/Mixins/TypeChecker.py,sha256=YXvM3s0NIMGf8Dyk7xWgEMUak-tkuPxNK7ZgmefRUoE,7577
|
|
29
|
+
steer_core/Mixins/TypeChecker.py,sha256=CIv-Tt-NECR55hbscBvqQnzzABflj4bHG2zYHV4kLwk,8199
|
|
30
30
|
steer_core/Mixins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
31
|
-
steer_core
|
|
32
|
-
steer_core-0.1.
|
|
33
|
-
steer_core-0.1.
|
|
34
|
-
steer_core-0.1.
|
|
31
|
+
steer_core/Mixins/serializer.py,sha256=VC3sqfPMR8BxBC7WaDO6cCDpVAgLV8MKAVZtiX953gQ,1016
|
|
32
|
+
steer_core-0.1.20.dist-info/METADATA,sha256=vfJQ4joPBy8fuJ_uCyFEeV4FkSIc3mRd63fMg9RCEdw,704
|
|
33
|
+
steer_core-0.1.20.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
34
|
+
steer_core-0.1.20.dist-info/top_level.txt,sha256=6LFpGCSDE_SqRoT7raeM3Ax7KTBKQnyXLXxM9kXtw5M,11
|
|
35
|
+
steer_core-0.1.20.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|