diff --git a/docs/docs/tutorials/fitting-bayesian.ipynb b/docs/docs/tutorials/fitting-bayesian.ipynb index 695ca508..4ddb4239 100644 --- a/docs/docs/tutorials/fitting-bayesian.ipynb +++ b/docs/docs/tutorials/fitting-bayesian.ipynb @@ -163,10 +163,10 @@ "from easyscience import ObjBase\n", "from easyscience import Parameter\n", "\n", - "area = Parameter(name='area', value=10, fixed=False, min=1, max=100)\n", - "gamma = Parameter(name='gamma', value=8e-3, fixed=False, min=1e-4, max=1e-2)\n", - "omega_0 = Parameter(name='omega_0', value=1e-3, fixed=False, min=0, max=2e-3)\n", - "sigma = Parameter(name='sigma', value=1e-3, fixed=False, min=1e-5, max=1e-1)\n", + "area = Parameter(display_name='area', value=10, fixed=False, min=1, max=100)\n", + "gamma = Parameter(display_name='gamma', value=8e-3, fixed=False, min=1e-4, max=1e-2)\n", + "omega_0 = Parameter(display_name='omega_0', value=1e-3, fixed=False, min=0, max=2e-3)\n", + "sigma = Parameter(display_name='sigma', value=1e-3, fixed=False, min=1e-5, max=1e-1)\n", "\n", "parameter_container = ObjBase(name='params', A=area, gamma=gamma, omega_0=omega_0, sigma=sigma)" ] diff --git a/docs/docs/tutorials/fitting-qens.ipynb b/docs/docs/tutorials/fitting-qens.ipynb index a4929a5c..0b820cab 100644 --- a/docs/docs/tutorials/fitting-qens.ipynb +++ b/docs/docs/tutorials/fitting-qens.ipynb @@ -246,10 +246,10 @@ "source": [ "from easyscience import Parameter\n", "\n", - "A = Parameter(name='A', value=10, fixed=False, min=0.01, max=100)\n", - "gamma = Parameter(name='gamma', value=8e-3, fixed=False, min=1e-4, max=10e-3)\n", - "omega_0 = Parameter(name='omega_0', value=0.001, fixed=False, min=0, max=0.002)\n", - "sigma = Parameter(name='sigma', value=0.001, fixed=False, min=1e-5, max=0.1)" + "A = Parameter(display_name='A', value=10, fixed=False, min=0.01, max=100)\n", + "gamma = Parameter(display_name='gamma', value=8e-3, fixed=False, min=1e-4, max=10e-3)\n", + "omega_0 = Parameter(display_name='omega_0', value=0.001, fixed=False, min=0, max=0.002)\n", + "sigma = Parameter(display_name='sigma', value=0.001, fixed=False, min=1e-5, max=0.1)" ] }, { diff --git a/docs/docs/tutorials/fitting-sans.ipynb b/docs/docs/tutorials/fitting-sans.ipynb index 06b0cc36..02fdb97f 100644 --- a/docs/docs/tutorials/fitting-sans.ipynb +++ b/docs/docs/tutorials/fitting-sans.ipynb @@ -236,10 +236,10 @@ "source": [ "from easyscience import Parameter\n", "\n", - "scale = Parameter(name='scale', value=1.4e-7, fixed=True)\n", - "delta_rho = Parameter(name='delta_rho', value=3, fixed=False, min=0, max=10)\n", - "r = Parameter(name='r', value=80, fixed=False, min=0, max=1000)\n", - "bkg = Parameter(name='bkg', value=0.01, fixed=False, min=0.001, max=0.1)" + "scale = Parameter(display_name='scale', value=1.4e-7, fixed=True)\n", + "delta_rho = Parameter(display_name='delta_rho', value=3, fixed=False, min=0, max=10)\n", + "r = Parameter(display_name='r', value=80, fixed=False, min=0, max=1000)\n", + "bkg = Parameter(display_name='bkg', value=0.01, fixed=False, min=0.001, max=0.1)" ] }, { diff --git a/docs/docs/tutorials/progress-callback.ipynb b/docs/docs/tutorials/progress-callback.ipynb index a5625a5a..d6c6d616 100644 --- a/docs/docs/tutorials/progress-callback.ipynb +++ b/docs/docs/tutorials/progress-callback.ipynb @@ -97,7 +97,7 @@ " sigma3: Parameter\n", "\n", " def __init__(self, **values):\n", - " params = {name: Parameter(name, value) for name, value in values.items()}\n", + " params = {name: Parameter(value, display_name=name) for name, value in values.items()}\n", " super().__init__('multipeak', **params)\n", "\n", " def __call__(self, x):\n", diff --git a/legacy/PARAMETER_DEPENDENCY_SERIALIZATION.md b/legacy/PARAMETER_DEPENDENCY_SERIALIZATION.md deleted file mode 100644 index 66a6659b..00000000 --- a/legacy/PARAMETER_DEPENDENCY_SERIALIZATION.md +++ /dev/null @@ -1,259 +0,0 @@ -# Parameter Dependency Serialization - -This document explains how to serialize and deserialize `Parameter` -objects that have dependencies. - -## Overview - -Parameters with dependencies can now be serialized to dictionaries (and -JSON) while preserving their dependency relationships. After -deserialization, the dependencies are automatically reconstructed using -the `serializer_id` attribute to match parameters, with `unique_name` -attribute being used as a fallback. - -## Key Features - -- **Automatic dependency serialization**: Dependency expressions and - maps are automatically saved during serialization -- **Reliable dependency resolution**: Dependencies are resolved using - stable `serializer_id` attributes with `unique_name` as fallback after - deserialization -- **Order-independent loading**: Parameters can be loaded in any order - thanks to the reliable ID system -- **Bulk dependency resolution**: Utility functions help resolve all - dependencies at once -- **JSON compatibility**: Full support for JSON - serialization/deserialization -- **Backward compatibility**: Existing code using `unique_name` - continues to work as fallback - -## Usage - -### Basic Serialization/Deserialization - -```python -import json -from easyscience import Parameter, global_object -from easyscience.variable.parameter_dependency_resolver import resolve_all_parameter_dependencies - -# Create parameters with dependencies -a = Parameter(name="a", value=2.0, unit="m", min=0, max=10) -b = Parameter.from_dependency( - name="b", - dependency_expression="2 * a", - dependency_map={"a": a}, - unit="m" -) - -# Serialize to dictionary and save to file -params_dict = {"a": a.as_dict(), "b": b.as_dict()} -with open("parameters.json", "w") as f: - json.dump(params_dict, f, indent=2, default=str) - -print("Parameters saved to parameters.json") -``` - -In a new Python session: - -```python -import json -from easyscience import Parameter, global_object -from easyscience.variable.parameter_dependency_resolver import resolve_all_parameter_dependencies - -# Load parameters from file -with open("parameters.json", "r") as f: - params_dict = json.load(f) - -# Clear global map (simulate new environment) -global_object.map._clear() - -# Deserialize parameters -new_a = Parameter.from_dict(params_dict["a"]) -new_b = Parameter.from_dict(params_dict["b"]) - -# Resolve dependencies -resolve_all_parameter_dependencies({"a": new_a, "b": new_b}) - -# Dependencies are now working -new_a.value = 5.0 -print(new_b.value) # Will be 10.0 (2 * 5.0) -``` - -### JSON Serialization - -```python -import json - -# Serialize to JSON -param_dict = parameter.as_dict() -json_str = json.dumps(param_dict, default=str) - -# Deserialize from JSON -loaded_dict = json.loads(json_str) -new_param = Parameter.from_dict(loaded_dict) - -# Resolve dependencies -resolve_all_parameter_dependencies(new_param) -``` - -### Bulk Operations - -```python -from easyscience.variable.parameter_dependency_resolver import get_parameters_with_pending_dependencies - -# Create multiple parameters with dependencies -params = create_parameter_hierarchy() # Your function - -# Serialize all -serialized = {name: param.as_dict() for name, param in params.items()} - -# Clear and deserialize -global_object.map._clear() -new_params = {name: Parameter.from_dict(d) for name, d in serialized.items()} - -# Check which parameters have pending dependencies -pending = get_parameters_with_pending_dependencies(new_params) -print(f"Found {len(pending)} parameters with pending dependencies") - -# Resolve all at once -resolve_all_parameter_dependencies(new_params) -``` - -## Implementation Details - -### Serialization - -During serialization, the following additional fields are added to -dependent parameters: - -- `_dependency_string`: The original dependency expression -- `_dependency_map_serializer_ids`: A mapping of dependency keys to - stable dependency IDs (preferred) -- `_dependency_map_unique_names`: A mapping of dependency keys to unique - names (fallback) -- `__serializer_id`: The parameter's own unique dependency ID -- `_independent`: Boolean flag indicating if the parameter is dependent - -### Deserialization - -During deserialization: - -1. Parameters are created normally but marked as independent temporarily -2. Dependency information is stored in `_pending_dependency_string`, - `_pending_dependency_map_serializer_ids`, and - `_pending_dependency_map_unique_names` attributes -3. The parameter's own `__serializer_id` is restored from serialized - data -4. After all parameters are loaded, - `resolve_all_parameter_dependencies()` establishes the dependency - relationships using dependency IDs first, then unique names as - fallback - -### Dependency Resolution - -The dependency resolution process: - -1. Scans for parameters with pending dependencies -2. First attempts to look up dependency objects by their stable - `serializer_id` -3. Falls back to `unique_name` lookup in the global map if serializer_id - is not available -4. Calls `make_dependent_on()` to establish the dependency relationship -5. Cleans up temporary attributes - -This dual-strategy approach ensures reliable dependency resolution -regardless of parameter loading order while maintaining backward -compatibility. - -## Error Handling - -The system provides detailed error messages for common issues: - -- Missing dependencies (parameter with required unique_name not found) -- Invalid dependency expressions -- Circular dependency detection - -## Utility Functions - -### `resolve_all_parameter_dependencies(obj)` - -Recursively finds all Parameter objects with pending dependencies and -resolves them. - -**Parameters:** - -- `obj`: Object to search for Parameters (can be Parameter, list, dict, - or complex object) - -**Returns:** - -- None (modifies parameters in place) - -**Raises:** - -- `ValueError`: If dependency resolution fails - -### `get_parameters_with_pending_dependencies(obj)` - -Finds all Parameter objects that have pending dependencies. - -**Parameters:** - -- `obj`: Object to search for Parameters - -**Returns:** - -- `List[Parameter]`: List of parameters with pending dependencies - -## Best Practices - -1. **Always resolve dependencies after deserialization**: Use - `resolve_all_parameter_dependencies()` after loading serialized - parameters - -2. **Handle the global map carefully**: The global map must contain all - referenced parameters for dependency resolution to work - -3. **Use unique names for cross-references**: When creating dependency - expressions that reference other parameters, consider using unique - names with quotes: `'Parameter_0'` - -4. **Error handling**: Wrap dependency resolution in try-catch blocks - for robust error handling - -5. **Bulk operations**: For complex object hierarchies, use the utility - functions to handle all parameters at once - -6. **Reliable ordering**: With the new dependency ID system, parameters - can be loaded in any order without affecting dependency resolution - -7. **Access dependency ID**: Use `parameter.serializer_id` to access the - stable ID for debugging or manual cross-referencing - -## Example: Complex Hierarchy - -```python -def save_model(model): - \"\"\"Save a model with parameter dependencies to JSON.\"\"\" - model_dict = model.as_dict() - with open('model.json', 'w') as f: - json.dump(model_dict, f, indent=2, default=str) - -def load_model(filename): - \"\"\"Load a model from JSON and resolve dependencies.\"\"\" - global_object.map._clear() # Start fresh - - with open(filename) as f: - model_dict = json.load(f) - - model = Model.from_dict(model_dict) - - # Resolve all parameter dependencies - resolve_all_parameter_dependencies(model) - - return model -``` - -This system ensures that complex parameter hierarchies with dependencies -can be reliably serialized and reconstructed while maintaining their -behavioral relationships. diff --git a/pixi.toml b/pixi.toml index a3237349..4873d04f 100644 --- a/pixi.toml +++ b/pixi.toml @@ -3,14 +3,13 @@ ########### [workspace] - # Supported platforms for the lock file (pixi.lock) platforms = [ 'win-64', # Set minimum supported version for glibc to be 2.35 to ensure packages # like `crysfml` that only have wheels for glibc 2.35+ # (manylinux_2_35_x86_64) are used. - #libc = { family = 'glibc', version = '2.35' } + # libc = { family = 'glibc', version = '2.35' } { platform = 'linux-64', glibc = '2.35' }, # Set minimum supported version for macOS to be 14.0 to ensure packages # like `scipp` that only have wheels for macOS 14.0+ (macosx_14_0_arm64) @@ -44,8 +43,8 @@ python = '3.14.*' # editable installations. [feature.dev.dependencies] -nodejs = '*' # Required for Prettier (non-Python formatting) -pixi-kernel = '*' # Pixi Jupyter kernel +nodejs = '*' # Required for Prettier (non-Python formatting) +pixi-kernel = '*' # Pixi Jupyter kernel [feature.dev.pypi-dependencies] pip = '*' @@ -55,7 +54,7 @@ easyscience = { path = '.', editable = true, extras = ['dev'] } # of editable installations. [feature.user.dependencies] -pixi-kernel = '*' # Pixi Jupyter kernel +pixi-kernel = '*' # Pixi Jupyter kernel [feature.user.pypi-dependencies] pip = '*' @@ -66,7 +65,6 @@ easyscience = '*' ############## [environments] - # The `default` feature is always included in all environments. # Additional features can be specified per environment. @@ -87,7 +85,6 @@ user = { features = ['py-max', 'user'] } ####### [tasks] - ################## # 🧪 Testing Tasks ################## @@ -172,9 +169,9 @@ notebook-tweak = 'python tools/tweak_notebooks.py docs/docs/tutorials/' notebook-exec = 'python -m pytest --nbmake docs/docs/tutorials/ --nbmake-timeout=1200 --overwrite --color=yes -n auto -v' notebook-prepare = { depends-on = [ - #'notebook-convert', + # 'notebook-convert', 'notebook-strip', - #'notebook-tweak', + # 'notebook-tweak', ] } ######################## @@ -266,7 +263,7 @@ clean-pycache = "find . -type d -name '__pycache__' -prune -exec rm -rf '{}' +" post-install = { depends-on = [ 'npm-config', 'prettier-install', - #'pre-commit-setup', + # 'pre-commit-setup', ] } ########################## diff --git a/prettierrc.toml b/prettierrc.toml index b98c86eb..d8a956f5 100644 --- a/prettierrc.toml +++ b/prettierrc.toml @@ -1,22 +1,24 @@ plugins = [ - "prettier-plugin-toml", # use the TOML plugin + 'prettier-plugin-toml', # use the TOML plugin ] -endOfLine = 'lf' # change line endings to LF -proseWrap = 'always' # change wrapping in Markdown files -semi = false # remove semicolons -singleQuote = true # use single quotes instead of double quotes -tabWidth = 2 # change tab width to 2 spaces -useTabs = false # use spaces instead of tabs +endOfLine = 'lf' # change line endings to LF +proseWrap = 'always' # change wrapping in Markdown files +semi = false # remove semicolons +singleQuote = true # use single quotes instead of double quotes +tabWidth = 2 # change tab width to 2 spaces +useTabs = false # use spaces instead of tabs -printWidth = 79 # wrap lines at 79 characters +printWidth = 79 # wrap lines at 79 characters [[overrides]] -files = ["*.md"] +files = ['*.md'] + [overrides.options] -printWidth = 72 # wrap Markdown files at 72 characters +printWidth = 72 # wrap Markdown files at 72 characters [[overrides]] -files = ["*.yml", "*.yaml"] +files = ['*.yml', '*.yaml'] + [overrides.options] -printWidth = 88 # wrap YAML files at 88 characters +printWidth = 88 # wrap YAML files at 88 characters diff --git a/pyproject.toml b/pyproject.toml index 89d28050..aa57296e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ [project] name = 'easyscience' -dynamic = ['version'] # Use versioningit to manage the version +dynamic = ['version'] # Use versioningit to manage the version description = 'Core building blocks for EasyScience' authors = [{ name = 'EasyScience contributors' }] readme = 'README.md' @@ -24,54 +24,54 @@ classifiers = [ ] requires-python = '>=3.11' dependencies = [ - 'asteval', # Safely evaluate Python expressions from strings - 'lmfit', # Non-linear least squares fitting - 'bumps>=1.0.4', # Bayesian uncertainty estimation - 'dfo-ls', # Derivative-free optimization - 'numpy', # Numerical computing - 'scipp', # Handling and analysis of scientific data + 'asteval', # Safely evaluate Python expressions from strings + 'lmfit', # Non-linear least squares fitting + 'bumps>=1.0.4', # Bayesian uncertainty estimation + 'dfo-ls', # Derivative-free optimization + 'numpy', # Numerical computing + 'scipp', # Handling and analysis of scientific data ] [project.optional-dependencies] dev = [ - 'pooch', # Data downloader - 'matplotlib', # Plotting library - 'jupyterlab', # Jupyter notebooks - 'ipykernel', # Jupyter kernel (required for running notebooks) - 'ipywidgets', # Widgets (needed for interactive matplotlib backends) - 'ipympl', # Matplotlib Jupyter widget backend (%matplotlib widget) - 'IPython', # Interactive Python shell - 'GitPython', # Interact with Git repositories - 'build', # Building the package - 'pre-commit', # Pre-commit hooks - 'jinja2', # Templating - 'nbmake', # Building notebooks - 'nbstripout', # Strip output from notebooks - 'nbqa', # Linting and formatting notebooks - 'pytest', # Testing - 'pytest-cov', # Test coverage - 'pytest-xdist', # Enable parallel testing - 'ruff', # Linting and formatting code - 'radon', # Code complexity and maintainability - 'validate-pyproject[all]', # Validate pyproject.toml - 'versioningit', # Automatic versioning from git tags - 'jupytext', # Jupyter notebook text format support - 'jupyterquiz', # Quizzes in Jupyter notebooks - 'pydoclint', # Docstring linter - 'format-docstring', # Docstring formatter - 'docstripy', # Convert docstrings to other formats - 'interrogate', # Docstring coverage checker - 'copier', # Template management - 'mike', # MkDocs: Versioned documentation support - 'mkdocs', # Static site generator - 'mkdocs-material', # Documentation framework on top of MkDocs - 'mkdocs-autorefs', # MkDocs: Auto-references support - 'mkdocs-jupyter', # MkDocs: Jupyter notebook support - 'mkdocs-plugin-inline-svg', # MkDocs: Inline SVG support - 'mkdocs-markdownextradata-plugin', # MkDocs: Markdown extra data support, such as global variables - 'mkdocstrings-python', # MkDocs: Python docstring support - 'pyyaml', # YAML parser - 'spdx-headers', # SPDX license header validation + 'pooch', # Data downloader + 'matplotlib', # Plotting library + 'jupyterlab', # Jupyter notebooks + 'ipykernel', # Jupyter kernel (required for running notebooks) + 'ipywidgets', # Widgets (needed for interactive matplotlib backends) + 'ipympl', # Matplotlib Jupyter widget backend (%matplotlib widget) + 'IPython', # Interactive Python shell + 'GitPython', # Interact with Git repositories + 'build', # Building the package + 'pre-commit', # Pre-commit hooks + 'jinja2', # Templating + 'nbmake', # Building notebooks + 'nbstripout', # Strip output from notebooks + 'nbqa', # Linting and formatting notebooks + 'pytest', # Testing + 'pytest-cov', # Test coverage + 'pytest-xdist', # Enable parallel testing + 'ruff', # Linting and formatting code + 'radon', # Code complexity and maintainability + 'validate-pyproject[all]', # Validate pyproject.toml + 'versioningit', # Automatic versioning from git tags + 'jupytext', # Jupyter notebook text format support + 'jupyterquiz', # Quizzes in Jupyter notebooks + 'pydoclint', # Docstring linter + 'format-docstring', # Docstring formatter + 'docstripy', # Convert docstrings to other formats + 'interrogate', # Docstring coverage checker + 'copier', # Template management + 'mike', # MkDocs: Versioned documentation support + 'mkdocs', # Static site generator + 'mkdocs-material', # Documentation framework on top of MkDocs + 'mkdocs-autorefs', # MkDocs: Auto-references support + 'mkdocs-jupyter', # MkDocs: Jupyter notebook support + 'mkdocs-plugin-inline-svg', # MkDocs: Inline SVG support + 'mkdocs-markdownextradata-plugin', # MkDocs: Markdown extra data support, such as global variables + 'mkdocstrings-python', # MkDocs: Python docstring support + 'pyyaml', # YAML parser + 'spdx-headers', # SPDX license header validation ] [project.urls] @@ -102,7 +102,7 @@ packages = ['src/easyscience'] allow-direct-references = true [tool.hatch.version] -source = 'versioningit' # Use versioningit to manage the version +source = 'versioningit' # Use versioningit to manage the version ################################ # Configuration for versioningit @@ -118,9 +118,9 @@ source = 'versioningit' # Use versioningit to manage the version # pixi.lock update without any changes to the source code. [tool.versioningit.format] -distance = '{base_version}+dev{distance}' # example: 1.2.3.post4+dev3 -dirty = '{base_version}+dirty{distance}' # example: 0.5.8+dirty3 -distance-dirty = '{base_version}+devdirty{distance}' # example: 0.5.8+devdirty3 +distance = '{base_version}+dev{distance}' # example: 1.2.3.post4+dev3 +dirty = '{base_version}+dirty{distance}' # example: 0.5.8+dirty3 +distance-dirty = '{base_version}+devdirty{distance}' # example: 0.5.8+devdirty3 # Configure how versioningit detects versions from Git # - 'match' ensures it only considers tags starting with 'v' @@ -138,7 +138,7 @@ default-tag = 'v999.0.0' # https://interrogate.readthedocs.io/en/latest/ [tool.interrogate] -fail-under = 45 # Minimum docstring coverage percentage to pass +fail-under = 45 # Minimum docstring coverage percentage to pass verbose = 1 exclude = ['src/easyscience/legacy'] @@ -150,13 +150,13 @@ exclude = ['src/easyscience/legacy'] # https://coverage.readthedocs.io/en/latest/ [tool.coverage.run] -branch = true # Measure branch coverage as well -source = ['src'] # Limit coverage to the source code directory +branch = true # Measure branch coverage as well +source = ['src'] # Limit coverage to the source code directory [tool.coverage.report] show_missing = true # Show missing lines -skip_covered = false # Skip files with 100% coverage in the report -fail_under = 80 # Minimum coverage percentage to pass +skip_covered = false # Skip files with 100% coverage in the report +fail_under = 80 # Minimum coverage percentage to pass ########################## # Configuration for pytest @@ -180,31 +180,31 @@ testpaths = ['tests'] [tool.ruff] exclude = ['tests', 'legacy', 'src/easyscience/legacy'] indent-width = 4 -line-length = 99 # See also `max-line-length` in [tool.ruff.lint.pycodestyle] -preview = true # Enable new rules that are not yet stable, like DOC +line-length = 99 # See also `max-line-length` in [tool.ruff.lint.pycodestyle] +preview = true # Enable new rules that are not yet stable, like DOC builtins = [ 'display', -] # Clutch-fix/patch to https://github.com/nbQA-dev/nbQA/issues/882 +] # Clutch-fix/patch to https://github.com/nbQA-dev/nbQA/issues/882 # Formatting options for Ruff [tool.ruff.format] -docstring-code-format = true # Whether to format code snippets in docstrings -docstring-code-line-length = 72 # Line length for code snippets in docstrings -indent-style = 'space' # PEP 8 recommends using spaces over tabs -quote-style = 'single' # But double quotes in docstrings (PEP 8, PEP 257) +docstring-code-format = true # Whether to format code snippets in docstrings +docstring-code-line-length = 72 # Line length for code snippets in docstrings +indent-style = 'space' # PEP 8 recommends using spaces over tabs +quote-style = 'single' # But double quotes in docstrings (PEP 8, PEP 257) # Linting rules to use with Ruff [tool.ruff.lint] select = [ - # 'E', # General PEP 8 style errors - 'E9', # Runtime errors (e.g., syntax errors, undefined names) - # 'F', # Pyflakes-specific checks (e.g., unused variables, imports) - 'F63', # Issues related to invalid escape sequences in strings + # 'E', # General PEP 8 style errors + 'E9', # Runtime errors (e.g., syntax errors, undefined names) + # 'F', # Pyflakes-specific checks (e.g., unused variables, imports) + 'F63', # Issues related to invalid escape sequences in strings 'F7', # Type-related errors (e.g., mismatched argument types, unsupported operations) - 'F82', # Import-related errors (e.g., unresolved imports, reimported modules) - 'I', # Import sorting issues (e.g., unsorted imports) - # 'S', # Security-related issues (e.g., use of insecure functions or libraries) + 'F82', # Import-related errors (e.g., unresolved imports, reimported modules) + 'I', # Import sorting issues (e.g., unsorted imports) + # 'S', # Security-related issues (e.g., use of insecure functions or libraries) # 'W', # General PEP 8 warnings (e.g., lines too long, trailing whitespace) ] @@ -212,31 +212,31 @@ select = [ # Ignore specific rules globally ignore = [ - 'COM812', # https://docs.astral.sh/ruff/rules/missing-trailing-comma/ + 'COM812', # https://docs.astral.sh/ruff/rules/missing-trailing-comma/ # Replaced by 'D' plus pydocstyle and pydoclint - 'DOC', # https://docs.astral.sh/ruff/rules/#pydoclint-doc + 'DOC', # https://docs.astral.sh/ruff/rules/#pydoclint-doc # Disable, as [tool.format_docstring] split one-line docstrings into the canonical multi-line layout - 'D200', # https://docs.astral.sh/ruff/rules/unnecessary-multiline-docstring/ + 'D200', # https://docs.astral.sh/ruff/rules/unnecessary-multiline-docstring/ ] # Ignore specific rules in certain files or directories [tool.ruff.lint.per-file-ignores] '*/__init__.py' = [ - 'F401', # re-exports are intentional in __init__.py + 'F401', # re-exports are intentional in __init__.py ] 'tests/**' = [ - 'ANN', # https://docs.astral.sh/ruff/rules/#flake8-annotations-ann - 'D', # https://docs.astral.sh/ruff/rules/#pydocstyle-d - 'DOC', # https://docs.astral.sh/ruff/rules/#pydoclint-doc - 'INP001', # https://docs.astral.sh/ruff/rules/implicit-namespace-package/ - 'S101', # https://docs.astral.sh/ruff/rules/assert/ + 'ANN', # https://docs.astral.sh/ruff/rules/#flake8-annotations-ann + 'D', # https://docs.astral.sh/ruff/rules/#pydocstyle-d + 'DOC', # https://docs.astral.sh/ruff/rules/#pydoclint-doc + 'INP001', # https://docs.astral.sh/ruff/rules/implicit-namespace-package/ + 'S101', # https://docs.astral.sh/ruff/rules/assert/ ] 'docs/**' = [ - 'INP001', # https://docs.astral.sh/ruff/rules/implicit-namespace-package/ - 'T201', # https://docs.astral.sh/ruff/rules/print/ + 'INP001', # https://docs.astral.sh/ruff/rules/implicit-namespace-package/ + 'T201', # https://docs.astral.sh/ruff/rules/print/ ] 'docs/docs/tutorials/**' = [ - 'E402', # https://docs.astral.sh/ruff/rules/module-import-not-at-top-of-file/ + 'E402', # https://docs.astral.sh/ruff/rules/module-import-not-at-top-of-file/ ] # Specific options for certain rules @@ -258,7 +258,7 @@ max-complexity = 10 # https://peps.python.org/pep-0008/#maximum-line-length # Use 99 characters as the project-wide maximum for regular code lines. # Use 72 characters for docstrings. -max-line-length = 99 # See also `line-length` in [tool.ruff] +max-line-length = 99 # See also `line-length` in [tool.ruff] max-doc-length = 72 [tool.ruff.lint.pydocstyle] diff --git a/src/easyscience/fitting/calculators/interface_factory.py b/src/easyscience/fitting/calculators/interface_factory.py index ad5fbc24..9dd2a71a 100644 --- a/src/easyscience/fitting/calculators/interface_factory.py +++ b/src/easyscience/fitting/calculators/interface_factory.py @@ -188,7 +188,7 @@ def generate_bindings(self, model: Any, *args: Any, ifun: Any = None, **kwargs: class_links = self.__interface_obj.create(model) props = model._get_linkable_attributes() - props_names = [prop.name for prop in props] + props_names = [prop.display_name for prop in props] for item in class_links: for item_key in item.name_conversion.keys(): if item_key not in props_names: diff --git a/src/easyscience/models/polynomial.py b/src/easyscience/models/polynomial.py index 49b4757e..18066e9f 100644 --- a/src/easyscience/models/polynomial.py +++ b/src/easyscience/models/polynomial.py @@ -52,7 +52,9 @@ def __init__( if issubclass(type(item), Parameter): self.coefficients.append(item) elif isinstance(item, float): - self.coefficients.append(Parameter(name='c{}'.format(index), value=item)) + self.coefficients.append( + Parameter(value=item, display_name='c{}'.format(index)) + ) else: raise TypeError('Coefficients must be floats or Parameters') else: diff --git a/src/easyscience/variable/descriptor_any_type.py b/src/easyscience/variable/descriptor_any_type.py index 06f52dbf..c83f62a6 100644 --- a/src/easyscience/variable/descriptor_any_type.py +++ b/src/easyscience/variable/descriptor_any_type.py @@ -28,8 +28,8 @@ class DescriptorAnyType(DescriptorBase): def __init__( self, - name: str, value: Any, + *, unique_name: Optional[str] = None, description: Optional[str] = None, url: Optional[str] = None, @@ -38,18 +38,27 @@ def __init__( """ 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 .. note:: Undo/Redo functionality is - implemented for the attributes ``variance``, ``error``, - ``unit`` and ``value``. + All arguments after ``value`` are keyword-only. + + Parameters + ---------- + value : Any + Value of this object. + unique_name : Optional[str], default=None + Unique identifier for this object. By default, None. + description : Optional[str], default=None + A brief summary of what this object is. By default, None. + url : Optional[str], default=None + Lookup url for documentation/information. By default, None. + display_name : Optional[str], default=None + A pretty name for the object. Falls back to ``unique_name`` + when not given. By default, None. + """ self._value = value super().__init__( - name=name, unique_name=unique_name, description=description, url=url, @@ -87,7 +96,7 @@ def __copy__(self) -> DescriptorAnyType: def __repr__(self) -> str: """ Return a string representation of the DescriptorAnyType, showing - its name and value. + its display name and value. """ if hasattr(self._value, '__repr__'): @@ -95,7 +104,7 @@ def __repr__(self) -> str: else: value_repr = type(self._value) - return f"<{self.__class__.__name__} '{self._name}': {value_repr}>" + return f"<{self.__class__.__name__} '{self.display_name}': {value_repr}>" def to_dict(self, skip: Optional[List[str]] = None) -> Dict[str, Any]: raw_dict = super().to_dict(skip=skip) diff --git a/src/easyscience/variable/descriptor_array.py b/src/easyscience/variable/descriptor_array.py index de6c0dac..b4254532 100644 --- a/src/easyscience/variable/descriptor_array.py +++ b/src/easyscience/variable/descriptor_array.py @@ -34,8 +34,8 @@ class DescriptorArray(DescriptorBase): def __init__( self, - name: str, value: Union[list, np.ndarray], + *, unit: Optional[Union[str, sc.Unit]] = '', variance: Optional[Union[list, np.ndarray]] = None, unique_name: Optional[str] = None, @@ -47,15 +47,43 @@ def __init__( """ Constructor for the DescriptorArray class. - param name: Name of the descriptor param value: List containing - 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 - 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``. + All arguments after ``value`` are keyword-only. + + Parameters + ---------- + value : Union[list, np.ndarray] + Values of this object. + unit : Optional[Union[str, sc.Unit]], default='' + This object can have a physical unit associated with it. By + default, ''. + variance : Optional[Union[list, np.ndarray]], default=None + The variances of the values, with the same shape as + ``value``. By default, None. + unique_name : Optional[str], default=None + Unique identifier for this object. By default, None. + description : Optional[str], default=None + A brief summary of what this object is. By default, None. + url : Optional[str], default=None + Lookup url for documentation/information. By default, None. + display_name : Optional[str], default=None + A pretty name for the object. Falls back to ``unique_name`` + when not given. By default, None. + dimensions : Optional[list], default=None + List of dimensions to pass to scipp. Autogenerated if not + supplied. By default, None. + + Raises + ------ + TypeError + If ``value`` or ``variance`` is not a list or NumPy array, or + if ``unit`` is not a string or scipp unit. + UnitError + If ``unit`` is not a valid scipp unit. + ValueError + If ``variance`` does not match the shape of ``value``, if it + contains negative entries, or if ``dimensions`` does not + match the shape of ``value``. + """ if not isinstance(value, (list, np.ndarray)): @@ -98,7 +126,6 @@ def __init__( # TODO: handle 1xn and nx1 arrays super().__init__( - name=name, unique_name=unique_name, description=description, url=url, @@ -110,14 +137,12 @@ def __init__( self.convert_unit(self._base_unit()) @classmethod - def from_scipp(cls, name: str, full_value: Variable, **kwargs: Any) -> DescriptorArray: + def from_scipp(cls, full_value: Variable, **kwargs: Any) -> DescriptorArray: """ Create a DescriptorArray from a scipp array. Parameters ---------- - name : str - Name of the descriptor. full_value : Variable Value of the descriptor as a scipp variable. **kwargs : Any @@ -136,7 +161,6 @@ def from_scipp(cls, name: str, full_value: Variable, **kwargs: Any) -> Descripto if not isinstance(full_value, Variable): raise TypeError(f'{full_value=} must be a scipp array') return cls( - name=name, value=full_value.values, unit=full_value.unit, variance=full_value.variances, @@ -435,12 +459,12 @@ def __copy__(self) -> DescriptorArray: def __repr__(self) -> str: """ Return a string representation of the DescriptorArray, showing - its name, value, variance, and unit. + its display name, value, variance, and unit. Large arrays are summarized for brevity. """ - # Base string with name - string = f"<{self.__class__.__name__} '{self._name}': " + # Base string with display name + string = f"<{self.__class__.__name__} '{self.display_name}': " # Summarize array values values_summary = np.array2string( @@ -589,9 +613,7 @@ def _apply_operation( else: return NotImplemented - descriptor_array = DescriptorArray.from_scipp(name=self.name, full_value=new_full_value) - descriptor_array.name = descriptor_array.unique_name - return descriptor_array + return DescriptorArray.from_scipp(full_value=new_full_value) def _rapply_operation( self, @@ -885,9 +907,7 @@ def __pow__(self, other: Union[DescriptorNumber, numbers.Number]) -> DescriptorA raise message from None if np.any(np.isnan(new_value.values)): raise ValueError('The result of the exponentiation is not a number') - descriptor_number = DescriptorArray.from_scipp(name=self.name, full_value=new_value) - descriptor_number.name = descriptor_number.unique_name - return descriptor_number + return DescriptorArray.from_scipp(full_value=new_value) def __rpow__(self, other: numbers.Number): """ @@ -901,9 +921,7 @@ def __rpow__(self, other: numbers.Number): def __neg__(self) -> DescriptorArray: """Negate all values in the DescriptorArray.""" new_value = -self.full_value - descriptor_array = DescriptorArray.from_scipp(name=self.name, full_value=new_value) - descriptor_array.name = descriptor_array.unique_name - return descriptor_array + return DescriptorArray.from_scipp(full_value=new_value) def __abs__(self) -> DescriptorArray: """ @@ -914,9 +932,7 @@ def __abs__(self) -> DescriptorArray: DescriptorArray. """ new_value = abs(self.full_value) - descriptor_array = DescriptorArray.from_scipp(name=self.name, full_value=new_value) - descriptor_array.name = descriptor_array.unique_name - return descriptor_array + return DescriptorArray.from_scipp(full_value=new_value) def __getitem__(self, a) -> DescriptorArray: """ @@ -924,11 +940,7 @@ def __getitem__(self, a) -> DescriptorArray: Defer slicing to scipp. """ - descriptor = DescriptorArray.from_scipp( - name=self.name, full_value=self.full_value.__getitem__(a) - ) - descriptor.name = descriptor.unique_name - return descriptor + return DescriptorArray.from_scipp(full_value=self.full_value.__getitem__(a)) def __delitem__(self, a): """ @@ -1025,9 +1037,7 @@ def trace( ) constructor = DescriptorArray.from_scipp - descriptor = constructor(name=self.name, full_value=trace) - descriptor.name = descriptor.unique_name - return descriptor + return constructor(full_value=trace) def sum( self, dim: Optional[Union[str, list]] = None @@ -1055,9 +1065,7 @@ def sum( else: constructor = DescriptorArray.from_scipp - descriptor = constructor(name=self.name, full_value=new_full_value) - descriptor.name = descriptor.unique_name - return descriptor + return constructor(full_value=new_full_value) # This is to be implemented at a later time # def __matmul__(self, other: [DescriptorArray, list]) -> DescriptorArray: diff --git a/src/easyscience/variable/descriptor_base.py b/src/easyscience/variable/descriptor_base.py index e2214d3a..1eb4f3e3 100644 --- a/src/easyscience/variable/descriptor_base.py +++ b/src/easyscience/variable/descriptor_base.py @@ -4,10 +4,12 @@ from __future__ import annotations import abc +from inspect import signature from typing import Any from typing import Dict from typing import List from typing import Optional +from typing import Set from easyscience import global_object from easyscience.base_classes.new_base import NewBase @@ -19,10 +21,10 @@ class DescriptorBase(NewBase, metaclass=abc.ABCMeta): This is the base of all variable descriptions for models. It contains all information to describe a single unique property of - an object. This description includes a name and value as well as - optionally a unit, description and url (for reference material). - Also implemented is a callback so that the value can be read/set - from a linked library object. + an object. This description includes a value as well as optionally a + unit, description and url (for reference material). Also implemented + is a callback so that the value can be read/set from a linked + library object. A ``Descriptor`` is typically something which describes part of a model and is non-fittable and generally changes the state of an @@ -35,7 +37,7 @@ class DescriptorBase(NewBase, metaclass=abc.ABCMeta): def __init__( self, - name: str, + *, unique_name: Optional[str] = None, description: Optional[str] = None, url: Optional[str] = None, @@ -45,17 +47,17 @@ def __init__( This is the base of variables for models. It contains all information to describe a single unique property - of an object. This description includes a name, description and - url (for reference material). + of an object. This description includes a description and url + (for reference material). A ``Descriptor`` is typically something which describes part of a model and is non-fittable and generally changes the state of an object. + All arguments are keyword-only. + Parameters ---------- - name : str - Name of this object. unique_name : Optional[str], default=None Unique identifier for this object. By default, None. description : Optional[str], default=None @@ -63,22 +65,17 @@ def __init__( url : Optional[str], default=None Lookup url for documentation/information. By default, None. display_name : Optional[str], default=None - A pretty name for the object. By default, None. + A pretty name for the object. Falls back to ``unique_name`` + when not given. By default, None. Raises ------ TypeError - If ``name`` is not a string or if any optional string field - has an invalid type. + If any optional string field has an invalid type. """ - if not isinstance(name, str): - raise TypeError('Name must be a string') - 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') if description is None: @@ -92,74 +89,17 @@ def __init__( self._url: str = url @property - def name(self) -> str: - """ - Get the name of the object. - - Returns - ------- - str - Name of the object. - """ - return self._name - - @name.setter - @property_stack - def name(self, new_name: str) -> None: - """ - Set the name. - - Parameters - ---------- - new_name : str - Name of the object. - - Raises - ------ - TypeError - If ``new_name`` is not a string. + def _arg_spec(self) -> Set[str]: """ - if not isinstance(new_name, str): - raise TypeError('Name must be a string') - self._name = new_name - - @property - 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 - The pretty display name. - """ - display_name = self._display_name - if display_name is None: - display_name = self._name - return display_name - - @display_name.setter - @property_stack - def display_name(self, name: Optional[str]) -> None: - """ - Set the pretty display name. - - Parameters - ---------- - name : Optional[str] - Pretty display name of the object. - - Raises - ------ - TypeError - If ``name`` is neither a string nor ``None``. + Names of the constructor arguments the serializer has to collect. """ - if name is not None and not isinstance(name, str): - raise TypeError('Display name must be a string or None') - self._display_name = name + sign = signature(self.__class__.__init__) + return { + param.name + for param in sign.parameters.values() + if param.kind in (param.POSITIONAL_OR_KEYWORD, param.KEYWORD_ONLY) + and param.name != 'self' + } @property def description(self) -> str: diff --git a/src/easyscience/variable/descriptor_bool.py b/src/easyscience/variable/descriptor_bool.py index 874509fc..013b0d29 100644 --- a/src/easyscience/variable/descriptor_bool.py +++ b/src/easyscience/variable/descriptor_bool.py @@ -15,24 +15,45 @@ class DescriptorBool(DescriptorBase): def __init__( self, - name: str, value: bool, + *, unique_name: Optional[str] = None, description: Optional[str] = None, url: Optional[str] = None, display_name: Optional[str] = None, ): + """ + Constructor for the DescriptorBool class. + + All arguments after ``value`` are keyword-only. + + Parameters + ---------- + value : bool + Value of this object. + unique_name : Optional[str], default=None + Unique identifier for this object. By default, None. + description : Optional[str], default=None + A brief summary of what this object is. By default, None. + url : Optional[str], default=None + Lookup url for documentation/information. By default, None. + display_name : Optional[str], default=None + A pretty name for the object. Falls back to ``unique_name`` + when not given. By default, None. + + Raises + ------ + ValueError + If ``value`` is not a boolean. + """ if not isinstance(value, bool): raise ValueError(f'{value=} must be type bool') super().__init__( - name=name, unique_name=unique_name, description=description, url=url, display_name=display_name, ) - if not isinstance(value, bool): - raise TypeError(f'{value=} must be type bool') self._bool_value = value @property @@ -75,7 +96,7 @@ def value(self, value: bool) -> None: def __repr__(self) -> str: """Return printable representation.""" class_name = self.__class__.__name__ - obj_name = self._name + obj_name = self.display_name obj_value = self._bool_value return f"<{class_name} '{obj_name}': {obj_value}>" diff --git a/src/easyscience/variable/descriptor_number.py b/src/easyscience/variable/descriptor_number.py index c2a97262..dc8ebc1b 100644 --- a/src/easyscience/variable/descriptor_number.py +++ b/src/easyscience/variable/descriptor_number.py @@ -57,8 +57,8 @@ class DescriptorNumber(DescriptorBase): def __init__( self, - name: str, value: numbers.Number, + *, unit: Optional[Union[str, sc.Unit]] = '', variance: Optional[numbers.Number] = None, unique_name: Optional[str] = None, @@ -70,19 +70,51 @@ def __init__( """ Constructor for the DescriptorNumber class. - param name: Name of the descriptor param value: Value of the - descriptor param unit: Unit of the descriptor param variance: - Variance of the descriptor param description: Description of the - descriptor param url: URL of the descriptor param display_name: - Display name of the descriptor .. note:: Undo/Redo functionality - is implemented for the attributes ``variance``, ``error``, - ``unit`` and ``value``. + All arguments after ``value`` are keyword-only. + + Parameters + ---------- + value : numbers.Number + Value of this object. + unit : Optional[Union[str, sc.Unit]], default='' + This object can have a physical unit associated with it. By + default, ''. + variance : Optional[numbers.Number], default=None + The variance of the value. By default, None. + unique_name : Optional[str], default=None + Unique identifier for this object. By default, None. + description : Optional[str], default=None + A brief summary of what this object is. By default, None. + url : Optional[str], default=None + Lookup url for documentation/information. By default, None. + display_name : Optional[str], default=None + A pretty name for the object. Falls back to ``unique_name`` + when not given. By default, None. + **kwargs : Any + Additional keyword arguments used during (de)serialization. + + Raises + ------ + TypeError + If ``value`` or ``variance`` is not a number, if ``unit`` is + not a string or scipp unit, or if an unexpected keyword + argument is given. + UnitError + If ``unit`` is not a valid scipp unit. + ValueError + If ``variance`` is negative. + """ self._observers: List[DescriptorNumber] = [] # Extract serializer_id if provided during deserialization if '__serializer_id' in kwargs: self.__serializer_id = kwargs.pop('__serializer_id') + if kwargs: + raise TypeError( + f'{self.__class__.__name__}.__init__() got unexpected keyword ' + f'argument(s): {", ".join(sorted(kwargs))}.' + ) if not isinstance(value, numbers.Number) or isinstance(value, bool): raise TypeError(f'{value=} must be a number') @@ -101,7 +133,6 @@ def __init__( except Exception as message: raise UnitError(message) super().__init__( - name=name, unique_name=unique_name, description=description, url=url, @@ -113,14 +144,12 @@ def __init__( self._convert_unit(self._base_unit()) @classmethod - def from_scipp(cls, name: str, full_value: Variable, **kwargs: Any) -> DescriptorNumber: + def from_scipp(cls, full_value: Variable, **kwargs: Any) -> DescriptorNumber: """ Create a DescriptorNumber from a scipp constant. Parameters ---------- - name : str - Name of the descriptor. full_value : Variable Value of the descriptor as a scipp scalar. **kwargs : Any @@ -141,7 +170,6 @@ def from_scipp(cls, name: str, full_value: Variable, **kwargs: Any) -> Descripto if len(full_value.dims) != 0: raise TypeError(f'{full_value=} must be a scipp scalar') return cls( - name=name, value=full_value.value, unit=full_value.unit, variance=full_value.variance, @@ -420,7 +448,7 @@ def __repr__(self) -> str: """Return printable representation.""" string = '<' string += self.__class__.__name__ + ' ' - string += f"'{self._name}': " + string += f"'{self.display_name}': " if np.abs(self._scalar.value) > 1e4 or ( np.abs(self._scalar.value) < 1e-4 and self._scalar.value != 0 ): @@ -468,9 +496,7 @@ def __add__(self, other: Union[DescriptorNumber, numbers.Number]) -> DescriptorN other._convert_unit(original_unit) else: return NotImplemented - descriptor_number = DescriptorNumber.from_scipp(name=self.name, full_value=new_value) - descriptor_number.name = descriptor_number.unique_name - return descriptor_number + return DescriptorNumber.from_scipp(full_value=new_value) def __radd__(self, other: numbers.Number) -> DescriptorNumber: if isinstance(other, numbers.Number): @@ -479,9 +505,7 @@ def __radd__(self, other: numbers.Number) -> DescriptorNumber: new_value = other + self.full_value else: return NotImplemented - descriptor_number = DescriptorNumber.from_scipp(name=self.name, full_value=new_value) - descriptor_number.name = descriptor_number.unique_name - return descriptor_number + return DescriptorNumber.from_scipp(full_value=new_value) def __sub__(self, other: Union[DescriptorNumber, numbers.Number]) -> DescriptorNumber: if isinstance(other, numbers.Number): @@ -500,9 +524,7 @@ def __sub__(self, other: Union[DescriptorNumber, numbers.Number]) -> DescriptorN other._convert_unit(original_unit) else: return NotImplemented - descriptor_number = DescriptorNumber.from_scipp(name=self.name, full_value=new_value) - descriptor_number.name = descriptor_number.unique_name - return descriptor_number + return DescriptorNumber.from_scipp(full_value=new_value) def __rsub__(self, other: numbers.Number) -> DescriptorNumber: if isinstance(other, numbers.Number): @@ -511,9 +533,7 @@ def __rsub__(self, other: numbers.Number) -> DescriptorNumber: new_value = other - self.full_value else: return NotImplemented - descriptor = DescriptorNumber.from_scipp(name=self.name, full_value=new_value) - descriptor.name = descriptor.unique_name - return descriptor + return DescriptorNumber.from_scipp(full_value=new_value) def __mul__(self, other: Union[DescriptorNumber, numbers.Number]) -> DescriptorNumber: if isinstance(other, numbers.Number): @@ -522,9 +542,8 @@ def __mul__(self, other: Union[DescriptorNumber, numbers.Number]) -> DescriptorN new_value = self.full_value * other.full_value else: return NotImplemented - descriptor_number = DescriptorNumber.from_scipp(name=self.name, full_value=new_value) + descriptor_number = DescriptorNumber.from_scipp(full_value=new_value) descriptor_number._convert_unit(descriptor_number._base_unit()) - descriptor_number.name = descriptor_number.unique_name return descriptor_number def __rmul__(self, other: numbers.Number) -> DescriptorNumber: @@ -532,9 +551,7 @@ def __rmul__(self, other: numbers.Number) -> DescriptorNumber: new_value = other * self.full_value else: return NotImplemented - descriptor_number = DescriptorNumber.from_scipp(name=self.name, full_value=new_value) - descriptor_number.name = descriptor_number.unique_name - return descriptor_number + return DescriptorNumber.from_scipp(full_value=new_value) def __truediv__(self, other: Union[DescriptorNumber, numbers.Number]) -> DescriptorNumber: if isinstance(other, numbers.Number): @@ -547,9 +564,8 @@ def __truediv__(self, other: Union[DescriptorNumber, numbers.Number]) -> Descrip new_value = self.full_value / other.full_value else: return NotImplemented - descriptor_number = DescriptorNumber.from_scipp(name=self.name, full_value=new_value) + descriptor_number = DescriptorNumber.from_scipp(full_value=new_value) descriptor_number._convert_unit(descriptor_number._base_unit()) - descriptor_number.name = descriptor_number.unique_name return descriptor_number def __rtruediv__(self, other: numbers.Number) -> DescriptorNumber: @@ -559,9 +575,7 @@ def __rtruediv__(self, other: numbers.Number) -> DescriptorNumber: new_value = other / self.full_value else: return NotImplemented - descriptor_number = DescriptorNumber.from_scipp(name=self.name, full_value=new_value) - descriptor_number.name = descriptor_number.unique_name - return descriptor_number + return DescriptorNumber.from_scipp(full_value=new_value) def __pow__(self, other: Union[DescriptorNumber, numbers.Number]) -> DescriptorNumber: if isinstance(other, numbers.Number): @@ -580,9 +594,7 @@ def __pow__(self, other: Union[DescriptorNumber, numbers.Number]) -> DescriptorN raise message from None if np.isnan(new_value.value): raise ValueError('The result of the exponentiation is not a number') - descriptor_number = DescriptorNumber.from_scipp(name=self.name, full_value=new_value) - descriptor_number.name = descriptor_number.unique_name - return descriptor_number + return DescriptorNumber.from_scipp(full_value=new_value) def __rpow__(self, other: numbers.Number) -> numbers.Number: if isinstance(other, numbers.Number): @@ -597,15 +609,11 @@ def __rpow__(self, other: numbers.Number) -> numbers.Number: def __neg__(self) -> DescriptorNumber: new_value = -self.full_value - descriptor_number = DescriptorNumber.from_scipp(name=self.name, full_value=new_value) - descriptor_number.name = descriptor_number.unique_name - return descriptor_number + return DescriptorNumber.from_scipp(full_value=new_value) def __abs__(self) -> DescriptorNumber: new_value = abs(self.full_value) - descriptor_number = DescriptorNumber.from_scipp(name=self.name, full_value=new_value) - descriptor_number.name = descriptor_number.unique_name - return descriptor_number + return DescriptorNumber.from_scipp(full_value=new_value) def _base_unit(self) -> str: """ diff --git a/src/easyscience/variable/descriptor_str.py b/src/easyscience/variable/descriptor_str.py index e4b28823..63fbaa3e 100644 --- a/src/easyscience/variable/descriptor_str.py +++ b/src/easyscience/variable/descriptor_str.py @@ -15,15 +15,38 @@ class DescriptorStr(DescriptorBase): def __init__( self, - name: str, value: str, + *, unique_name: Optional[str] = None, description: Optional[str] = None, url: Optional[str] = None, display_name: Optional[str] = None, ): + """ + Constructor for the DescriptorStr class. + + All arguments after ``value`` are keyword-only. + + Parameters + ---------- + value : str + Value of this object. + unique_name : Optional[str], default=None + Unique identifier for this object. By default, None. + description : Optional[str], default=None + A brief summary of what this object is. By default, None. + url : Optional[str], default=None + Lookup url for documentation/information. By default, None. + display_name : Optional[str], default=None + A pretty name for the object. Falls back to ``unique_name`` + when not given. By default, None. + + Raises + ------ + ValueError + If ``value`` is not a string. + """ super().__init__( - name=name, unique_name=unique_name, description=description, url=url, @@ -73,7 +96,7 @@ def value(self, value: str) -> None: def __repr__(self) -> str: """Return printable representation.""" class_name = self.__class__.__name__ - obj_name = self._name + obj_name = self.display_name obj_value = self._string return f"<{class_name} '{obj_name}': {obj_value}>" diff --git a/src/easyscience/variable/parameter.py b/src/easyscience/variable/parameter.py index 35654ed5..8dda0f7d 100644 --- a/src/easyscience/variable/parameter.py +++ b/src/easyscience/variable/parameter.py @@ -40,8 +40,8 @@ class Parameter(DescriptorNumber): def __init__( self, - name: str, value: numbers.Number, + *, unit: Optional[Union[str, sc.Unit]] = '', variance: Optional[numbers.Number] = 0.0, min: Optional[numbers.Number] = -np.inf, @@ -61,10 +61,10 @@ def __init__( for dynamic objects. A parameter has the ability to be used in fitting and has additional fields to facilitate this. + All arguments after ``value`` are keyword-only. + Parameters ---------- - name : str - Name of this object. value : numbers.Number Value of this object. unit : Optional[Union[str, sc.Unit]], default='' @@ -86,8 +86,8 @@ def __init__( url : Optional[str], default=None Lookup url for documentation/information. By default, None. display_name : Optional[str], default=None - The name of the object as it should be displayed. By - default, None. + The name of the object as it should be displayed. Falls back + to ``unique_name`` when not given. By default, None. callback : property, default=property() Callback used to synchronize the parameter with an external model. @@ -102,11 +102,6 @@ def __init__( If ``value`` falls outside the provided bounds or if the bounds are invalid. - Notes - ----- - Undo/Redo functionality is implemented for the attributes - ``value``, ``variance``, ``error``, ``min``, ``max``, - ``bounds``, ``fixed``, ``unit`` """ # Extract and ignore serialization-specific fields from kwargs kwargs.pop('_dependency_string', None) @@ -135,7 +130,6 @@ def __init__( self._max = sc.scalar(float(max), unit=unit) super().__init__( - name=name, value=value, unit=unit, variance=variance, @@ -156,7 +150,6 @@ def __init__( @classmethod def from_dependency( cls, - name: str, dependency_expression: str, dependency_map: Optional[dict] = None, desired_unit: str | sc.Unit | None = None, @@ -168,8 +161,6 @@ def from_dependency( Parameters ---------- - name : str - The name of the parameter. dependency_expression : str The dependency expression to evaluate. This should be a string which can be evaluated by the ASTEval interpreter. @@ -193,7 +184,7 @@ def from_dependency( default_kwargs = {'value': 0.0, 'variance': 0.0, 'min': -np.inf, 'max': np.inf} # Update with user-provided kwargs, to avoid errors. default_kwargs.update(kwargs) - parameter = cls(name=name, **default_kwargs) + parameter = cls(**default_kwargs) parameter.make_dependent_on( dependency_expression=dependency_expression, dependency_map=dependency_map, @@ -1061,11 +1052,7 @@ def __add__(self, other: Union[DescriptorNumber, Parameter, numbers.Number]) -> other._convert_unit(other_unit) else: return NotImplemented - parameter = Parameter.from_scipp( - name=self.name, full_value=new_full_value, min=min_value, max=max_value - ) - parameter.name = parameter.unique_name - return parameter + return Parameter.from_scipp(full_value=new_full_value, min=min_value, max=max_value) def __radd__(self, other: Union[DescriptorNumber, numbers.Number]) -> Parameter: if isinstance(other, numbers.Number): @@ -1090,11 +1077,7 @@ def __radd__(self, other: Union[DescriptorNumber, numbers.Number]) -> Parameter: self._convert_unit(original_unit) else: return NotImplemented - parameter = Parameter.from_scipp( - name=self.name, full_value=new_full_value, min=min_value, max=max_value - ) - parameter.name = parameter.unique_name - return parameter + return Parameter.from_scipp(full_value=new_full_value, min=min_value, max=max_value) def __sub__(self, other: Union[DescriptorNumber, Parameter, numbers.Number]) -> Parameter: if isinstance(other, numbers.Number): @@ -1123,11 +1106,7 @@ def __sub__(self, other: Union[DescriptorNumber, Parameter, numbers.Number]) -> other._convert_unit(other_unit) else: return NotImplemented - parameter = Parameter.from_scipp( - name=self.name, full_value=new_full_value, min=min_value, max=max_value - ) - parameter.name = parameter.unique_name - return parameter + return Parameter.from_scipp(full_value=new_full_value, min=min_value, max=max_value) def __rsub__(self, other: Union[DescriptorNumber, numbers.Number]) -> Parameter: if isinstance(other, numbers.Number): @@ -1152,21 +1131,13 @@ def __rsub__(self, other: Union[DescriptorNumber, numbers.Number]) -> Parameter: self._convert_unit(original_unit) else: return NotImplemented - parameter = Parameter.from_scipp( - name=self.name, full_value=new_full_value, min=min_value, max=max_value - ) - parameter.name = parameter.unique_name - return parameter + return Parameter.from_scipp(full_value=new_full_value, min=min_value, max=max_value) def __mul__(self, other: Union[DescriptorNumber, Parameter, numbers.Number]) -> Parameter: if isinstance(other, numbers.Number): new_full_value = self.full_value * other if other == 0: - descriptor_number = DescriptorNumber.from_scipp( - name=self.name, full_value=new_full_value - ) - descriptor_number.name = descriptor_number.unique_name - return descriptor_number + return DescriptorNumber.from_scipp(full_value=new_full_value) combinations = [self.min * other, self.max * other] elif isinstance( other, DescriptorNumber @@ -1175,11 +1146,7 @@ def __mul__(self, other: Union[DescriptorNumber, Parameter, numbers.Number]) -> if ( other.value == 0 and type(other) is DescriptorNumber ): # Only return DescriptorNumber if other is strictly 0, i.e. not a parameter # noqa: E501 - descriptor_number = DescriptorNumber.from_scipp( - name=self.name, full_value=new_full_value - ) - descriptor_number.name = descriptor_number.unique_name - return descriptor_number + return DescriptorNumber.from_scipp(full_value=new_full_value) if isinstance(other, Parameter): combinations = [] for first, second in [ @@ -1200,43 +1167,29 @@ def __mul__(self, other: Union[DescriptorNumber, Parameter, numbers.Number]) -> return NotImplemented min_value = min(combinations) max_value = max(combinations) - parameter = Parameter.from_scipp( - name=self.name, full_value=new_full_value, min=min_value, max=max_value - ) + parameter = Parameter.from_scipp(full_value=new_full_value, min=min_value, max=max_value) parameter._convert_unit(parameter._base_unit()) - parameter.name = parameter.unique_name return parameter def __rmul__(self, other: Union[DescriptorNumber, numbers.Number]) -> Parameter: if isinstance(other, numbers.Number): new_full_value = other * self.full_value if other == 0: - descriptor_number = DescriptorNumber.from_scipp( - name=self.name, full_value=new_full_value - ) - descriptor_number.name = descriptor_number.unique_name - return descriptor_number + return DescriptorNumber.from_scipp(full_value=new_full_value) combinations = [other * self.min, other * self.max] elif isinstance( other, DescriptorNumber ): # Parameter inherits from DescriptorNumber and is also handled here new_full_value = other.full_value * self.full_value if other.value == 0: - descriptor_number = DescriptorNumber.from_scipp( - name=self.name, full_value=new_full_value - ) - descriptor_number.name = descriptor_number.unique_name - return descriptor_number + return DescriptorNumber.from_scipp(full_value=new_full_value) combinations = [self.min * other.value, self.max * other.value] else: return NotImplemented min_value = min(combinations) max_value = max(combinations) - parameter = Parameter.from_scipp( - name=self.name, full_value=new_full_value, min=min_value, max=max_value - ) + parameter = Parameter.from_scipp(full_value=new_full_value, min=min_value, max=max_value) parameter._convert_unit(parameter._base_unit()) - parameter.name = parameter.unique_name return parameter def __truediv__(self, other: Union[DescriptorNumber, Parameter, numbers.Number]) -> Parameter: @@ -1282,11 +1235,8 @@ def __truediv__(self, other: Union[DescriptorNumber, Parameter, numbers.Number]) return NotImplemented min_value = min(combinations) max_value = max(combinations) - parameter = Parameter.from_scipp( - name=self.name, full_value=new_full_value, min=min_value, max=max_value - ) + parameter = Parameter.from_scipp(full_value=new_full_value, min=min_value, max=max_value) parameter._convert_unit(parameter._base_unit()) - parameter.name = parameter.unique_name return parameter def __rtruediv__(self, other: Union[DescriptorNumber, numbers.Number]) -> Parameter: @@ -1297,22 +1247,14 @@ def __rtruediv__(self, other: Union[DescriptorNumber, numbers.Number]) -> Parame new_full_value = other / self.full_value other_value = other if other_value == 0: - descriptor_number = DescriptorNumber.from_scipp( - name=self.name, full_value=new_full_value - ) - descriptor_number.name = descriptor_number.unique_name - return descriptor_number + return DescriptorNumber.from_scipp(full_value=new_full_value) elif isinstance( other, DescriptorNumber ): # Parameter inherits from DescriptorNumber and is also handled here new_full_value = other.full_value / self.full_value other_value = other.value if other_value == 0: - descriptor_number = DescriptorNumber.from_scipp( - name=self.name, full_value=new_full_value - ) - descriptor_number.name = descriptor_number.unique_name - return descriptor_number + return DescriptorNumber.from_scipp(full_value=new_full_value) else: return NotImplemented if self.min < 0 and self.max > 0: @@ -1331,11 +1273,8 @@ def __rtruediv__(self, other: Union[DescriptorNumber, numbers.Number]) -> Parame combinations = [other_value / self.min, other_value / self.max] min_value = min(combinations) max_value = max(combinations) - parameter = Parameter.from_scipp( - name=self.name, full_value=new_full_value, min=min_value, max=max_value - ) + parameter = Parameter.from_scipp(full_value=new_full_value, min=min_value, max=max_value) parameter._convert_unit(parameter._base_unit()) - parameter.name = parameter.unique_name return parameter def __pow__(self, other: Union[DescriptorNumber, numbers.Number]) -> Parameter: @@ -1360,11 +1299,7 @@ def __pow__(self, other: Union[DescriptorNumber, numbers.Number]) -> Parameter: if np.isnan(new_full_value.value): raise ValueError('The result of the exponentiation is not a number') if exponent == 0: - descriptor_number = DescriptorNumber.from_scipp( - name=self.name, full_value=new_full_value - ) - descriptor_number.name = descriptor_number.unique_name - return descriptor_number + return DescriptorNumber.from_scipp(full_value=new_full_value) elif exponent < 0: if self.min < 0 and self.max > 0: combinations = [-np.inf, np.inf] @@ -1386,21 +1321,13 @@ def __pow__(self, other: Union[DescriptorNumber, numbers.Number]) -> Parameter: combinations = [combination for combination in combinations if combination >= 0] min_value = min(combinations) max_value = max(combinations) - parameter = Parameter.from_scipp( - name=self.name, full_value=new_full_value, min=min_value, max=max_value - ) - parameter.name = parameter.unique_name - return parameter + return Parameter.from_scipp(full_value=new_full_value, min=min_value, max=max_value) def __neg__(self) -> Parameter: new_full_value = -self.full_value min_value = -self.max max_value = -self.min - parameter = Parameter.from_scipp( - name=self.name, full_value=new_full_value, min=min_value, max=max_value - ) - parameter.name = parameter.unique_name - return parameter + return Parameter.from_scipp(full_value=new_full_value, min=min_value, max=max_value) def __abs__(self) -> Parameter: new_full_value = abs(self.full_value) @@ -1409,11 +1336,7 @@ def __abs__(self) -> Parameter: combinations.append(0.0) min_value = min(combinations) max_value = max(combinations) - parameter = Parameter.from_scipp( - name=self.name, full_value=new_full_value, min=min_value, max=max_value - ) - parameter.name = parameter.unique_name - return parameter + return Parameter.from_scipp(full_value=new_full_value, min=min_value, max=max_value) def resolve_pending_dependencies(self) -> None: """ diff --git a/src/easyscience/variable/parameter_dependency_resolver.py b/src/easyscience/variable/parameter_dependency_resolver.py index d231dcd2..fd91411b 100644 --- a/src/easyscience/variable/parameter_dependency_resolver.py +++ b/src/easyscience/variable/parameter_dependency_resolver.py @@ -82,8 +82,8 @@ def _collect_parameters(item: Any, parameters: List[Parameter]) -> None: error_count += 1 serializer_id = getattr(param, '_DescriptorNumber__serializer_id', 'unknown') errors.append( - f"Failed to resolve dependencies for parameter '{param.name}'" - f" (unique_name: '{param.unique_name}', serializer_id: '{serializer_id}'): {e}" + f"Failed to resolve dependencies for parameter '{param.unique_name}'" + f" (display_name: '{param.display_name}', serializer_id: '{serializer_id}'): {e}" ) # Report results diff --git a/tests/functional/test_smoke.py b/tests/functional/test_smoke.py index 23323fc9..a355e548 100644 --- a/tests/functional/test_smoke.py +++ b/tests/functional/test_smoke.py @@ -16,5 +16,5 @@ def test_polynomial_smoke() -> None: model = Polynomial(name='smoke', coefficients=[1.0, 2.0, 3.0]) x = np.array([0.0, 1.0, 2.0]) - assert [coefficient.name for coefficient in model.coefficients] == ['c0', 'c1', 'c2'] + assert [coefficient.display_name for coefficient in model.coefficients] == ['c0', 'c1', 'c2'] assert np.allclose(model(x), np.polyval([1.0, 2.0, 3.0], x)) diff --git a/tests/integration/fitting/test_fitter.py b/tests/integration/fitting/test_fitter.py index 1b4be9c4..c3b1c924 100644 --- a/tests/integration/fitting/test_fitter.py +++ b/tests/integration/fitting/test_fitter.py @@ -18,8 +18,8 @@ class AbsSin(ObjBase): offset: Parameter def __init__(self, offset_val: float, phase_val: float): - offset = Parameter('offset', offset_val) - phase = Parameter('phase', phase_val) + offset = Parameter(offset_val, display_name='offset') + phase = Parameter(phase_val, display_name='phase') super().__init__('sin', offset=offset, phase=phase) def __call__(self, x): @@ -31,8 +31,8 @@ class AbsSin2D(ObjBase): offset: Parameter def __init__(self, offset_val: float, phase_val: float): - offset = Parameter('offset', offset_val) - phase = Parameter('phase', phase_val) + offset = Parameter(offset_val, display_name='offset') + phase = Parameter(phase_val, display_name='phase') super().__init__('sin2D', offset=offset, phase=phase) def __call__(self, x): @@ -55,8 +55,8 @@ def __call__(self, x): class StraightLine(ModelBase): def __init__(self, slope: float, intercept: float): super().__init__() - self._slope = Parameter('slope', slope) - self._intercept = Parameter('intercept', intercept) + self._slope = Parameter(slope, display_name='slope') + self._intercept = Parameter(intercept, display_name='intercept') @property def slope(self) -> Parameter: diff --git a/tests/integration/fitting/test_multi_fitter.py b/tests/integration/fitting/test_multi_fitter.py index 99dc60b4..927eff0b 100644 --- a/tests/integration/fitting/test_multi_fitter.py +++ b/tests/integration/fitting/test_multi_fitter.py @@ -13,8 +13,8 @@ class Line(ModelBase): def __init__(self, m_val: float, c_val: float): super().__init__() - self._m = Parameter('m', m_val) - self._c = Parameter('c', c_val) + self._m = Parameter(m_val, display_name='m') + self._c = Parameter(c_val, display_name='c') @property def m(self) -> Parameter: @@ -39,8 +39,8 @@ def __call__(self, x): class AbsSin(ModelBase): def __init__(self, offset_val: float, phase_val: float): super().__init__() - self._offset = Parameter('offset', offset_val) - self._phase = Parameter('phase', phase_val) + self._offset = Parameter(offset_val, display_name='offset') + self._phase = Parameter(phase_val, display_name='phase') @property def offset(self) -> Parameter: diff --git a/tests/integration/fitting/test_sampler.py b/tests/integration/fitting/test_sampler.py index 2e428907..1411243e 100644 --- a/tests/integration/fitting/test_sampler.py +++ b/tests/integration/fitting/test_sampler.py @@ -23,8 +23,8 @@ class Line(ModelBase): def __init__(self, m_val: float, c_val: float): super().__init__() - self._m = Parameter('m', m_val) - self._c = Parameter('c', c_val) + self._m = Parameter(m_val, display_name='m') + self._c = Parameter(c_val, display_name='c') @property def m(self) -> Parameter: @@ -49,8 +49,8 @@ def __call__(self, x): class AbsSin(ModelBase): def __init__(self, offset_val: float, phase_val: float): super().__init__() - self._offset = Parameter('offset', offset_val) - self._phase = Parameter('phase', phase_val) + self._offset = Parameter(offset_val, display_name='offset') + self._phase = Parameter(phase_val, display_name='phase') @property def offset(self) -> Parameter: diff --git a/tests/unit/base_classes/test_collection_base.py b/tests/unit/base_classes/test_collection_base.py index 8886a474..8db6c220 100644 --- a/tests/unit/base_classes/test_collection_base.py +++ b/tests/unit/base_classes/test_collection_base.py @@ -20,7 +20,6 @@ '@module': DescriptorNumber.__module__, '@class': DescriptorNumber.__name__, '@version': easyscience.__version__, - 'name': 'par1', 'value': 1.0, 'unit': 'dimensionless', 'variance': None, @@ -44,11 +43,11 @@ class Alpha(CollectionBase): def setup_pars(): d = { 'name': 'test', - 'par1': Parameter('p1', 0.1, fixed=True), - 'des1': DescriptorNumber('d1', 0.1), - 'par2': Parameter('p2', 0.1), - 'des2': DescriptorNumber('d2', 0.1), - 'par3': Parameter('p3', 0.1), + 'par1': Parameter(0.1, fixed=True, display_name='p1'), + 'des1': DescriptorNumber(0.1, display_name='d1'), + 'par2': Parameter(0.1, display_name='p2'), + 'des2': DescriptorNumber(0.1, display_name='d2'), + 'par3': Parameter(0.1, display_name='p3'), } return d @@ -64,7 +63,7 @@ def test_CollectionBase_from_base(cls, setup_pars): assert coll.user_data == {} for item, key in zip(coll, setup_pars.keys()): - assert item.name == setup_pars[key].name + assert item.display_name == setup_pars[key].display_name assert item.value == setup_pars[key].value @@ -87,6 +86,7 @@ def test_CollectionBase_from_ObjBase(cls, setup_pars: dict, value: int): idx = 0 for item, key in zip(coll, objs.keys()): + # Members here are legacy ObjBase instances, which still carry `name`. assert item.name == prefix + str(idx) assert isinstance(item, objs[key].__class__) idx += 1 @@ -108,7 +108,7 @@ def test_CollectionBase_create_fail(cls, setup_pars, value): def test_CollectionBase_create_fail2(cls, setup_pars, key): name = setup_pars['name'] del setup_pars['name'] - setup_pars[key] = DescriptorNumber('fail_name', 0) + setup_pars[key] = DescriptorNumber(0, display_name='fail_name') with pytest.raises(AttributeError): coll = cls(name, **setup_pars) @@ -121,14 +121,14 @@ def test_CollectionBase_append_base(cls, setup_pars): new_item_name = 'boo' new_item_value = 100 - new_item = Parameter(new_item_name, new_item_value) + new_item = Parameter(new_item_value, display_name=new_item_name) coll = cls(name, **setup_pars) n_before = len(coll) coll.append(new_item) assert len(coll) == n_before + 1 - assert coll[-1].name == new_item_name + assert coll[-1].display_name == new_item_name assert coll[-1].value == new_item_value @@ -156,7 +156,7 @@ def test_CollectionBase_getItem(cls, setup_pars, value): key = value else: key = list(setup_pars.keys())[value] - assert get_item.name == setup_pars[key].name + assert get_item.display_name == setup_pars[key].display_name @pytest.mark.parametrize('cls', class_constructors) @@ -190,14 +190,14 @@ def test_CollectionBase_setItem(cls, setup_pars, value): coll = cls(name, **setup_pars) n_coll = len(coll) - name_coll_idx = coll[value].name + name_coll_idx = coll[value].display_name new_item_value = 100 coll[value] = new_item_value assert len(coll) == n_coll - assert coll[value].name == name_coll_idx + assert coll[value].display_name == name_coll_idx assert coll[value].value == new_item_value @@ -223,14 +223,14 @@ def test_CollectionBase_delItem(cls, setup_pars, value): coll = cls(name, **setup_pars) n_coll = len(coll) # On del we should shift left - name_coll_idx = coll[value].name - name_coll_idxp = coll[value + 1].name + name_coll_idx = coll[value].display_name + name_coll_idxp = coll[value + 1].display_name del coll[value] assert len(coll) == n_coll - 1 - assert coll[value].name == name_coll_idxp - assert name_coll_idx not in [col.name for col in coll] + assert coll[value].display_name == name_coll_idxp + assert name_coll_idx not in [col.display_name for col in coll] @pytest.mark.parametrize('cls', class_constructors) @@ -293,7 +293,7 @@ def test_CollectionBase_get_fit_parameters_nested(cls, setup_pars): @pytest.mark.parametrize('cls', class_constructors) def test_CollectionBase_dir(cls): name = 'testing' - kwargs = {'p1': DescriptorNumber('par1', 1)} + kwargs = {'p1': DescriptorNumber(1, display_name='par1')} obj = cls(name, **kwargs) d = set(dir(obj)) @@ -329,7 +329,7 @@ def test_CollectionBase_dir(cls): @pytest.mark.parametrize('cls', class_constructors) def test_CollectionBase_to_dict(cls): name = 'testing' - kwargs = {'p1': DescriptorNumber('par1', 1)} + kwargs = {'p1': DescriptorNumber(1, display_name='par1')} obj = cls(name, **kwargs) d = obj.to_dict() @@ -374,21 +374,21 @@ def testit(item1, item2): def test_CollectionBase_from_dict(cls): global_object.map._clear() # TODO: figure out why this test fails without this line name = 'testing' - kwargs = {'p1': DescriptorNumber('par1', 1)} + kwargs = {'p1': DescriptorNumber(1, display_name='par1')} expected = cls.from_dict(test_dict) ref = cls(name, **kwargs) assert ref.name == expected.name assert len(ref) == len(expected) for item1, item2 in zip(ref, expected): - assert item1.name == item2.name + assert item1.display_name == item2.display_name assert item1.value == item2.value @pytest.mark.parametrize('cls', class_constructors) def test_CollectionBase_repr(cls): name = 'test' - p1 = Parameter('p1', 1) + p1 = Parameter(1, display_name='p1') obj = cls(name, p1) test_str = str(obj) ref_str = f'{cls.__name__} `{name}` of length 1' @@ -398,10 +398,10 @@ def test_CollectionBase_repr(cls): @pytest.mark.parametrize('cls', class_constructors) def test_CollectionBase_iterator(cls): name = 'test' - p1 = Parameter('p1', 1) - p2 = Parameter('p2', 2) - p3 = Parameter('p3', 3) - p4 = Parameter('p4', 4) + p1 = Parameter(1, display_name='p1') + p2 = Parameter(2, display_name='p2') + p3 = Parameter(3, display_name='p3') + p4 = Parameter(4, display_name='p4') l_object = [p1, p2, p3, p4] @@ -415,10 +415,10 @@ def test_CollectionBase_iterator(cls): def test_CollectionBase_iterator_dict(cls): global_object.map._clear() # TODO: figure out why this test fails without this line name = 'test' - p1 = Parameter('p1', 1) - p2 = Parameter('p2', 2) - p3 = Parameter('p3', 3) - p4 = Parameter('p4', 4) + p1 = Parameter(1, display_name='p1') + p2 = Parameter(2, display_name='p2') + p3 = Parameter(3, display_name='p3') + p4 = Parameter(4, display_name='p4') l_object = [p1, p2, p3, p4] @@ -431,14 +431,19 @@ def test_CollectionBase_iterator_dict(cls): assert item.value == l_object[index].value +@pytest.mark.xfail( + strict=True, + raises=AttributeError, + reason='legacy CollectionBase string indexing uses the removed descriptor `name` (#308/#292)', +) @pytest.mark.parametrize('cls', class_constructors) def test_CollectionBase_sameName(cls): global_object.map._clear() # TODO: figure out why this test fails without this line name = 'test' - p1 = Parameter('p1', 1) - p2 = Parameter('p1', 2) - p3 = Parameter('p3', 3) - p4 = Parameter('p4', 4) + p1 = Parameter(1, display_name='p1') + p2 = Parameter(2, display_name='p1') + p3 = Parameter(3, display_name='p3') + p4 = Parameter(4, display_name='p4') l_object = [p1, p2, p3, p4] obj = cls(name, *l_object) @@ -455,10 +460,10 @@ def test_CollectionBase_sameName(cls): @pytest.mark.parametrize('cls', class_constructors) def test_CollectionBase_set_index(cls): name = 'test' - p1 = Parameter('p1', 1) - p2 = Parameter('p1', 2) - p3 = Parameter('p3', 3) - p4 = Parameter('p4', 4) + p1 = Parameter(1, display_name='p1') + p2 = Parameter(2, display_name='p1') + p3 = Parameter(3, display_name='p3') + p4 = Parameter(4, display_name='p4') l_object = [p1, p2, p3] obj = cls(name, *l_object) @@ -477,11 +482,11 @@ def test_CollectionBase_set_index(cls): @pytest.mark.parametrize('cls', class_constructors) def test_CollectionBase_set_index_based(cls): name = 'test' - p1 = Parameter('p1', 1) - p2 = Parameter('p2', 2) - p3 = Parameter('p3', 3) - p4 = Parameter('p4', 4) - p5 = Parameter('p5', 5) + p1 = Parameter(1, display_name='p1') + p2 = Parameter(2, display_name='p2') + p3 = Parameter(3, display_name='p3') + p4 = Parameter(4, display_name='p4') + p5 = Parameter(5, display_name='p5') d = cls('testing', p1, p2) l_object = [p3, p4, p5] @@ -503,7 +508,7 @@ def test_CollectionBase_sort(cls): name = 'test' v = [1, 4, 3, 2, 5] expected = [1, 2, 3, 4, 5] - d = cls(name, *[Parameter(f'p{i}', v[i]) for i in range(len(v))]) + d = cls(name, *[Parameter(v[i], display_name=f'p{i}') for i in range(len(v))]) d.sort(lambda x: x.value) for i, item in enumerate(d): assert item.value == expected[i] @@ -515,7 +520,7 @@ def test_CollectionBase_sort_reverse(cls): v = [1, 4, 3, 2, 5] expected = [1, 2, 3, 4, 5] expected.reverse() - d = cls(name, *[Parameter(f'p{i}', v[i]) for i in range(len(v))]) + d = cls(name, *[Parameter(v[i], display_name=f'p{i}') for i in range(len(v))]) d.sort(lambda x: x.value, reverse=True) for i, item in enumerate(d): assert item.value == expected[i] @@ -532,7 +537,7 @@ def test_CollectionBaseGraph(cls): G = global_object.map name = 'test' v = [1, 2] - p = [Parameter(f'p{i}', v[i]) for i in range(len(v))] + p = [Parameter(v[i], display_name=f'p{i}') for i in range(len(v))] p_id = [_p.unique_name for _p in p] bb = cls(name, *p) bb_id = bb.unique_name diff --git a/tests/unit/base_classes/test_deprecated_wrappers.py b/tests/unit/base_classes/test_deprecated_wrappers.py index 492fc387..ea7cb6e3 100644 --- a/tests/unit/base_classes/test_deprecated_wrappers.py +++ b/tests/unit/base_classes/test_deprecated_wrappers.py @@ -50,10 +50,10 @@ def test_collection_base_still_works_from_deprecated(caplog: 'pytest.LogCaptureF from easyscience import Parameter - p = Parameter('p1', 1.0) + p = Parameter(1.0, display_name='p1') coll = CollectionBase('test', p) assert len(coll) == 1 - assert coll[0].name == 'p1' + assert coll[0].display_name == 'p1' # --------------------------------------------------------------------------- @@ -82,6 +82,6 @@ def test_obj_base_still_works_from_deprecated(caplog: 'pytest.LogCaptureFixture' from easyscience import Parameter - p = Parameter('p1', 1.0) + p = Parameter(1.0, display_name='p1') obj = ObjBase('test', p1=p) assert obj.p1.value == 1.0 diff --git a/tests/unit/base_classes/test_easy_list.py b/tests/unit/base_classes/test_easy_list.py index b1a2e3d2..8a593766 100644 --- a/tests/unit/base_classes/test_easy_list.py +++ b/tests/unit/base_classes/test_easy_list.py @@ -32,8 +32,8 @@ class MockModel(ModelBase): def __init__(self, unique_name=None, display_name=None, temperature=25, volume=1.0): super().__init__(unique_name=unique_name, display_name=display_name) - self._temperature = Parameter(name='temperature', value=temperature) - self._volume = DescriptorNumber(name='volume', value=volume) + self._temperature = Parameter(display_name='temperature', value=temperature) + self._volume = DescriptorNumber(display_name='volume', value=volume) @property def temperature(self): @@ -57,7 +57,7 @@ class MockModelNested(ModelBase): def __init__(self, unique_name=None, display_name=None, component=None, pressure=0): super().__init__(unique_name=unique_name, display_name=display_name) - self._pressure = Parameter(name='pressure', value=pressure) + self._pressure = Parameter(display_name='pressure', value=pressure) self._component = component or MockModel(unique_name='inner', temperature=30, volume=2.0) @property @@ -588,13 +588,13 @@ def test_get_all_variables_single_modelbase(self): el = EasyList(m1, protected_types=ModelBase) vars = el.get_all_variables() assert len(vars) == 2 - names = {v.name for v in vars} + names = {v.display_name for v in vars} assert 'temperature' in names assert 'volume' in names # Verify specific values - temp_var = next(v for v in vars if v.name == 'temperature') + temp_var = next(v for v in vars if v.display_name == 'temperature') assert temp_var.value == 10 - vol_var = next(v for v in vars if v.name == 'volume') + vol_var = next(v for v in vars if v.display_name == 'volume') assert vol_var.value == 5.0 def test_get_all_variables_multiple_modelbase(self): @@ -604,7 +604,7 @@ def test_get_all_variables_multiple_modelbase(self): el = EasyList(m1, m2, protected_types=ModelBase) vars = el.get_all_variables() assert len(vars) == 4 - names = {v.name for v in vars} + names = {v.display_name for v in vars} assert names == {'temperature', 'volume'} def test_get_all_variables_mixed_elements(self): @@ -614,7 +614,7 @@ def test_get_all_variables_mixed_elements(self): el = EasyList(m1, a1) vars = el.get_all_variables() assert len(vars) == 2 - names = {v.name for v in vars} + names = {v.display_name for v in vars} assert names == {'temperature', 'volume'} def test_get_all_variables_nested_model(self): @@ -625,7 +625,7 @@ def test_get_all_variables_nested_model(self): vars = el.get_all_variables() # parent: pressure (Parameter), inner: temperature (Parameter), volume (DescriptorNumber) assert len(vars) == 3 - names = {v.name for v in vars} + names = {v.display_name for v in vars} assert names == {'pressure', 'temperature', 'volume'} def test_get_all_variables_returns_descriptorbase_instances(self): @@ -640,8 +640,8 @@ def test_get_all_variables_returns_descriptorbase_instances(self): def test_get_all_variables_bare_parameters(self): """Bare Parameters passed to the constructor should be collected directly.""" - p1 = Parameter('a', value=1.0) - p2 = Parameter('b', value=2.0) + p1 = Parameter(value=1.0, display_name='a') + p2 = Parameter(value=2.0, display_name='b') el = EasyList(p1, p2) vars = el.get_all_variables() assert vars == [p1, p2] @@ -649,8 +649,8 @@ def test_get_all_variables_bare_parameters(self): def test_get_all_variables_bare_descriptors(self): """Bare DescriptorNumbers are collected as variables but are not fit parameters.""" - p1 = Parameter('a', value=1.0) - d1 = DescriptorNumber('b', value=2.0) + p1 = Parameter(value=1.0, display_name='a') + d1 = DescriptorNumber(value=2.0, display_name='b') el = EasyList(p1, d1) assert el.get_all_variables() == [p1, d1] assert el.get_all_parameters() == [p1] @@ -658,42 +658,42 @@ def test_get_all_variables_bare_descriptors(self): def test_get_all_variables_fixed_parameter_not_fitted(self): """A fixed bare Parameter is returned as a variable but not as a fit parameter.""" - free = Parameter('a', value=1.0) - fixed = Parameter('b', value=2.0, fixed=True) + free = Parameter(value=1.0, display_name='a') + fixed = Parameter(value=2.0, fixed=True, display_name='b') el = EasyList(free, fixed) assert el.get_all_variables() == [free, fixed] assert el.get_fit_parameters() == [free] def test_get_all_variables_parameters_from_list(self): """A plain list of Parameters should be flattened and collected.""" - p1 = Parameter('a', value=1.0) - p2 = Parameter('b', value=2.0) + p1 = Parameter(value=1.0, display_name='a') + p2 = Parameter(value=2.0, display_name='b') el = EasyList([p1, p2]) assert len(el) == 2 assert el.get_all_variables() == [p1, p2] def test_get_all_variables_parameters_from_tuple(self): """A plain tuple of Parameters should be flattened and collected.""" - p1 = Parameter('a', value=1.0) - p2 = Parameter('b', value=2.0) + p1 = Parameter(value=1.0, display_name='a') + p2 = Parameter(value=2.0, display_name='b') el = EasyList((p1, p2)) assert len(el) == 2 assert el.get_all_variables() == [p1, p2] def test_get_all_variables_bare_parameters_and_model(self): """Bare Parameters and ModelBase items should both contribute variables.""" - p1 = Parameter('a', value=1.0) + p1 = Parameter(value=1.0, display_name='a') m1 = MockModel(unique_name='m1', temperature=10, volume=5.0) el = EasyList(p1, m1) vars = el.get_all_variables() assert len(vars) == 3 assert vars[0] is p1 - assert {v.name for v in vars[1:]} == {'temperature', 'volume'} + assert {v.display_name for v in vars[1:]} == {'temperature', 'volume'} def test_get_all_variables_bare_parameters_in_nested_easylist(self): """Bare Parameters inside a nested EasyList should be collected by the outer list.""" - p1 = Parameter('a', value=1.0) - p2 = Parameter('b', value=2.0) + p1 = Parameter(value=1.0, display_name='a') + p2 = Parameter(value=2.0, display_name='b') inner_list = EasyList(p1) outer_list = EasyList(inner_list, p2) assert outer_list.get_all_variables() == [p1, p2] @@ -731,7 +731,7 @@ def test_get_all_variables_nested_easylist(self): assert isinstance(v, DescriptorNumber) # Collect temperatures and volumes from both models - temps = {v.value for v in vars if v.name == 'temperature'} - vols = {v.value for v in vars if v.name == 'volume'} + temps = {v.value for v in vars if v.display_name == 'temperature'} + vols = {v.value for v in vars if v.display_name == 'volume'} assert temps == {50, 70} assert vols == {3.0, 4.0} diff --git a/tests/unit/base_classes/test_model_base.py b/tests/unit/base_classes/test_model_base.py index e91c20a9..504e888e 100644 --- a/tests/unit/base_classes/test_model_base.py +++ b/tests/unit/base_classes/test_model_base.py @@ -20,9 +20,11 @@ class MockModelComponent(ModelBase): def __init__(self, display_name=None, unique_name=None, temperature=0, room_temperature=22): super().__init__(display_name=display_name, unique_name=unique_name) - self._temperature = Parameter(name='temperature', value=temperature) - self._room_temperature = DescriptorNumber(name='room_temperature', value=room_temperature) - self._status = DescriptorStr(name='status', value='OK') + self._temperature = Parameter(display_name='temperature', value=temperature) + self._room_temperature = DescriptorNumber( + display_name='room_temperature', value=room_temperature + ) + self._status = DescriptorStr(display_name='status', value='OK') @property def temperature(self): @@ -56,8 +58,8 @@ class MockModelFull(ModelBase): def __init__(self, component=None, display_name=None, unique_name=None, pressure=0, area=1): super().__init__(display_name=display_name, unique_name=unique_name) - self._pressure = Parameter(name='pressure', value=pressure) - self._area = Parameter(name='area', value=area) + self._pressure = Parameter(display_name='pressure', value=pressure) + self._area = Parameter(display_name='area', value=area) if component is not None: self._component = component else: diff --git a/tests/unit/base_classes/test_obj_base.py b/tests/unit/base_classes/test_obj_base.py index 723d617f..8b95c96d 100644 --- a/tests/unit/base_classes/test_obj_base.py +++ b/tests/unit/base_classes/test_obj_base.py @@ -29,11 +29,11 @@ def clear(): def setup_pars(): d = { 'name': 'test', - 'par1': Parameter('p1', 0.1, fixed=True), - 'des1': DescriptorNumber('d1', 0.1), - 'par2': Parameter('p2', 0.1), - 'des2': DescriptorNumber('d2', 0.1), - 'par3': Parameter('p3', 0.1), + 'par1': Parameter(0.1, fixed=True, display_name='p1'), + 'des1': DescriptorNumber(0.1, display_name='d1'), + 'par2': Parameter(0.1, display_name='p2'), + 'des2': DescriptorNumber(0.1, display_name='d2'), + 'par3': Parameter(0.1, display_name='p3'), } return d @@ -50,13 +50,24 @@ def not_raises(expected_exception: Union[Type[BaseException], List[Type[BaseExce raise pytest.fail('An unexpected exception {0} raised.'.format(repr(err))) +#: ``ObjBase`` keys positional components on ``arg.name`` (obj_base.py:71), which +#: descriptors no longer have. Pass descriptors as keyword arguments instead. +_positional_descriptors_unsupported = pytest.mark.xfail( + strict=True, + raises=AttributeError, + reason='legacy ObjBase keys positional components on the removed descriptor `name` (#308/#292)', +) + + @pytest.mark.parametrize( 'a, kw', [ ([], ['par1']), - (['par1'], []), - (['par1'], ['par2']), - (['par1', 'des1'], ['par2', 'des2']), + pytest.param(['par1'], [], marks=_positional_descriptors_unsupported), + pytest.param(['par1'], ['par2'], marks=_positional_descriptors_unsupported), + pytest.param( + ['par1', 'des1'], ['par2', 'des2'], marks=_positional_descriptors_unsupported + ), ], ) def test_ObjBase_create(setup_pars: dict, a: List[str], kw: List[str]): @@ -70,20 +81,15 @@ def test_ObjBase_create(setup_pars: dict, a: List[str], kw: List[str]): base = ObjBase(name, None, *args, **kwargs) assert base.name == name for key in a: - item = getattr(base, setup_pars[key].name) + item = getattr(base, setup_pars[key].display_name) assert isinstance(item, setup_pars[key].__class__) def test_ObjBase_copy(setup_pars: dict): # When name = setup_pars['name'] - args = [] - for key in ['par1', 'des1']: - args.append(setup_pars[key]) - kwargs = {} - for key in ['par2', 'des2']: - kwargs[key] = setup_pars[key] - base = ObjBase(name, None, *args, **kwargs) + kwargs = {key: setup_pars[key] for key in ['par1', 'des1', 'par2', 'des2']} + base = ObjBase(name, None, **kwargs) # Then base_copy = copy(base) @@ -92,9 +98,12 @@ def test_ObjBase_copy(setup_pars: dict): assert base_copy.name == name assert base_copy.unique_name != base.unique_name - for key in ['par1', 'des1']: - item = getattr(base, setup_pars[key].name) + for key in kwargs: + item = getattr(base_copy, key) assert isinstance(item, setup_pars[key].__class__) + assert item.unique_name != setup_pars[key].unique_name + assert item.value == setup_pars[key].value + assert item.display_name == setup_pars[key].display_name def test_ObjBase_get(setup_pars: dict): @@ -102,8 +111,8 @@ def test_ObjBase_get(setup_pars: dict): explicit_name1 = 'par1' explicit_name2 = 'par2' kwargs = { - setup_pars[explicit_name1].name: setup_pars[explicit_name1], - setup_pars[explicit_name2].name: setup_pars[explicit_name2], + setup_pars[explicit_name1].display_name: setup_pars[explicit_name1], + setup_pars[explicit_name2].display_name: setup_pars[explicit_name2], } obj = ObjBase(name, **kwargs) with not_raises(AttributeError): @@ -116,7 +125,7 @@ def test_ObjBase_set(setup_pars: dict): name = setup_pars['name'] explicit_name1 = 'par1' kwargs = { - setup_pars[explicit_name1].name: setup_pars[explicit_name1], + setup_pars[explicit_name1].display_name: setup_pars[explicit_name1], } obj = ObjBase(name, **kwargs) new_value = 5.0 @@ -132,7 +141,7 @@ def test_ObjBase_get_parameters(setup_pars: dict): pars = obj.get_fit_parameters() assert isinstance(pars, list) assert len(pars) == 2 - par_names = [par.name for par in pars] + par_names = [par.display_name for par in pars] assert 'p2' in par_names assert 'p3' in par_names @@ -156,7 +165,7 @@ def test_ObjBase_to_dict(clear, setup_pars: dict): '@module': Parameter.__module__, '@class': Parameter.__name__, '@version': easyscience.__version__, - 'name': 'p1', + 'display_name': 'p1', 'value': 0.1, 'variance': 0.0, 'min': -np.inf, @@ -170,7 +179,6 @@ def test_ObjBase_to_dict(clear, setup_pars: dict): '@module': DescriptorNumber.__module__, '@class': DescriptorNumber.__name__, '@version': easyscience.__version__, - 'name': 'd1', 'value': 0.1, 'unit': 'dimensionless', 'description': '', @@ -181,7 +189,7 @@ def test_ObjBase_to_dict(clear, setup_pars: dict): '@module': Parameter.__module__, '@class': Parameter.__name__, '@version': easyscience.__version__, - 'name': 'p2', + 'display_name': 'p2', 'value': 0.1, 'variance': 0.0, 'min': -np.inf, @@ -195,7 +203,6 @@ def test_ObjBase_to_dict(clear, setup_pars: dict): '@module': DescriptorNumber.__module__, '@class': DescriptorNumber.__name__, '@version': easyscience.__version__, - 'name': 'd2', 'value': 0.1, 'unit': 'dimensionless', 'description': '', @@ -206,7 +213,7 @@ def test_ObjBase_to_dict(clear, setup_pars: dict): '@module': Parameter.__module__, '@class': Parameter.__name__, '@version': easyscience.__version__, - 'name': 'p3', + 'display_name': 'p3', 'value': 0.1, 'variance': 0.0, 'min': -np.inf, @@ -332,7 +339,7 @@ def test_ObjBase__add_component(setup_pars): del setup_pars['name'] obj = ObjBase(name, **setup_pars) - p = Parameter('added_par', 1) + p = Parameter(1, display_name='added_par') new_item_name = 'Added' obj._add_component(new_item_name, p) @@ -355,7 +362,7 @@ def __init__(self, a: Parameter): @classmethod def from_pars(cls, a: float): - return cls(a=Parameter('a', a)) + return cls(a=Parameter(a, display_name='a')) a_start = 5 a_end = 10 @@ -378,7 +385,7 @@ def __init__(self, a: Parameter): @classmethod def from_pars(cls, a: float): - return cls(a=Parameter('a', a)) + return cls(a=Parameter(a, display_name='a')) a = A.from_pars(5) b_new = 10 @@ -395,7 +402,7 @@ def __init__(self, a: Parameter): @classmethod def from_pars(cls, a: float): - return cls(a=Parameter('a', a)) + return cls(a=Parameter(a, display_name='a')) a_start = 5 a_end = 10 @@ -419,7 +426,7 @@ def __init__(self, a: Parameter): @classmethod def from_pars(cls, a: float): - return cls(a=Parameter('a', a)) + return cls(a=Parameter(a, display_name='a')) a_start = 5 a_end = 10 @@ -428,7 +435,7 @@ def from_pars(cls, a: float): assert a.a.value == a_start assert len(graph.get_edges(a)) == 1 - a_ = Parameter('a', a_end) + a_ = Parameter(a_end, display_name='a') assert a.a.unique_name in graph.get_edges(a) a__ = a.a @@ -442,7 +449,7 @@ def from_pars(cls, a: float): def test_BaseCreation(): class A(ObjBase): def __init__(self, a: Optional[Union[Parameter, float]] = None): - super(A, self).__init__('A', a=Parameter('a', 1.0)) + super(A, self).__init__('A', a=Parameter(1.0, display_name='a')) if a is not None: self.a = a @@ -450,7 +457,7 @@ def __init__(self, a: Optional[Union[Parameter, float]] = None): assert a.a.value == 1.0 a = A(2.0) assert a.a.value == 2.0 - a = A(Parameter('a', 3.0)) + a = A(Parameter(3.0, display_name='a')) assert a.a.value == 3.0 a.a = 4.0 assert a.a.value == 4.0 diff --git a/tests/unit/fitting/calculators/test_interface_factory.py b/tests/unit/fitting/calculators/test_interface_factory.py index ce5bb17a..23910309 100644 --- a/tests/unit/fitting/calculators/test_interface_factory.py +++ b/tests/unit/fitting/calculators/test_interface_factory.py @@ -252,7 +252,7 @@ def test_generate_bindings_with_matching_properties(self, factory_single_interfa # Given mock_model = MagicMock() mock_prop = MagicMock() - mock_prop.name = 'test_param' + mock_prop.display_name = 'test_param' mock_prop.value = 42 mock_model._get_linkable_attributes.return_value = [mock_prop] @@ -276,7 +276,7 @@ def test_generate_bindings_with_value_no_call_back_property(self, factory_single # Given mock_model = MagicMock() mock_prop = MagicMock() - mock_prop.name = 'test_param' + mock_prop.display_name = 'test_param' mock_prop.value_no_call_back = 24 mock_model._get_linkable_attributes.return_value = [mock_prop] @@ -300,7 +300,7 @@ def test_generate_bindings_skips_non_matching_properties(self, factory_single_in # Given mock_model = MagicMock() mock_prop = MagicMock() - mock_prop.name = 'non_matching_param' + mock_prop.display_name = 'non_matching_param' mock_model._get_linkable_attributes.return_value = [mock_prop] mock_item = MagicMock() @@ -391,7 +391,7 @@ def test_generate_bindings_with_property_without_value_no_call_back( # Given mock_model = MagicMock() mock_prop = MagicMock() - mock_prop.name = 'test_param' + mock_prop.display_name = 'test_param' mock_prop.value = 99 # This will be used since no value_no_call_back attribute # Explicitly remove value_no_call_back to force the else branch del mock_prop.value_no_call_back diff --git a/tests/unit/fitting/minimizers/bumps_utils/test_problem.py b/tests/unit/fitting/minimizers/bumps_utils/test_problem.py index d1208138..23912f55 100644 --- a/tests/unit/fitting/minimizers/bumps_utils/test_problem.py +++ b/tests/unit/fitting/minimizers/bumps_utils/test_problem.py @@ -18,7 +18,7 @@ class TestToBumpsParameter: def test_convert_parameter_object(self) -> None: from easyscience.variable import Parameter - param = Parameter('thickness', 42.0, min=0.0, max=100.0) + param = Parameter(42.0, min=0.0, max=100.0, display_name='thickness') param.fixed = False result = to_bumps_parameter(param) @@ -32,7 +32,7 @@ def test_convert_parameter_object(self) -> None: def test_convert_fixed_parameter(self) -> None: from easyscience.variable import Parameter - param = Parameter('roughness', 5.0, min=0.0, max=20.0) + param = Parameter(5.0, min=0.0, max=20.0, display_name='roughness') param.fixed = True result = to_bumps_parameter(param) diff --git a/tests/unit/fitting/test_multi_fitter.py b/tests/unit/fitting/test_multi_fitter.py index 3af44358..fb2e02d2 100644 --- a/tests/unit/fitting/test_multi_fitter.py +++ b/tests/unit/fitting/test_multi_fitter.py @@ -19,8 +19,8 @@ class Line(ModelBase): def __init__(self, m_val: float, c_val: float): super().__init__() - self._m = Parameter('m', m_val) - self._c = Parameter('c', c_val) + self._m = Parameter(m_val, display_name='m') + self._c = Parameter(c_val, display_name='c') @property def m(self) -> Parameter: @@ -49,7 +49,9 @@ class LegacyLine(ObjBase): c: Parameter def __init__(self, m_val: float, c_val: float): - super().__init__('line', m=Parameter('m', m_val), c=Parameter('c', c_val)) + super().__init__( + 'line', m=Parameter(m_val, display_name='m'), c=Parameter(c_val, display_name='c') + ) def __call__(self, x): return self.m.value * x + self.c.value @@ -264,7 +266,7 @@ def test_rejects_bare_parameter(self): harvests parameters from ModelBase members).""" model = Line(1.0, 0.5) with pytest.raises(TypeError, match='Items must be one of'): - MultiFitter([model, Parameter('p', 1.0)], [model, None]) + MultiFitter([model, Parameter(1.0, display_name='p')], [model, None]) def test_flattens_nested_list(self): """Nested lists are flattened, as CollectionBase did.""" diff --git a/tests/unit/fitting/test_sampler.py b/tests/unit/fitting/test_sampler.py index e2151741..0bb8a279 100644 --- a/tests/unit/fitting/test_sampler.py +++ b/tests/unit/fitting/test_sampler.py @@ -27,8 +27,8 @@ class AbsSin(ModelBase): def __init__(self, offset_val: float, phase_val: float): super().__init__() - self._offset = Parameter('offset', offset_val) - self._phase = Parameter('phase', phase_val) + self._offset = Parameter(offset_val, display_name='offset') + self._phase = Parameter(phase_val, display_name='phase') @property def offset(self) -> Parameter: diff --git a/tests/unit/global_object/test_global_object.py b/tests/unit/global_object/test_global_object.py index 719fee5a..6199c542 100644 --- a/tests/unit/global_object/test_global_object.py +++ b/tests/unit/global_object/test_global_object.py @@ -33,13 +33,13 @@ def test_generate_unique_name_already_taken(self): global_object = GlobalObject() # Block the other_name_prefix_2 name keep_due_toweakref_1 = DescriptorBool( - name='test', value=True, unique_name='other_name_prefix_2' + display_name='test', value=True, unique_name='other_name_prefix_2' ) keep_due_toweakref_2 = DescriptorBool( - name='test', value=True, unique_name='other_name_prefix_a_3' + display_name='test', value=True, unique_name='other_name_prefix_a_3' ) keep_due_toweakref_3 = DescriptorBool( - name='test', value=True, unique_name='almost_other_name_prefix_3' + display_name='test', value=True, unique_name='almost_other_name_prefix_3' ) # Then @@ -109,9 +109,9 @@ def test_generate_unique_name_with_gaps(self, clear_global_map): # Given global_obj = GlobalObject() # Create objects with non-sequential names - keep1 = DescriptorBool(name='test', value=True, unique_name='prefix_0') - keep2 = DescriptorBool(name='test', value=True, unique_name='prefix_2') - keep3 = DescriptorBool(name='test', value=True, unique_name='prefix_5') + keep1 = DescriptorBool(display_name='test', value=True, unique_name='prefix_0') + keep2 = DescriptorBool(display_name='test', value=True, unique_name='prefix_2') + keep3 = DescriptorBool(display_name='test', value=True, unique_name='prefix_5') # When name = global_obj.generate_unique_name('prefix') @@ -123,8 +123,8 @@ def test_generate_unique_name_non_numeric_suffix(self, clear_global_map): """Test that non-numeric suffixes are ignored""" # Given global_obj = GlobalObject() - keep1 = DescriptorBool(name='test', value=True, unique_name='prefix_abc') - keep2 = DescriptorBool(name='test', value=True, unique_name='prefix_1') + keep1 = DescriptorBool(display_name='test', value=True, unique_name='prefix_abc') + keep2 = DescriptorBool(display_name='test', value=True, unique_name='prefix_1') # When name = global_obj.generate_unique_name('prefix') @@ -136,8 +136,8 @@ def test_generate_unique_name_similar_prefixes(self, clear_global_map): """Test that similar but different prefixes don't interfere""" # Given global_obj = GlobalObject() - keep1 = DescriptorBool(name='test', value=True, unique_name='test_param_5') - keep2 = DescriptorBool(name='test', value=True, unique_name='test_parameter_10') + keep1 = DescriptorBool(display_name='test', value=True, unique_name='test_param_5') + keep2 = DescriptorBool(display_name='test', value=True, unique_name='test_parameter_10') # When name1 = global_obj.generate_unique_name('test_param') @@ -153,8 +153,8 @@ def test_integration_with_parameter_creation(self, clear_global_map): global_obj = GlobalObject() # When - param1 = Parameter(name='test1', value=1.0) - param2 = Parameter(name='test2', value=2.0) + param1 = Parameter(display_name='test1', value=1.0) + param2 = Parameter(display_name='test2', value=2.0) # Then assert len(global_obj.map.vertices()) == 2 diff --git a/tests/unit/global_object/test_integration_comprehensive.py b/tests/unit/global_object/test_integration_comprehensive.py index 541c9e46..13424351 100644 --- a/tests/unit/global_object/test_integration_comprehensive.py +++ b/tests/unit/global_object/test_integration_comprehensive.py @@ -33,7 +33,7 @@ def test_parameter_lifecycle_integration(self, clear_all): global_obj = GlobalObject() # When - Create parameter - param = Parameter(name='test_param', value=10.0, unit='m') + param = Parameter(display_name='test_param', value=10.0, unit='m') # Then - Should be registered in global map assert global_obj.map.is_known(param) @@ -78,8 +78,8 @@ def test_objbase_parameter_relationship(self, clear_all): # Given global_obj = GlobalObject() - param1 = Parameter(name='length', value=10.0, unit='m') - param2 = Parameter(name='width', value=5.0, unit='m') + param1 = Parameter(display_name='length', value=10.0, unit='m') + param2 = Parameter(display_name='width', value=5.0, unit='m') # When - Create ObjBase with parameters obj = ObjBase(name='rectangle', length=param1, width=param2) @@ -114,7 +114,7 @@ def test_unique_name_generation_integration(self, clear_all): # When - Create multiple objects of same type params = [] for i in range(5): - param = Parameter(name=f'param_{i}', value=float(i)) + param = Parameter(display_name=f'param_{i}', value=float(i)) params.append(param) # Then - Should have unique names @@ -127,7 +127,7 @@ def test_unique_name_generation_integration(self, clear_all): # When - Create mixed object types obj = ObjBase(name='test_obj') - desc = DescriptorBool(name='test_desc', value=True) + desc = DescriptorBool(display_name='test_desc', value=True) # Then - Should not interfere with each other's naming assert obj.unique_name == 'ObjBase_0' @@ -137,7 +137,7 @@ def test_map_vertex_type_management(self, clear_all): """Test comprehensive vertex type management""" # Given global_obj = GlobalObject() - param = Parameter(name='test', value=1.0) + param = Parameter(display_name='test', value=1.0) # When - Check initial type initial_types = global_obj.map.find_type(param) @@ -168,8 +168,8 @@ def test_weak_reference_cleanup_integration(self, clear_all): global_obj = GlobalObject() # When - Create objects - param1 = Parameter(name='temp1', value=1.0) - param2 = Parameter(name='temp2', value=2.0) + param1 = Parameter(display_name='temp1', value=1.0) + param2 = Parameter(display_name='temp2', value=2.0) obj = ObjBase(name='temp_obj', param1=param1, param2=param2) param1_name = param1.unique_name @@ -206,9 +206,9 @@ def test_complex_undo_redo_scenario(self, clear_all): global_obj.stack.enabled = True # Create a complex object structure - length = Parameter(name='length', value=10.0, unit='m') - width = Parameter(name='width', value=5.0, unit='m') - height = Parameter(name='height', value=3.0, unit='m') + length = Parameter(display_name='length', value=10.0, unit='m') + width = Parameter(display_name='width', value=5.0, unit='m') + height = Parameter(display_name='height', value=3.0, unit='m') box = ObjBase(name='box', length=length, width=width, height=height) @@ -252,7 +252,7 @@ def test_map_path_finding_integration(self, clear_all): global_obj = GlobalObject() # Create a hierarchy: container -> sub_container -> parameter - param = Parameter(name='value', value=42.0) + param = Parameter(display_name='value', value=42.0) sub_container = ObjBase(name='sub', value=param) main_container = ObjBase(name='main', sub=sub_container) @@ -277,8 +277,8 @@ def test_map_connectivity_with_isolated_objects(self, clear_all): global_obj = GlobalObject() # When - Create connected objects - param1 = Parameter(name='connected1', value=1.0) - param2 = Parameter(name='connected2', value=2.0) + param1 = Parameter(display_name='connected1', value=1.0) + param2 = Parameter(display_name='connected2', value=2.0) container = ObjBase(name='container', p1=param1, p2=param2) # Then - Map should be connected @@ -286,7 +286,7 @@ def test_map_connectivity_with_isolated_objects(self, clear_all): # assert global_obj.map.is_connected() # When - Create isolated object - isolated = Parameter(name='isolated', value=99.0) + isolated = Parameter(display_name='isolated', value=99.0) # Remove its automatic connection by clearing edges # (In real usage, isolated objects would be rare) @@ -305,7 +305,7 @@ def test_error_handling_integration(self, clear_all): global_obj.map.get_item_by_key('non_existent') # When - Try to add object with duplicate name - param1 = Parameter(name='test', value=1.0) + param1 = Parameter(display_name='test', value=1.0) param1_name = param1.unique_name # Create another with same unique name (should fail in add_vertex) @@ -321,7 +321,7 @@ def test_memory_pressure_simulation(self, clear_all): # When - Create many objects objects = [] for i in range(100): - param = Parameter(name=f'param_{i}', value=float(i)) + param = Parameter(display_name=f'param_{i}', value=float(i)) obj = ObjBase(name=f'obj_{i}', param=param) objects.append((param, obj)) @@ -355,7 +355,7 @@ def test_serialization_integration_with_global_state(self, clear_all): global_obj = GlobalObject() # Create objects - param = Parameter(name='test_param', value=123.45, unit='kg') + param = Parameter(display_name='test_param', value=123.45, unit='kg') obj = ObjBase(name='test_obj', param=param) original_vertex_count = len(global_obj.map.vertices()) @@ -378,7 +378,7 @@ def test_serialization_integration_with_global_state(self, clear_all): assert global_obj.map.is_known(new_obj) # Objects should be functionally equivalent - assert new_param.name == param.name + assert new_param.display_name == param.display_name assert new_param.value == param.value assert new_param.unit == param.unit @@ -397,7 +397,7 @@ def test_debug_mode_integration(self, clear_all): global_obj.stack.enabled = True # Create and modify objects - param = Parameter(name='debug_test', value=1.0) + param = Parameter(display_name='debug_test', value=1.0) # This should trigger debug output in property_stack decorator with patch('builtins.print') as mock_print: @@ -428,7 +428,7 @@ def create_objects(thread_id, count=10): """Create objects in a thread""" try: for i in range(count): - param = Parameter(name=f'thread_{thread_id}_param_{i}', value=float(i)) + param = Parameter(display_name=f'thread_{thread_id}_param_{i}', value=float(i)) results.append(param.unique_name) time.sleep(0.001) # Small delay to encourage race conditions except Exception as e: diff --git a/tests/unit/global_object/test_map.py b/tests/unit/global_object/test_map.py index c68aa96f..259fa0dc 100644 --- a/tests/unit/global_object/test_map.py +++ b/tests/unit/global_object/test_map.py @@ -141,7 +141,7 @@ def base_object(self): @pytest.fixture def parameter_object(self): - return Parameter(name='test2', value=2) + return Parameter(display_name='test2', value=2) def test_add_vertex(self, clear, base_object, parameter_object): # When Then Expect @@ -182,13 +182,15 @@ def test_get_item_by_key(self, clear, base_object, parameter_object): assert global_object.map.get_item_by_key(base_object.unique_name) == base_object assert global_object.map.get_item_by_key(parameter_object.unique_name) == parameter_object - @pytest.mark.parametrize('cls, kwargs', [(ObjBase, {}), (Parameter, {'value': 2.0})]) + @pytest.mark.parametrize( + 'cls, kwargs', [(ObjBase, {'name': 'test'}), (Parameter, {'value': 2.0})] + ) def test_identical_unique_names_exception(self, clear, cls, kwargs): # When - test_obj = cls(name='test', unique_name='test', **kwargs) + test_obj = cls(unique_name='test', **kwargs) # Then Expect with pytest.raises(ValueError): - test_obj2 = cls(name='test2', unique_name='test', **kwargs) + test_obj2 = cls(unique_name='test', **kwargs) def test_unique_name_change_still_in_map(self, clear, base_object, parameter_object): # When @@ -381,7 +383,7 @@ def test_type_filtering_properties(self, clear): """Test type filtering properties""" # Given obj1 = ObjBase(name='obj1') # 'created' type - obj2 = Parameter(name='obj2', value=1) # 'created' type + obj2 = Parameter(display_name='obj2', value=1) # 'created' type global_object.map.change_type(obj1, 'argument') global_object.map.change_type(obj2, 'returned') diff --git a/tests/unit/global_object/test_undo_redo.py b/tests/unit/global_object/test_undo_redo.py index 0171a0e6..23abd276 100644 --- a/tests/unit/global_object/test_undo_redo.py +++ b/tests/unit/global_object/test_undo_redo.py @@ -20,9 +20,9 @@ def createSingleObjs(idx): reps = math.floor(idx / len(alphabet)) + 1 name = alphabet[idx % len(alphabet)] * reps if idx % 2: - return Parameter(name, idx, unit='m/s') + return Parameter(idx, unit='m/s', display_name=name) else: - return DescriptorNumber(name, idx, unit='m/s') + return DescriptorNumber(idx, unit='m/s', display_name=name) def createParam(option): @@ -74,7 +74,7 @@ def getter(_obj, _attr): ], ) def test_DescriptorNumberUndoRedo(test): - obj = DescriptorNumber('DescriptorNumber', 1, unit='m/s') + obj = DescriptorNumber(1, unit='m/s', display_name='DescriptorNumber') attr = test[0] value = test[1] @@ -83,14 +83,14 @@ def test_DescriptorNumberUndoRedo(test): def test_DescriptorBoolUndoRedo(): - obj = DescriptorBool('DescriptorBool', False) + obj = DescriptorBool(False, display_name='DescriptorBool') attr = 'value' value = True e = doUndoRedo(obj, attr, value) assert not e - obj = DescriptorBool('DescriptorBool', True) + obj = DescriptorBool(True, display_name='DescriptorBool') attr = 'value' value = False @@ -99,7 +99,7 @@ def test_DescriptorBoolUndoRedo(): def test_DescriptorStrUndoRedo(): - obj = DescriptorStr('DescriptorStr', 'Foo') + obj = DescriptorStr('Foo', display_name='DescriptorStr') attr = 'value' value = 'Bar' @@ -123,7 +123,7 @@ def test_DescriptorStrUndoRedo(): ], ) def test_ParameterUndoRedo(test): - obj = Parameter('Parameter', 1, unit='m/s') + obj = Parameter(1, unit='m/s', display_name='Parameter') attr = test[0] value = test[1] @@ -135,7 +135,7 @@ def test_Parameter_Bounds_UndoRedo(): from easyscience import global_object global_object.stack.enabled = True - parameter = Parameter('test', 1) + parameter = Parameter(1, display_name='test') assert parameter.min == -np.inf assert parameter.max == np.inf @@ -151,7 +151,7 @@ def test_Parameter_Bounds_UndoRedo(): def test_ObjBaseUndoRedo(): - objs = {obj.name: obj for obj in [createSingleObjs(idx) for idx in range(5)]} + objs = {obj.display_name: obj for obj in [createSingleObjs(idx) for idx in range(5)]} name = 'test' obj = ObjBase(name, **objs) name2 = 'best' @@ -161,7 +161,7 @@ def test_ObjBaseUndoRedo(): # Test setting value for b_obj in objs.values(): - e = doUndoRedo(obj, b_obj.name, b_obj.value + 1, 'value') + e = doUndoRedo(obj, b_obj.display_name, b_obj.value + 1, 'value') assert not e @@ -178,7 +178,7 @@ def test_CollectionBaseUndoRedo(): global_object.stack.enabled = True original_length = len(obj) - p = Parameter('slip_in', 50) + p = Parameter(50, display_name='slip_in') idx = 2 obj.insert(idx, p) assert len(obj) == original_length + 1 @@ -279,14 +279,14 @@ def __init__(self, m: Parameter, c: Parameter): @classmethod def default(cls): - m = Parameter('m', m_value) - c = Parameter('c', c_value) + m = Parameter(m_value, display_name='m') + c = Parameter(c_value, display_name='c') return cls(m=m, c=c) @classmethod def from_pars(cls, m_value: float, c_value: float): - m = Parameter('m', m_value) - c = Parameter('c', c_value) + m = Parameter(m_value, display_name='m') + c = Parameter(c_value, display_name='c') return cls(m=m, c=c) def __call__(self, x: np.ndarray) -> np.ndarray: diff --git a/tests/unit/io/test_serializer_base.py b/tests/unit/io/test_serializer_base.py index 550c4d75..0f479e2e 100644 --- a/tests/unit/io/test_serializer_base.py +++ b/tests/unit/io/test_serializer_base.py @@ -231,7 +231,6 @@ def test_convert_from_dict_easyscience_object(self, clear): '@module': 'easyscience.variable.parameter', '@class': 'Parameter', '@version': '0.6.0', - 'name': 'test_param', 'value': 5.0, 'unit': 'm', 'variance': 0.1, @@ -245,7 +244,7 @@ def test_convert_from_dict_easyscience_object(self, clear): result = SerializerBase._convert_from_dict(param_dict) assert isinstance(result, Parameter) - assert result.name == 'test_param' + assert result.display_name == 'test_param' assert result.value == 5.0 assert str(result.unit) == 'm' @@ -427,8 +426,8 @@ def test_recursive_encoder_with_mutable_sequence(self, serializer, clear): """Test _recursive_encoder with MutableSequence objects""" from easyscience.base_classes import CollectionBase - d0 = DescriptorNumber('a', 0) # type: ignore - d1 = DescriptorNumber('b', 1) # type: ignore + d0 = DescriptorNumber(0, display_name='a') # type: ignore + d1 = DescriptorNumber(1, display_name='b') # type: ignore collection = CollectionBase('test_collection', d0, d1) result = serializer._recursive_encoder(collection) @@ -701,7 +700,7 @@ def test_deserialize_dict(self, monkeypatch): '_deserialize_value', MagicMock( side_effect=[ - Parameter(name='param1', value=10.0), + Parameter(display_name='param1', value=10.0), np.array([0, 1], dtype=np.int64), ] ), diff --git a/tests/unit/io/test_serializer_component.py b/tests/unit/io/test_serializer_component.py index a90e364c..08cc3405 100644 --- a/tests/unit/io/test_serializer_component.py +++ b/tests/unit/io/test_serializer_component.py @@ -19,7 +19,6 @@ '@module': DescriptorNumber.__module__, '@class': DescriptorNumber.__name__, '@version': easyscience.__version__, - 'name': 'test', 'value': 1.0, 'variance': None, 'unit': 'dimensionless', @@ -34,7 +33,6 @@ '@module': Parameter.__module__, '@class': Parameter.__name__, '@version': easyscience.__version__, - 'name': 'test', 'unit': 'km', 'value': 1.0, 'variance': 0.0, diff --git a/tests/unit/io/test_serializer_dict.py b/tests/unit/io/test_serializer_dict.py index 1b37fae9..f725c261 100644 --- a/tests/unit/io/test_serializer_dict.py +++ b/tests/unit/io/test_serializer_dict.py @@ -100,8 +100,8 @@ def test_variable_SerializerDict_from_dict(dp_kwargs: dict, dp_cls: Type[Descrip def test_group_encode(): - d0 = DescriptorNumber('a', 0) - d1 = DescriptorNumber('b', 1) + d0 = DescriptorNumber(0, display_name='a') + d1 = DescriptorNumber(1, display_name='b') from easyscience.base_classes import CollectionBase @@ -111,8 +111,8 @@ def test_group_encode(): def test_group_encode2(): - d0 = DescriptorNumber('a', 0) - d1 = DescriptorNumber('b', 1) + d0 = DescriptorNumber(0, display_name='a') + d1 = DescriptorNumber(1, display_name='b') from easyscience.base_classes import CollectionBase diff --git a/tests/unit/legacy/test_collection_base.py b/tests/unit/legacy/test_collection_base.py index 152a0a37..9583d06b 100644 --- a/tests/unit/legacy/test_collection_base.py +++ b/tests/unit/legacy/test_collection_base.py @@ -16,6 +16,15 @@ from easyscience import global_object from easyscience.legacy.collection_base import CollectionBase +#: ``CollectionBase.__getitem__`` resolves a string index against ``item.name`` +#: (collection_base.py:187), which descriptors no longer have. +#: Index by position or ``unique_name`` instead. +_string_indexing_unsupported = pytest.mark.xfail( + strict=True, + raises=AttributeError, + reason='legacy CollectionBase string indexing uses the removed descriptor `name` (#308/#292)', +) + @pytest.fixture(autouse=True) def _clear_map(): @@ -28,11 +37,11 @@ def _clear_map(): def setup_pars(): return { 'name': 'test', - 'par1': Parameter('p1', 0.1, fixed=True), - 'des1': DescriptorNumber('d1', 0.1), - 'par2': Parameter('p2', 0.2), - 'des2': DescriptorNumber('d2', 0.2), - 'par3': Parameter('p3', 0.3), + 'par1': Parameter(0.1, fixed=True, display_name='p1'), + 'des1': DescriptorNumber(0.1, display_name='d1'), + 'par2': Parameter(0.2, display_name='p2'), + 'des2': DescriptorNumber(0.2, display_name='d2'), + 'par3': Parameter(0.3, display_name='p3'), } @@ -99,12 +108,12 @@ def test_setitem_with_easyscience_object(setup_pars): n_before = len(coll) old_item = coll[0] - new_item = Parameter('replacement', 99.0) + new_item = Parameter(99.0, display_name='replacement') coll[0] = new_item assert len(coll) == n_before - assert coll[0].name == 'replacement' + assert coll[0].display_name == 'replacement' assert coll[0].value == 99.0 # Old item should be removed from the graph assert old_item.unique_name not in global_object.map.get_edges(coll) @@ -114,12 +123,13 @@ def test_setitem_with_easyscience_object(setup_pars): # __getitem__ with duplicate names returns a new CollectionBase # --------------------------------------------------------------------------- +@_string_indexing_unsupported def test_getitem_duplicate_names_returns_collection(setup_pars): """When multiple items share the same name, __getitem__ returns a sub-collection.""" name = setup_pars.pop('name') # Add two items with the same display name - p1 = Parameter('same_name', 1.0) - p2 = Parameter('same_name', 2.0) + p1 = Parameter(1.0, display_name='same_name') + p2 = Parameter(2.0, display_name='same_name') coll = CollectionBase(name, p1, p2) result = coll['same_name'] @@ -127,6 +137,7 @@ def test_getitem_duplicate_names_returns_collection(setup_pars): assert len(result) == 2 +@_string_indexing_unsupported def test_getitem_nonexistent_name_raises(setup_pars): """Looking up a nonexistent name raises IndexError.""" name = setup_pars.pop('name') @@ -146,10 +157,10 @@ def test_insert_at_specific_index(setup_pars): coll = CollectionBase(name, **setup_pars) n_before = len(coll) - new_item = Parameter('inserted', 42.0) + new_item = Parameter(42.0, display_name='inserted') coll.insert(2, new_item) assert len(coll) == n_before + 1 - assert coll[2].name == 'inserted' + assert coll[2].display_name == 'inserted' assert coll[2].value == 42.0 diff --git a/tests/unit/legacy/test_obj_base.py b/tests/unit/legacy/test_obj_base.py index fc33c424..8735a440 100644 --- a/tests/unit/legacy/test_obj_base.py +++ b/tests/unit/legacy/test_obj_base.py @@ -64,7 +64,7 @@ class A(ObjBase): def __init__(self, a: Parameter): super().__init__('A', a=a) - p1 = Parameter('a', 1.0) + p1 = Parameter(1.0, display_name='a') a = A(p1) # Attach a mock interface @@ -72,7 +72,7 @@ def __init__(self, a: Parameter): a.interface = mock_iface # Replace the parameter — should trigger generate_bindings via __setattr__ - p2 = Parameter('a', 2.0) + p2 = Parameter(2.0, display_name='a') a.a = p2 mock_iface.generate_bindings.assert_called() @@ -89,14 +89,14 @@ class A(ObjBase): def __init__(self, p: Parameter): super().__init__('A', p=p) - p1 = Parameter('p', 1.0) + p1 = Parameter(1.0, display_name='p') a = A(p1) graph = global_object.map edges_before = set(graph.get_edges(a)) # Replace the parameter with a new one - p2 = Parameter('p', 2.0) + p2 = Parameter(2.0, display_name='p') a.p = p2 edges_after = set(graph.get_edges(a)) @@ -113,7 +113,7 @@ def test_setter_sets_descriptor_value(): """When setting a Descriptor via the logged property, the descriptor's value is updated.""" from easyscience import DescriptorNumber - d = DescriptorNumber('d1', 0.5) + d = DescriptorNumber(0.5, display_name='d1') obj = ObjBase('test', d1=d) obj.d1 = 3.14 assert obj.d1.value == 3.14 diff --git a/tests/unit/models/test_polynomial.py b/tests/unit/models/test_polynomial.py index 5376d03e..67b18ddb 100644 --- a/tests/unit/models/test_polynomial.py +++ b/tests/unit/models/test_polynomial.py @@ -55,16 +55,16 @@ def test_Polynomial_default_initialization(clear): def test_Polynomial_with_Parameter_objects(clear): """Test Polynomial with Parameter objects as coefficients.""" - p0 = Parameter('c0', value=1.0) - p1 = Parameter('c1', value=2.0) - p2 = Parameter('c2', value=3.0) + p0 = Parameter(value=1.0, display_name='c0') + p1 = Parameter(value=2.0, display_name='c1') + p2 = Parameter(value=3.0, display_name='c2') poly = Polynomial(coefficients=[p0, p1, p2]) assert len(poly.coefficients) == 3 - assert poly.coefficients[0].name == 'c0' - assert poly.coefficients[1].name == 'c1' - assert poly.coefficients[2].name == 'c2' + assert poly.coefficients[0].display_name == 'c0' + assert poly.coefficients[1].display_name == 'c1' + assert poly.coefficients[2].display_name == 'c2' assert poly.coefficients[0].value == 1.0 assert poly.coefficients[1].value == 2.0 assert poly.coefficients[2].value == 3.0 @@ -78,14 +78,14 @@ def test_Polynomial_with_Parameter_objects(clear): def test_Polynomial_with_mixed_coefficients(clear): """Test Polynomial with mixed float and Parameter coefficients.""" - p0 = Parameter('c0', value=5.0) + p0 = Parameter(value=5.0, display_name='c0') poly = Polynomial(coefficients=[p0, 2.0, 1.0]) assert len(poly.coefficients) == 3 - assert poly.coefficients[0].name == 'c0' - assert poly.coefficients[1].name == 'c1' - assert poly.coefficients[2].name == 'c2' + assert poly.coefficients[0].display_name == 'c0' + assert poly.coefficients[1].display_name == 'c1' + assert poly.coefficients[2].display_name == 'c2' # polyval([5.0, 2.0, 1.0], x) = 5.0*x^2 + 2.0*x + 1.0 x = np.array([1, 2, 3]) @@ -96,9 +96,9 @@ def test_Polynomial_with_mixed_coefficients(clear): def test_Polynomial_with_CollectionBase(clear): """Test Polynomial initialized with a CollectionBase.""" collection = CollectionBase('coeffs') - collection.append(Parameter('c0', value=1.0)) - collection.append(Parameter('c1', value=2.0)) - collection.append(Parameter('c2', value=3.0)) + collection.append(Parameter(value=1.0, display_name='c0')) + collection.append(Parameter(value=2.0, display_name='c1')) + collection.append(Parameter(value=3.0, display_name='c2')) poly = Polynomial(coefficients=collection) diff --git a/tests/unit/variable/test_descriptor_any_type.py b/tests/unit/variable/test_descriptor_any_type.py index 12db376a..39fbf325 100644 --- a/tests/unit/variable/test_descriptor_any_type.py +++ b/tests/unit/variable/test_descriptor_any_type.py @@ -12,7 +12,6 @@ class TestDescriptorAnyType: @pytest.fixture def descriptor(self): descriptor = DescriptorAnyType( - name='name', value='string', description='description', url='url', @@ -29,7 +28,6 @@ def test_init(self, descriptor: DescriptorAnyType): assert descriptor._value == 'string' # From super - assert descriptor._name == 'name' assert descriptor._description == 'description' assert descriptor._url == 'url' assert descriptor._display_name == 'display_name' @@ -71,7 +69,7 @@ def test_repr(self, descriptor: DescriptorAnyType, value, expected): print(repr_str) # Expect - assert repr_str == f"" + assert repr_str == f"" def test_copy(self, descriptor: DescriptorAnyType): # When Then diff --git a/tests/unit/variable/test_descriptor_array.py b/tests/unit/variable/test_descriptor_array.py index 36ede2e3..cafe0e66 100644 --- a/tests/unit/variable/test_descriptor_array.py +++ b/tests/unit/variable/test_descriptor_array.py @@ -16,7 +16,6 @@ class TestDescriptorArray: @pytest.fixture def descriptor(self): descriptor = DescriptorArray( - name='name', value=[[1.0, 2.0], [3.0, 4.0]], unit='m', variance=[[0.1, 0.2], [0.3, 0.4]], @@ -29,7 +28,6 @@ def descriptor(self): @pytest.fixture def descriptor_dimensionless(self): descriptor = DescriptorArray( - name='name', value=[[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]], unit='dimensionless', variance=[[0.1, 0.2], [0.3, 0.4], [0.5, 0.6]], @@ -50,7 +48,6 @@ def test_init(self, descriptor: DescriptorArray): assert np.array_equal(descriptor._array.variances, np.array([[0.1, 0.2], [0.3, 0.4]])) # From super - assert descriptor._name == 'name' assert descriptor._description == 'description' assert descriptor._url == 'url' assert descriptor._display_name == 'display_name' @@ -58,7 +55,6 @@ def test_init(self, descriptor: DescriptorArray): def test_init_sc_unit(self): # When Then descriptor = DescriptorArray( - name='name', value=[[1.0, 2.0], [3.0, 4.0]], unit=sc.units.Unit('m'), variance=[[0.1, 0.2], [0.3, 0.4]], @@ -76,7 +72,6 @@ def test_init_sc_unit_unknown(self): # When Then Expect with pytest.raises(UnitError): DescriptorArray( - name='name', value=[[1.0, 2.0], [3.0, 4.0]], unit='unknown', variance=[[0.1, 0.2], [0.3, 0.4]], @@ -92,7 +87,6 @@ def test_init_value_type_exception(self, value): # Then Expect with pytest.raises(TypeError): DescriptorArray( - name='name', value=value, unit='m', variance=[[0.1, 0.2], [0.3, 0.4]], @@ -107,7 +101,6 @@ def test_init_variance_exception(self): # Then Expect with pytest.raises(ValueError): DescriptorArray( - name='name', value=[[1.0, 2.0], [3.0, 4.0]], unit='m', variance=variance, @@ -121,7 +114,7 @@ def test_from_scipp(self): # When full_value = sc.array(dims=['row', 'column'], values=[[1, 2], [3, 4]], unit='m') # Then - descriptor = DescriptorArray.from_scipp(name='name', full_value=full_value) + descriptor = DescriptorArray.from_scipp(display_name='name', full_value=full_value) # Expect assert np.array_equal(descriptor._array.values, [[1, 2], [3, 4]]) @@ -207,7 +200,7 @@ def test_repr(self, descriptor: DescriptorArray): # Expect assert ( repr_str - == "" + == "" ) def test_copy(self, descriptor: DescriptorArray): @@ -226,7 +219,9 @@ def test_copy(self, descriptor: DescriptorArray): ) def test_base_unit(self, unit_string, expected): # When - descriptor = DescriptorArray(name='name', value=[[1.0, 2.0], [3.0, 4.0]], unit=unit_string) + descriptor = DescriptorArray( + display_name='name', value=[[1.0, 2.0], [3.0, 4.0]], unit=unit_string + ) # Then base_unit = descriptor._base_unit() @@ -238,36 +233,47 @@ def test_base_unit(self, unit_string, expected): 'test, expected, raises_warning', [ ( - DescriptorNumber('test', 2, 'm', 0.01), + DescriptorNumber(2, unit='m', variance=0.01, display_name='test'), DescriptorArray( - 'test + name', [[3.0, 4.0], [5.0, 6.0]], 'm', [[0.11, 0.21], [0.31, 0.41]] + [[3.0, 4.0], [5.0, 6.0]], + unit='m', + variance=[[0.11, 0.21], [0.31, 0.41]], + display_name='test + name', ), True, ), ( - DescriptorNumber('test', 1, 'cm', 10), + DescriptorNumber(1, unit='cm', variance=10, display_name='test'), DescriptorArray( - 'test + name', [[1.01, 2.01], [3.01, 4.01]], - 'm', - [[0.1010, 0.2010], [0.3010, 0.4010]], + unit='m', + variance=[[0.1010, 0.2010], [0.3010, 0.4010]], + display_name='test + name', ), True, ), ( - DescriptorArray('test', [[2.0, 3.0], [4.0, -5.0]], 'cm', [[1.0, 2.0], [3.0, 4.0]]), DescriptorArray( - 'test + name', + [[2.0, 3.0], [4.0, -5.0]], + unit='cm', + variance=[[1.0, 2.0], [3.0, 4.0]], + display_name='test', + ), + DescriptorArray( [[1.02, 2.03], [3.04, 3.95]], - 'm', - [[0.1001, 0.2002], [0.3003, 0.4004]], + unit='m', + variance=[[0.1001, 0.2002], [0.3003, 0.4004]], + display_name='test + name', ), False, ), ( - DescriptorArray('test', [[2, 3], [4, -5]], 'cm'), + DescriptorArray([[2, 3], [4, -5]], unit='cm', display_name='test'), DescriptorArray( - 'test + name', [[1.02, 2.03], [3.04, 3.95]], 'm', [[0.1, 0.2], [0.3, 0.4]] + [[1.02, 2.03], [3.04, 3.95]], + unit='m', + variance=[[0.1, 0.2], [0.3, 0.4]], + display_name='test + name', ), False, ), @@ -290,7 +296,6 @@ def test_addition(self, descriptor: DescriptorArray, test, expected, raises_warn result = descriptor + test # Expect assert type(result) == DescriptorArray - assert result.name == result.unique_name assert np.array_equal(result.value, expected.value) assert result.unit == expected.unit assert np.allclose(result.variance, expected.variance) @@ -302,19 +307,19 @@ def test_addition(self, descriptor: DescriptorArray, test, expected, raises_warn ( [[2.0, 3.0], [4.0, -5.0], [6.0, -8.0]], DescriptorArray( - 'test', [[3.0, 5.0], [7.0, -1.0], [11.0, -2.0]], - 'dimensionless', - [[0.1, 0.2], [0.3, 0.4], [0.5, 0.6]], + unit='dimensionless', + variance=[[0.1, 0.2], [0.3, 0.4], [0.5, 0.6]], + display_name='test', ), ), ( 1, DescriptorArray( - 'test', [[2.0, 3.0], [4.0, 5.0], [6.0, 7.0]], - 'dimensionless', - [[0.1, 0.2], [0.3, 0.4], [0.5, 0.6]], + unit='dimensionless', + variance=[[0.1, 0.2], [0.3, 0.4], [0.5, 0.6]], + display_name='test', ), ), ], @@ -335,39 +340,47 @@ def test_addition_dimensionless( 'test, expected, raises_warning', [ ( - DescriptorNumber('test', 2, 'm', 0.01), + DescriptorNumber(2, unit='m', variance=0.01, display_name='test'), DescriptorArray( - 'test + name', [[3.0, 4.0], [5.0, 6.0]], 'm', [[0.11, 0.21], [0.31, 0.41]] + [[3.0, 4.0], [5.0, 6.0]], + unit='m', + variance=[[0.11, 0.21], [0.31, 0.41]], + display_name='test + name', ), True, ), ( - DescriptorNumber('test', 1, 'cm', 10), + DescriptorNumber(1, unit='cm', variance=10, display_name='test'), DescriptorArray( - 'test + name', [[101.0, 201.0], [301.0, 401.0]], - 'cm', - [[1010.0, 2010.0], [3010.0, 4010.0]], + unit='cm', + variance=[[1010.0, 2010.0], [3010.0, 4010.0]], + display_name='test + name', ), True, ), ( - DescriptorArray('test', [[2.0, 3.0], [4.0, -5.0]], 'cm', [[1.0, 2.0], [3.0, 4.0]]), DescriptorArray( - 'test + name', + [[2.0, 3.0], [4.0, -5.0]], + unit='cm', + variance=[[1.0, 2.0], [3.0, 4.0]], + display_name='test', + ), + DescriptorArray( [[102.0, 203.0], [304.0, 395.0]], - 'cm', - [[1001.0, 2002.0], [3003.0, 4004.0]], + unit='cm', + variance=[[1001.0, 2002.0], [3003.0, 4004.0]], + display_name='test + name', ), False, ), ( - DescriptorArray('test', [[2, 3], [4, -5]], 'cm'), + DescriptorArray([[2, 3], [4, -5]], unit='cm', display_name='test'), DescriptorArray( - 'test + name', [[102.0, 203.0], [304.0, 395.0]], - 'cm', - [[1000.0, 2000.0], [3000.0, 4000.0]], + unit='cm', + variance=[[1000.0, 2000.0], [3000.0, 4000.0]], + display_name='test + name', ), False, ), @@ -390,7 +403,6 @@ def test_reverse_addition(self, descriptor: DescriptorArray, test, expected, rai result = test + descriptor # Expect assert type(result) == DescriptorArray - assert result.name == result.unique_name assert np.array_equal(result.value, expected.value) assert result.unit == expected.unit assert np.allclose(result.variance, expected.variance) @@ -402,19 +414,19 @@ def test_reverse_addition(self, descriptor: DescriptorArray, test, expected, rai ( [[2.0, 3.0], [4.0, -5.0], [6.0, -8.0]], DescriptorArray( - 'test', [[3.0, 5.0], [7.0, -1.0], [11.0, -2.0]], - 'dimensionless', - [[0.1, 0.2], [0.3, 0.4], [0.5, 0.6]], + unit='dimensionless', + variance=[[0.1, 0.2], [0.3, 0.4], [0.5, 0.6]], + display_name='test', ), ), ( 1, DescriptorArray( - 'test', [[2.0, 3.0], [4.0, 5.0], [6.0, 7.0]], - 'dimensionless', - [[0.1, 0.2], [0.3, 0.4], [0.5, 0.6]], + unit='dimensionless', + variance=[[0.1, 0.2], [0.3, 0.4], [0.5, 0.6]], + display_name='test', ), ), ], @@ -435,39 +447,47 @@ def test_reverse_addition_dimensionless( 'test, expected, raises_warning', [ ( - DescriptorNumber('test', 2, 'm', 0.01), + DescriptorNumber(2, unit='m', variance=0.01, display_name='test'), DescriptorArray( - 'test + name', [[-1.0, 0.0], [1.0, 2.0]], 'm', [[0.11, 0.21], [0.31, 0.41]] + [[-1.0, 0.0], [1.0, 2.0]], + unit='m', + variance=[[0.11, 0.21], [0.31, 0.41]], + display_name='test + name', ), True, ), ( - DescriptorNumber('test', 1, 'cm', 10), + DescriptorNumber(1, unit='cm', variance=10, display_name='test'), DescriptorArray( - 'test + name', [[0.99, 1.99], [2.99, 3.99]], - 'm', - [[0.1010, 0.2010], [0.3010, 0.4010]], + unit='m', + variance=[[0.1010, 0.2010], [0.3010, 0.4010]], + display_name='test + name', ), True, ), ( - DescriptorArray('test', [[2.0, 3.0], [4.0, -5.0]], 'cm', [[1.0, 2.0], [3.0, 4.0]]), DescriptorArray( - 'test + name', + [[2.0, 3.0], [4.0, -5.0]], + unit='cm', + variance=[[1.0, 2.0], [3.0, 4.0]], + display_name='test', + ), + DescriptorArray( [[0.98, 1.97], [2.96, 4.05]], - 'm', - [[0.1001, 0.2002], [0.3003, 0.4004]], + unit='m', + variance=[[0.1001, 0.2002], [0.3003, 0.4004]], + display_name='test + name', ), False, ), ( - DescriptorArray('test', [[2, 3], [4, -5]], 'cm'), + DescriptorArray([[2, 3], [4, -5]], unit='cm', display_name='test'), DescriptorArray( - 'test + name', [[0.98, 1.97], [2.96, 4.05]], - 'm', - [[0.100, 0.200], [0.300, 0.400]], + unit='m', + variance=[[0.100, 0.200], [0.300, 0.400]], + display_name='test + name', ), False, ), @@ -490,7 +510,6 @@ def test_subtraction(self, descriptor: DescriptorArray, test, expected, raises_w result = descriptor - test # Expect assert type(result) == DescriptorArray - assert result.name == result.unique_name assert np.array_equal(result.value, expected.value) assert result.unit == expected.unit assert np.allclose(result.variance, expected.variance) @@ -502,19 +521,19 @@ def test_subtraction(self, descriptor: DescriptorArray, test, expected, raises_w ( [[2.0, 3.0], [4.0, -5.0], [6.0, -8.0]], DescriptorArray( - 'test', [[-1.0, -1.0], [-1.0, 9.0], [-1, 14.0]], - 'dimensionless', - [[0.1, 0.2], [0.3, 0.4], [0.5, 0.6]], + unit='dimensionless', + variance=[[0.1, 0.2], [0.3, 0.4], [0.5, 0.6]], + display_name='test', ), ), ( 1, DescriptorArray( - 'test', [[0.0, 1.0], [2.0, 3.0], [4.0, 5.0]], - 'dimensionless', - [[0.1, 0.2], [0.3, 0.4], [0.5, 0.6]], + unit='dimensionless', + variance=[[0.1, 0.2], [0.3, 0.4], [0.5, 0.6]], + display_name='test', ), ), ], @@ -535,39 +554,47 @@ def test_subtraction_dimensionless( 'test, expected, raises_warning', [ ( - DescriptorNumber('test', 2, 'm', 0.01), + DescriptorNumber(2, unit='m', variance=0.01, display_name='test'), DescriptorArray( - 'test + name', [[1.0, 0.0], [-1.0, -2.0]], 'm', [[0.11, 0.21], [0.31, 0.41]] + [[1.0, 0.0], [-1.0, -2.0]], + unit='m', + variance=[[0.11, 0.21], [0.31, 0.41]], + display_name='test + name', ), True, ), ( - DescriptorNumber('test', 1, 'cm', 10), + DescriptorNumber(1, unit='cm', variance=10, display_name='test'), DescriptorArray( - 'test + name', [[-99.0, -199.0], [-299.0, -399.0]], - 'cm', - [[1010.0, 2010.0], [3010.0, 4010.0]], + unit='cm', + variance=[[1010.0, 2010.0], [3010.0, 4010.0]], + display_name='test + name', ), True, ), ( - DescriptorArray('test', [[2.0, 3.0], [4.0, -5.0]], 'cm', [[1.0, 2.0], [3.0, 4.0]]), DescriptorArray( - 'test + name', + [[2.0, 3.0], [4.0, -5.0]], + unit='cm', + variance=[[1.0, 2.0], [3.0, 4.0]], + display_name='test', + ), + DescriptorArray( [[-98.0, -197.0], [-296.0, -405.0]], - 'cm', - [[1001.0, 2002.0], [3003.0, 4004.0]], + unit='cm', + variance=[[1001.0, 2002.0], [3003.0, 4004.0]], + display_name='test + name', ), False, ), ( - DescriptorArray('test', [[2, 3], [4, -5]], 'cm'), + DescriptorArray([[2, 3], [4, -5]], unit='cm', display_name='test'), DescriptorArray( - 'test + name', [[-98.0, -197.0], [-296.0, -405.0]], - 'cm', - [[1000.0, 2000.0], [3000.0, 4000.0]], + unit='cm', + variance=[[1000.0, 2000.0], [3000.0, 4000.0]], + display_name='test + name', ), False, ), @@ -592,7 +619,6 @@ def test_reverse_subtraction( result = test - descriptor # Expect assert type(result) == DescriptorArray - assert result.name == result.unique_name assert np.array_equal(result.value, expected.value) assert result.unit == expected.unit assert np.allclose(result.variance, expected.variance) @@ -604,19 +630,19 @@ def test_reverse_subtraction( ( [[2.0, 3.0], [4.0, -5.0], [6.0, -8.0]], DescriptorArray( - 'test', [[1.0, 1.0], [1.0, -9.0], [1.0, -14.0]], - 'dimensionless', - [[0.1, 0.2], [0.3, 0.4], [0.5, 0.6]], + unit='dimensionless', + variance=[[0.1, 0.2], [0.3, 0.4], [0.5, 0.6]], + display_name='test', ), ), ( 1, DescriptorArray( - 'test', [[0.0, -1.0], [-2.0, -3.0], [-4.0, -5.0]], - 'dimensionless', - [[0.1, 0.2], [0.3, 0.4], [0.5, 0.6]], + unit='dimensionless', + variance=[[0.1, 0.2], [0.3, 0.4], [0.5, 0.6]], + display_name='test', ), ), ], @@ -637,69 +663,80 @@ def test_reverse_subtraction_dimensionless( 'test, expected, raises_warning', [ ( - DescriptorNumber('test', 2, 'm', 0.01), + DescriptorNumber(2, unit='m', variance=0.01, display_name='test'), DescriptorArray( - 'test * name', [[2.0, 4.0], [6.0, 8.0]], 'm^2', [[0.41, 0.84], [1.29, 1.76]] + [[2.0, 4.0], [6.0, 8.0]], + unit='m^2', + variance=[[0.41, 0.84], [1.29, 1.76]], + display_name='test * name', ), True, ), ( - DescriptorNumber('test', 1, 'cm', 10), + DescriptorNumber(1, unit='cm', variance=10, display_name='test'), DescriptorArray( - 'test * name', [[0.01, 0.02], [0.03, 0.04]], - 'm^2', - [[0.00101, 0.00402], [0.00903, 0.01604]], + unit='m^2', + variance=[[0.00101, 0.00402], [0.00903, 0.01604]], + display_name='test * name', ), True, ), ( - DescriptorNumber('test', 1, 'kg', 10), + DescriptorNumber(1, unit='kg', variance=10, display_name='test'), DescriptorArray( - 'test * name', [[1.0, 2.0], [3.0, 4.0]], 'kg*m', [[10.1, 40.2], [90.3, 160.4]] + [[1.0, 2.0], [3.0, 4.0]], + unit='kg*m', + variance=[[10.1, 40.2], [90.3, 160.4]], + display_name='test * name', ), True, ), ( - DescriptorArray('test', [[2.0, 3.0], [4.0, -5.0]], 'cm', [[1.0, 2.0], [3.0, 4.0]]), DescriptorArray( - 'test * name', + [[2.0, 3.0], [4.0, -5.0]], + unit='cm', + variance=[[1.0, 2.0], [3.0, 4.0]], + display_name='test', + ), + DescriptorArray( [[0.02, 0.06], [0.12, -0.2]], - 'm^2', - [[0.00014, 0.00098], [0.00318, 0.0074]], + unit='m^2', + variance=[[0.00014, 0.00098], [0.00318, 0.0074]], + display_name='test * name', ), False, ), ( - DescriptorArray('test', [[2, 3], [4, -5]], 'cm'), + DescriptorArray([[2, 3], [4, -5]], unit='cm', display_name='test'), DescriptorArray( - 'test * name', [[0.02, 0.06], [0.12, -0.2]], - 'm^2', - [ + unit='m^2', + variance=[ [0.1 * 2**2 * 1e-4, 0.2 * 3**2 * 1e-4], [0.3 * 4**2 * 1e-4, 0.4 * 5**2 * 1e-4], ], + display_name='test * name', ), False, ), ( [[2.0, 3.0], [4.0, -5.0]], DescriptorArray( - 'test * name', [[2.0, 6.0], [12.0, -20.0]], - 'm', - [[0.1 * 2**2, 0.2 * 3**2], [0.3 * 4**2, 0.4 * 5**2]], + unit='m', + variance=[[0.1 * 2**2, 0.2 * 3**2], [0.3 * 4**2, 0.4 * 5**2]], + display_name='test * name', ), False, ), ( 2.0, DescriptorArray( - 'test * name', [[2.0, 4.0], [6.0, 8.0]], - 'm', - [[0.1 * 2**2, 0.2 * 2**2], [0.3 * 2**2, 0.4 * 2**2]], + unit='m', + variance=[[0.1 * 2**2, 0.2 * 2**2], [0.3 * 2**2, 0.4 * 2**2]], + display_name='test * name', ), False, ), @@ -725,7 +762,6 @@ def test_multiplication(self, descriptor: DescriptorArray, test, expected, raise result = descriptor * test # Expect assert type(result) == DescriptorArray - assert result.name == result.unique_name assert np.array_equal(result.value, expected.value) assert result.unit == expected.unit assert np.allclose(result.variance, expected.variance) @@ -737,19 +773,19 @@ def test_multiplication(self, descriptor: DescriptorArray, test, expected, raise ( [[2.0, 3.0], [4.0, -5.0], [6.0, -8.0]], DescriptorArray( - 'test', [[2.0, 6.0], [12.0, -20.0], [30.0, -48.0]], - 'dimensionless', - [[0.4, 1.8], [4.8, 10.0], [18.0, 38.4]], + unit='dimensionless', + variance=[[0.4, 1.8], [4.8, 10.0], [18.0, 38.4]], + display_name='test', ), ), ( 1.5, DescriptorArray( - 'test', [[1.5, 3.0], [4.5, 6.0], [7.5, 9.0]], - 'dimensionless', - [[0.225, 0.45], [0.675, 0.9], [1.125, 1.35]], + unit='dimensionless', + variance=[[0.225, 0.45], [0.675, 0.9], [1.125, 1.35]], + display_name='test', ), ), ], @@ -770,66 +806,80 @@ def test_multiplication_dimensionless( 'test, expected, raises_warning', [ ( - DescriptorNumber('test', 2, 'm', 0.01), + DescriptorNumber(2, unit='m', variance=0.01, display_name='test'), DescriptorArray( - 'test * name', [[2.0, 4.0], [6.0, 8.0]], 'm^2', [[0.41, 0.84], [1.29, 1.76]] + [[2.0, 4.0], [6.0, 8.0]], + unit='m^2', + variance=[[0.41, 0.84], [1.29, 1.76]], + display_name='test * name', ), True, ), ( - DescriptorNumber('test', 1, 'cm', 10), + DescriptorNumber(1, unit='cm', variance=10, display_name='test'), DescriptorArray( - 'test * name', [[100.0, 200.0], [300.0, 400.0]], - 'cm^2', - [[101000.0, 402000.0], [903000.0, 1604000.0]], + unit='cm^2', + variance=[[101000.0, 402000.0], [903000.0, 1604000.0]], + display_name='test * name', ), True, ), ( - DescriptorNumber('test', 1, 'kg', 10), + DescriptorNumber(1, unit='kg', variance=10, display_name='test'), DescriptorArray( - 'test * name', [[1.0, 2.0], [3.0, 4.0]], 'kg*m', [[10.1, 40.2], [90.3, 160.4]] + [[1.0, 2.0], [3.0, 4.0]], + unit='kg*m', + variance=[[10.1, 40.2], [90.3, 160.4]], + display_name='test * name', ), True, ), ( - DescriptorArray('test', [[2.0, 3.0], [4.0, -5.0]], 'cm', [[1.0, 2.0], [3.0, 4.0]]), DescriptorArray( - 'test * name', + [[2.0, 3.0], [4.0, -5.0]], + unit='cm', + variance=[[1.0, 2.0], [3.0, 4.0]], + display_name='test', + ), + DescriptorArray( [[200.0, 600.0], [1200.0, -2000.0]], - 'cm^2', - [[14000.0, 98000.0], [318000.0, 740000.0]], + unit='cm^2', + variance=[[14000.0, 98000.0], [318000.0, 740000.0]], + display_name='test * name', ), False, ), ( - DescriptorArray('test', [[2, 3], [4, -5]], 'cm'), + DescriptorArray([[2, 3], [4, -5]], unit='cm', display_name='test'), DescriptorArray( - 'test * name', [[200.0, 600.0], [1200.0, -2000.0]], - 'cm^2', - [[0.1 * 2**2 * 1e4, 0.2 * 3**2 * 1e4], [0.3 * 4**2 * 1e4, 0.4 * 5**2 * 1e4]], + unit='cm^2', + variance=[ + [0.1 * 2**2 * 1e4, 0.2 * 3**2 * 1e4], + [0.3 * 4**2 * 1e4, 0.4 * 5**2 * 1e4], + ], + display_name='test * name', ), False, ), ( [[2.0, 3.0], [4.0, -5.0]], DescriptorArray( - 'test * name', [[2.0, 6.0], [12.0, -20.0]], - 'm', - [[0.1 * 2**2, 0.2 * 3**2], [0.3 * 4**2, 0.4 * 5**2]], + unit='m', + variance=[[0.1 * 2**2, 0.2 * 3**2], [0.3 * 4**2, 0.4 * 5**2]], + display_name='test * name', ), False, ), ( 2.0, DescriptorArray( - 'test * name', [[2.0, 4.0], [6.0, 8.0]], - 'm', - [[0.1 * 2**2, 0.2 * 2**2], [0.3 * 2**2, 0.4 * 2**2]], + unit='m', + variance=[[0.1 * 2**2, 0.2 * 2**2], [0.3 * 2**2, 0.4 * 2**2]], + display_name='test * name', ), False, ), @@ -857,7 +907,6 @@ def test_reverse_multiplication( result = test * descriptor # Expect assert type(result) == DescriptorArray - assert result.name == result.unique_name assert np.array_equal(result.value, expected.value) assert result.unit == expected.unit assert np.allclose(result.variance, expected.variance) @@ -869,19 +918,19 @@ def test_reverse_multiplication( ( [[2.0, 3.0], [4.0, -5.0], [6.0, -8.0]], DescriptorArray( - 'test', [[2.0, 6.0], [12.0, -20.0], [30.0, -48.0]], - 'dimensionless', - [[0.4, 1.8], [4.8, 10.0], [18.0, 38.4]], + unit='dimensionless', + variance=[[0.4, 1.8], [4.8, 10.0], [18.0, 38.4]], + display_name='test', ), ), ( 1.5, DescriptorArray( - 'test', [[1.5, 3.0], [4.5, 6.0], [7.5, 9.0]], - 'dimensionless', - [[0.225, 0.45], [0.675, 0.9], [1.125, 1.35]], + unit='dimensionless', + variance=[[0.225, 0.45], [0.675, 0.9], [1.125, 1.35]], + display_name='test', ), ), ], @@ -902,12 +951,11 @@ def test_reverse_multiplication_dimensionless( 'test, expected, raises_warning', [ ( - DescriptorNumber('test', 2, 'm', 0.01), + DescriptorNumber(2, unit='m', variance=0.01, display_name='test'), DescriptorArray( - 'name / test', [[1.0 / 2.0, 2.0 / 2.0], [3.0 / 2.0, 4.0 / 2.0]], - 'dimensionless', - [ + unit='dimensionless', + variance=[ [ (0.1 + 0.01 * 1.0**2 / 2.0**2) / 2.0**2, (0.2 + 0.01 * 2.0**2 / 2.0**2) / 2.0**2, @@ -917,16 +965,16 @@ def test_reverse_multiplication_dimensionless( (0.4 + 0.01 * 4.0**2 / 2.0**2) / 2.0**2, ], ], + display_name='name / test', ), True, ), ( - DescriptorNumber('test', 1, 'cm', 10), + DescriptorNumber(1, unit='cm', variance=10, display_name='test'), DescriptorArray( - 'name / test', [[100.0, 200.0], [300.0, 400.0]], - 'dimensionless', - [ + unit='dimensionless', + variance=[ [ (0.1 + 10 * 1.0**2 / 1.0**2) / 1.0**2 * 1e4, (0.2 + 10 * 2.0**2 / 1.0**2) / 1.0**2 * 1e4, @@ -936,16 +984,16 @@ def test_reverse_multiplication_dimensionless( (0.4 + 10 * 4.0**2 / 1.0**2) / 1.0**2 * 1e4, ], ], + display_name='name / test', ), True, ), ( - DescriptorNumber('test', 1, 'kg', 10), + DescriptorNumber(1, unit='kg', variance=10, display_name='test'), DescriptorArray( - 'name / test', [[1.0, 2.0], [3.0, 4.0]], - 'm/kg', - [ + unit='m/kg', + variance=[ [ (0.1 + 10 * 1.0**2 / 1.0**2) / 1.0**2, (0.2 + 10 * 2.0**2 / 1.0**2) / 1.0**2, @@ -955,18 +1003,21 @@ def test_reverse_multiplication_dimensionless( (0.4 + 10 * 4.0**2 / 1.0**2) / 1.0**2, ], ], + display_name='name / test', ), True, ), ( DescriptorArray( - 'test', [[2.0, 3.0], [4.0, -5.0]], 'cm^2', [[1.0, 2.0], [3.0, 4.0]] + [[2.0, 3.0], [4.0, -5.0]], + unit='cm^2', + variance=[[1.0, 2.0], [3.0, 4.0]], + display_name='test', ), DescriptorArray( - 'name / test', [[1 / 2 * 1e4, 2 / 3 * 1e4], [3.0 / 4.0 * 1e4, -4.0 / 5.0 * 1e4]], - '1/m', - [ + unit='1/m', + variance=[ [ (0.1 + 1.0 * 1.0**2 / 2.0**2) / 2.0**2 * 1e8, (0.2 + 2.0 * 2.0**2 / 3.0**2) / 3.0**2 * 1e8, @@ -976,39 +1027,40 @@ def test_reverse_multiplication_dimensionless( (0.4 + 4.0 * 4.0**2 / 5.0**2) / 5.0**2 * 1e8, ], ], + display_name='name / test', ), False, ), ( - DescriptorArray('test', [[2, 3], [4, -5]], 'cm^2'), + DescriptorArray([[2, 3], [4, -5]], unit='cm^2', display_name='test'), DescriptorArray( - 'name / test', [[1 / 2 * 1e4, 2 / 3 * 1e4], [3.0 / 4.0 * 1e4, -4.0 / 5.0 * 1e4]], - '1/m', - [ + unit='1/m', + variance=[ [(0.1) / 2.0**2 * 1e8, (0.2) / 3.0**2 * 1e8], [(0.3) / 4.0**2 * 1e8, (0.4) / 5.0**2 * 1e8], ], + display_name='name / test', ), False, ), ( [[2.0, 3.0], [4.0, -5.0]], DescriptorArray( - 'name / name', [[0.5, 2.0 / 3.0], [3.0 / 4.0, -4 / 5]], - 'm', - [[0.1 / 2**2, 0.2 / 3.0**2], [0.3 / 4**2, 0.4 / 5.0**2]], + unit='m', + variance=[[0.1 / 2**2, 0.2 / 3.0**2], [0.3 / 4**2, 0.4 / 5.0**2]], + display_name='name / name', ), False, ), ( 2.0, DescriptorArray( - 'name / test', [[0.5, 1.0], [3.0 / 2.0, 2.0]], - 'm', - [[0.1 / 2.0**2, 0.2 / 2.0**2], [0.3 / 2.0**2, 0.4 / 2.0**2]], + unit='m', + variance=[[0.1 / 2.0**2, 0.2 / 2.0**2], [0.3 / 2.0**2, 0.4 / 2.0**2]], + display_name='name / test', ), False, ), @@ -1034,7 +1086,6 @@ def test_division(self, descriptor: DescriptorArray, test, expected, raises_warn result = descriptor / test # Expect assert type(result) == DescriptorArray - assert result.name == result.unique_name assert np.allclose(result.value, expected.value) assert result.unit == expected.unit assert np.allclose(result.variance, expected.variance) @@ -1046,27 +1097,27 @@ def test_division(self, descriptor: DescriptorArray, test, expected, raises_warn ( [[2.0, 3.0], [4.0, -5.0], [6.0, -8.0]], DescriptorArray( - 'test', [[1.0 / 2.0, 2.0 / 3.0], [3.0 / 4.0, -4.0 / 5.0], [5.0 / 6.0, -6.0 / 8.0]], - 'dimensionless', - [ + unit='dimensionless', + variance=[ [0.1 / 2.0**2, 0.2 / 3.0**2], [0.3 / 4.0**2, 0.4 / 5.0**2], [0.5 / 6.0**2, 0.6 / 8.0**2], ], + display_name='test', ), ), ( 2, DescriptorArray( - 'test', [[1.0 / 2.0, 2.0 / 2.0], [3.0 / 2.0, 4.0 / 2.0], [5.0 / 2.0, 6.0 / 2.0]], - 'dimensionless', - [ + unit='dimensionless', + variance=[ [0.1 / 2.0**2, 0.2 / 2.0**2], [0.3 / 2.0**2, 0.4 / 2.0**2], [0.5 / 2.0**2, 0.6 / 2.0**2], ], + display_name='test', ), ), ], @@ -1087,75 +1138,77 @@ def test_division_dimensionless( 'test, expected, raises_warning', [ ( - DescriptorNumber('test', 2, 'm', 0.01), + DescriptorNumber(2, unit='m', variance=0.01, display_name='test'), DescriptorArray( - 'test / name', [[2.0, 1.0], [2.0 / 3.0, 0.5]], - 'dimensionless', - [ + unit='dimensionless', + variance=[ [0.41, 0.0525], [ (0.01 + 0.3 * 2**2 / 3.0**2) / 3.0**2, (0.01 + 0.4 * 2**2 / 4.0**2) / 4.0**2, ], ], + display_name='test / name', ), True, ), ( - DescriptorNumber('test', 1, 'cm', 10), + DescriptorNumber(1, unit='cm', variance=10, display_name='test'), DescriptorArray( - 'test / name', [[1.0 / 100.0, 1.0 / 200.0], [1.0 / 300.0, 1.0 / 400.0]], - 'dimensionless', - [ + unit='dimensionless', + variance=[ [1.01e-3, (1e-3 + 0.2 * 0.01**2 / 2**2) / 2**2], [ (1e-3 + 0.3 * 0.01**2 / 3**2) / 3**2, (1e-3 + 0.4 * 0.01**2 / 4**2) / 4**2, ], ], + display_name='test / name', ), True, ), ( - DescriptorNumber('test', 1, 'kg', 10), + DescriptorNumber(1, unit='kg', variance=10, display_name='test'), DescriptorArray( - 'test / name', [[1.0, 0.5], [1.0 / 3.0, 0.25]], - 'kg/m', - [ + unit='kg/m', + variance=[ [10.1, (10 + 0.2 * 1 / 2**2) / 2**2], [(10 + 0.3 * 1 / 3**2) / 3**2, (10 + 0.4 * 1 / 4**2) / 4**2], ], + display_name='test / name', ), True, ), ( DescriptorArray( - 'test', [[2.0, 3.0], [4.0, -5.0]], 'cm^2', [[1.0, 2.0], [3.0, 4.0]] + [[2.0, 3.0], [4.0, -5.0]], + unit='cm^2', + variance=[[1.0, 2.0], [3.0, 4.0]], + display_name='test', ), DescriptorArray( - 'test / name', [[2e-4, 1.5e-4], [4.0 / 3.0 * 1e-4, -1.25e-4]], - 'm', - [ + unit='m', + variance=[ [1.4e-8, 6.125e-9], [ (3.0e-8 + 0.3 * (0.0004) ** 2 / 3**2) / 3**2, (4.0e-8 + 0.4 * (0.0005) ** 2 / 4**2) / 4**2, ], ], + display_name='test / name', ), False, ), ( - DescriptorArray('test', [[2, 3], [4, -5]], 'cm^2'), + DescriptorArray([[2, 3], [4, -5]], unit='cm^2', display_name='test'), DescriptorArray( - 'test / name', [[2e-4, 1.5e-4], [4.0 / 3.0 * 1e-4, -1.25e-4]], - 'm', - [ + unit='m', + variance=[ [ (0.1 * 2.0**2 / 1.0**2) / 1.0**2 * 1e-8, (0.2 * 3.0**2 / 2.0**2) / 2.0**2 * 1e-8, @@ -1165,32 +1218,33 @@ def test_division_dimensionless( (0.4 * 5.0**2 / 4.0**2) / 4.0**2 * 1e-8, ], ], + display_name='test / name', ), False, ), ( [[2.0, 3.0], [4.0, -5.0]], DescriptorArray( - 'test / name', [[2, 1.5], [4.0 / 3.0, -1.25]], - '1/m', - [ + unit='1/m', + variance=[ [0.1 * 2**2 / 1**4, 0.2 * 3.0**2 / 2.0**4], [0.3 * 4**2 / 3**4, 0.4 * 5.0**2 / 4.0**4], ], + display_name='test / name', ), False, ), ( 2.0, DescriptorArray( - 'test / name', [[2, 1.0], [2.0 / 3.0, 0.5]], - '1/m', - [ + unit='1/m', + variance=[ [0.1 * 2**2 / 1**4, 0.2 * 2.0**2 / 2.0**4], [0.3 * 2**2 / 3**4, 0.4 * 2.0**2 / 4.0**4], ], + display_name='test / name', ), False, ), @@ -1216,7 +1270,6 @@ def test_reverse_division(self, descriptor: DescriptorArray, test, expected, rai result = test / descriptor # Expect assert type(result) == DescriptorArray - assert result.name == result.unique_name assert np.allclose(result.value, expected.value) assert result.unit == expected.unit assert np.allclose(result.variance, expected.variance) @@ -1228,27 +1281,27 @@ def test_reverse_division(self, descriptor: DescriptorArray, test, expected, rai ( [[2.0, 3.0], [4.0, -5.0], [6.0, -8.0]], DescriptorArray( - 'test', [[2.0 / 1.0, 3.0 / 2.0], [4.0 / 3.0, -5.0 / 4.0], [6.0 / 5.0, -8.0 / 6.0]], - 'dimensionless', - [ + unit='dimensionless', + variance=[ [0.1 * 2.0**2, 0.2 * 3.0**2 / 2**4], [0.3 * 4.0**2 / 3.0**4, 0.4 * 5.0**2 / 4**4], [0.5 * 6.0**2 / 5**4, 0.6 * 8.0**2 / 6**4], ], + display_name='test', ), ), ( 2, DescriptorArray( - 'test', [[2.0, 1.0], [2.0 / 3.0, 0.5], [2.0 / 5.0, 1.0 / 3.0]], - 'dimensionless', - [ + unit='dimensionless', + variance=[ [0.1 * 2.0**2, 0.2 / 2**2], [0.3 * 2**2 / 3**4, 0.4 * 2**2 / 4**4], [0.5 * 2**2 / 5**4, 0.6 * 2**2 / 6**4], ], + display_name='test', ), ), ], @@ -1270,12 +1323,12 @@ def test_reverse_division_dimensionless( [ [[2.0, 3.0], [4.0, -5.0], [6.0, 0.0]], 0.0, - DescriptorNumber('test', 0, 'cm', 10), + DescriptorNumber(0, unit='cm', variance=10, display_name='test'), DescriptorArray( - 'test', [[1.5, 0.0], [4.5, 6.0], [7.5, 9.0]], - 'dimensionless', - [[0.225, 0.45], [0.675, 0.9], [1.125, 1.35]], + unit='dimensionless', + variance=[[0.225, 0.45], [0.675, 0.9], [1.125, 1.35]], + display_name='test', ), ], ids=['list', 'number', 'DescriptorNumber', 'DescriptorArray'], @@ -1287,10 +1340,10 @@ def test_division_exception(self, descriptor_dimensionless: DescriptorArray, tes # Also test reverse division where `self` is a DescriptorArray with a zero zero_descriptor = DescriptorArray( - 'test', [[1.5, 0.0], [4.5, 6.0], [7.5, 0.0]], - 'dimensionless', - [[0.225, 0.45], [0.675, 0.9], [1.125, 1.35]], + unit='dimensionless', + variance=[[0.225, 0.45], [0.675, 0.9], [1.125, 1.35]], + display_name='test', ) with pytest.raises(ZeroDivisionError): test / zero_descriptor @@ -1299,39 +1352,39 @@ def test_division_exception(self, descriptor_dimensionless: DescriptorArray, tes 'test, expected', [ ( - DescriptorNumber('test', 2, 'dimensionless'), + DescriptorNumber(2, unit='dimensionless', display_name='test'), DescriptorArray( - 'test ** name', [[1.0, 4.0], [9.0, 16.0]], - 'm^2', - [[4 * 0.1 * 1, 4 * 0.2 * 2**2], [4 * 0.3 * 3**2, 4 * 0.4 * 4**2]], + unit='m^2', + variance=[[4 * 0.1 * 1, 4 * 0.2 * 2**2], [4 * 0.3 * 3**2, 4 * 0.4 * 4**2]], + display_name='test ** name', ), ), ( - DescriptorNumber('test', 3, 'dimensionless'), + DescriptorNumber(3, unit='dimensionless', display_name='test'), DescriptorArray( - 'test ** name', [[1.0, 8.0], [27, 64.0]], - 'm^3', - [[9 * 0.1, 9 * 0.2 * 2**4], [9 * 0.3 * 3**4, 9 * 0.4 * 4**4]], + unit='m^3', + variance=[[9 * 0.1, 9 * 0.2 * 2**4], [9 * 0.3 * 3**4, 9 * 0.4 * 4**4]], + display_name='test ** name', ), ), ( - DescriptorNumber('test', 0.0, 'dimensionless'), + DescriptorNumber(0.0, unit='dimensionless', display_name='test'), DescriptorArray( - 'test ** name', [[1.0, 1.0], [1.0, 1.0]], - 'dimensionless', - [[0.0, 0.0], [0.0, 0.0]], + unit='dimensionless', + variance=[[0.0, 0.0], [0.0, 0.0]], + display_name='test ** name', ), ), ( 0.0, DescriptorArray( - 'test ** name', [[1.0, 1.0], [1.0, 1.0]], - 'dimensionless', - [[0.0, 0.0], [0.0, 0.0]], + unit='dimensionless', + variance=[[0.0, 0.0], [0.0, 0.0]], + display_name='test ** name', ), ), ], @@ -1347,7 +1400,6 @@ def test_power(self, descriptor: DescriptorArray, test, expected): result = descriptor**test # Expect assert type(result) == DescriptorArray - assert result.name == result.unique_name assert np.array_equal(result.value, expected.value) assert result.unit == expected.unit assert np.allclose(result.variance, expected.variance) @@ -1357,25 +1409,25 @@ def test_power(self, descriptor: DescriptorArray, test, expected): 'test, expected', [ ( - DescriptorNumber('test', 0.1, 'dimensionless'), + DescriptorNumber(0.1, unit='dimensionless', display_name='test'), DescriptorArray( - 'test ** name', [[1, 2**0.1], [3**0.1, 4**0.1], [5**0.1, 6**0.1]], - 'dimensionless', - [ + unit='dimensionless', + variance=[ [0.1**2 * 0.1 * 1, 0.1**2 * 0.2 * 2 ** (-1.8)], [0.1**2 * 0.3 * 3 ** (-1.8), 0.1**2 * 0.4 * 4 ** (-1.8)], [0.1**2 * 0.5 * 5 ** (-1.8), 0.1**2 * 0.6 * 6 ** (-1.8)], ], + display_name='test ** name', ), ), ( - DescriptorNumber('test', 2.0, 'dimensionless'), + DescriptorNumber(2.0, unit='dimensionless', display_name='test'), DescriptorArray( - 'test ** name', [[1.0, 4.0], [9.0, 16.0], [25.0, 36.0]], - 'dimensionless', - [[0.4, 3.2], [10.8, 25.6], [50.0, 86.4]], + unit='dimensionless', + variance=[[0.4, 3.2], [10.8, 25.6], [50.0, 86.4]], + display_name='test ** name', ), ), ], @@ -1386,7 +1438,6 @@ def test_power_dimensionless(self, descriptor_dimensionless: DescriptorArray, te result = descriptor_dimensionless**test # Expect assert type(result) == DescriptorArray - assert result.name == result.unique_name assert np.allclose(result.value, expected.value) assert result.unit == expected.unit assert np.allclose(result.variance, expected.variance) @@ -1395,13 +1446,16 @@ def test_power_dimensionless(self, descriptor_dimensionless: DescriptorArray, te @pytest.mark.parametrize( 'test, exception', [ - (DescriptorNumber('test', 2, 'm'), UnitError), - (DescriptorNumber('test', 2, 'dimensionless', 10), ValueError), - (DescriptorNumber('test', np.nan, 'dimensionless'), UnitError), - (DescriptorNumber('test', np.nan, 'dimensionless'), UnitError), - (DescriptorNumber('test', 1.5, 'dimensionless'), UnitError), + (DescriptorNumber(2, unit='m', display_name='test'), UnitError), + ( + DescriptorNumber(2, unit='dimensionless', variance=10, display_name='test'), + ValueError, + ), + (DescriptorNumber(np.nan, unit='dimensionless', display_name='test'), UnitError), + (DescriptorNumber(np.nan, unit='dimensionless', display_name='test'), UnitError), + (DescriptorNumber(1.5, unit='dimensionless', display_name='test'), UnitError), ( - DescriptorNumber('test', 0.5, 'dimensionless'), + DescriptorNumber(0.5, unit='dimensionless', display_name='test'), UnitError, ), # Square roots are not legal ], @@ -1424,7 +1478,10 @@ def test_power_exception(self, descriptor: DescriptorArray, test, exception): @pytest.mark.parametrize( 'test', - [DescriptorNumber('test', 2, 's'), DescriptorArray('test', [[1, 2], [3, 4]], 's')], + [ + DescriptorNumber(2, unit='s', display_name='test'), + DescriptorArray([[1, 2], [3, 4]], unit='s', display_name='test'), + ], ids=['add_array_to_unit', 'incompatible_units'], ) def test_addition_exception(self, descriptor: DescriptorArray, test): @@ -1436,7 +1493,10 @@ def test_addition_exception(self, descriptor: DescriptorArray, test): @pytest.mark.parametrize( 'test', - [DescriptorNumber('test', 2, 's'), DescriptorArray('test', [[1, 2], [3, 4]], 's')], + [ + DescriptorNumber(2, unit='s', display_name='test'), + DescriptorArray([[1, 2], [3, 4]], unit='s', display_name='test'), + ], ids=['add_array_to_unit', 'incompatible_units'], ) def test_sub_exception(self, descriptor: DescriptorArray, test): @@ -1468,7 +1528,6 @@ def test_negation(self, descriptor): # Expect expected = DescriptorArray( - name='name', value=[[-1.0, -2.0], [-3.0, -4.0]], unit='m', variance=[[0.1, 0.2], [0.3, 0.4]], @@ -1477,7 +1536,6 @@ def test_negation(self, descriptor): display_name='display_name', ) assert type(result) == DescriptorArray - assert result.name == result.unique_name assert np.array_equal(result.value, expected.value) assert result.unit == expected.unit assert np.allclose(result.variance, expected.variance) @@ -1486,7 +1544,6 @@ def test_negation(self, descriptor): def test_abs(self, descriptor): # When negated = DescriptorArray( - name='name', value=[[-1.0, -2.0], [-3.0, -4.0]], unit='m', variance=[[0.1, 0.2], [0.3, 0.4]], @@ -1500,7 +1557,6 @@ def test_abs(self, descriptor): # Expect assert type(result) == DescriptorArray - assert result.name == result.unique_name assert np.array_equal(result.value, descriptor.value) assert result.unit == descriptor.unit assert np.allclose(result.variance, descriptor.variance) @@ -1511,40 +1567,55 @@ def test_abs(self, descriptor): [ ( DescriptorArray( - 'test + name', [[3.0, 4.0], [5.0, 6.0]], 'm', [[0.11, 0.21], [0.31, 0.41]] + [[3.0, 4.0], [5.0, 6.0]], + unit='m', + variance=[[0.11, 0.21], [0.31, 0.41]], + display_name='test + name', ), - DescriptorNumber('test', 9, 'm', 0.52), + DescriptorNumber(9, unit='m', variance=0.52, display_name='test'), ), ( DescriptorArray( - 'test + name', [[101.0, 201.0], [301.0, 401.0]], - 'dimensionless', - [[1010.0, 2010.0], [3010.0, 4010.0]], + unit='dimensionless', + variance=[[1010.0, 2010.0], [3010.0, 4010.0]], + display_name='test + name', + ), + DescriptorNumber( + 502.0, unit='dimensionless', variance=5020.0, display_name='test' ), - DescriptorNumber('test', 502.0, 'dimensionless', 5020.0), ), ( - DescriptorArray('test', np.ones((9, 9)), 'dimensionless', np.ones((9, 9))), - DescriptorNumber('test', 9.0, 'dimensionless', 9.0), + DescriptorArray( + np.ones((9, 9)), + unit='dimensionless', + variance=np.ones((9, 9)), + display_name='test', + ), + DescriptorNumber(9.0, unit='dimensionless', variance=9.0, display_name='test'), ), ( - DescriptorArray('test', np.ones((3, 3, 3)), 'dimensionless', np.ones((3, 3, 3))), DescriptorArray( - 'test', + np.ones((3, 3, 3)), + unit='dimensionless', + variance=np.ones((3, 3, 3)), + display_name='test', + ), + DescriptorArray( [3.0, 3.0, 3.0], - 'dimensionless', - [ + unit='dimensionless', + variance=[ 3.0, 3.0, 3.0, ], dimensions=['dim2'], + display_name='test', ), ), ( - DescriptorArray('test', [[2.0]], 'dimensionless'), - DescriptorNumber('test', 2.0, 'dimensionless'), + DescriptorArray([[2.0]], unit='dimensionless', display_name='test'), + DescriptorNumber(2.0, unit='dimensionless', display_name='test'), ), ], ids=['2d_unit', '2d_dimensionless', '2d_large', '3d_dimensionless', '1d_dimensionless'], @@ -1552,7 +1623,6 @@ def test_abs(self, descriptor): def test_trace(self, test: DescriptorArray, expected: DescriptorNumber): result = test.trace() assert type(result) == type(expected) - assert result.name == result.unique_name assert np.array_equal(result.value, expected.value) assert result.unit == expected.unit if test.variance is not None: @@ -1565,14 +1635,17 @@ def test_trace(self, test: DescriptorArray, expected: DescriptorNumber): [ ( DescriptorArray( - 'test', np.ones((3, 3, 4, 5)), 'dimensionless', np.ones((3, 3, 4, 5)) + np.ones((3, 3, 4, 5)), + unit='dimensionless', + variance=np.ones((3, 3, 4, 5)), + display_name='test', ), DescriptorArray( - 'test', - 3 * np.ones((3, 4)), - 'dimensionless', 3 * np.ones((3, 4)), + unit='dimensionless', + variance=3 * np.ones((3, 4)), dimensions=['dim0', 'dim2'], + display_name='test', ), ('dim1', 'dim3'), ) @@ -1584,7 +1657,6 @@ def test_trace_select_dimensions( ): result = test.trace(dimension1=dimensions[0], dimension2=dimensions[1]) assert type(result) == type(expected) - assert result.name == result.unique_name assert np.array_equal(result.value.shape, expected.value.shape) assert np.array_equal(result.value, expected.value) assert result.unit == expected.unit @@ -1594,17 +1666,32 @@ def test_trace_select_dimensions( 'test,dimensions,message', [ ( - DescriptorArray('test', np.ones((3, 3, 3)), 'dimensionless', np.ones((3, 3, 3))), + DescriptorArray( + np.ones((3, 3, 3)), + unit='dimensionless', + variance=np.ones((3, 3, 3)), + display_name='test', + ), ('dim0', None), 'Either both or none', ), ( - DescriptorArray('test', np.ones((3, 3, 3)), 'dimensionless', np.ones((3, 3, 3))), + DescriptorArray( + np.ones((3, 3, 3)), + unit='dimensionless', + variance=np.ones((3, 3, 3)), + display_name='test', + ), ('dim0', 'dim0'), 'must be different', ), ( - DescriptorArray('test', np.ones((3, 3, 3)), 'dimensionless', np.ones((3, 3, 3))), + DescriptorArray( + np.ones((3, 3, 3)), + unit='dimensionless', + variance=np.ones((3, 3, 3)), + display_name='test', + ), ('dim0', 'dim1337'), 'does not exist', ), @@ -1627,9 +1714,10 @@ def test_slicing(self, descriptor: DescriptorArray): assert type(last_value) == DescriptorArray assert type(second_array) == DescriptorArray - assert first_value.name != descriptor.unique_name - assert last_value.name != descriptor.unique_name - assert second_array.name != descriptor.unique_name + # Slices are fresh objects with their own identity, not the sliced parent. + assert first_value.unique_name != descriptor.unique_name + assert last_value.unique_name != descriptor.unique_name + assert second_array.unique_name != descriptor.unique_name assert np.array_equal( first_value.full_value.values, descriptor.full_value['dim0', 0].values @@ -1672,26 +1760,31 @@ def test_slice_assignment_exception(self, descriptor_dimensionless: DescriptorAr [ ( DescriptorArray( - 'test + name', [[3.0, 4.0], [5.0, 6.0]], 'm', [[0.11, 0.21], [0.31, 0.41]] + [[3.0, 4.0], [5.0, 6.0]], + unit='m', + variance=[[0.11, 0.21], [0.31, 0.41]], + display_name='test + name', ), - DescriptorNumber('test', 18, 'm', 1.04), + DescriptorNumber(18, unit='m', variance=1.04, display_name='test'), ), ( DescriptorArray( - 'test + name', [[101.0, 201.0], [301.0, 401.0]], - 'cm', - [[1010.0, 2010.0], [3010.0, 4010.0]], + unit='cm', + variance=[[1010.0, 2010.0], [3010.0, 4010.0]], + display_name='test + name', ), - DescriptorNumber('test', 1004.0, 'cm', 10040.0), + DescriptorNumber(1004.0, unit='cm', variance=10040.0, display_name='test'), ), ( - DescriptorArray('test', [[2.0, 3.0]], 'dimensionless', [[1.0, 2.0]]), - DescriptorNumber('test', 5.0, 'dimensionless', 3.0), + DescriptorArray( + [[2.0, 3.0]], unit='dimensionless', variance=[[1.0, 2.0]], display_name='test' + ), + DescriptorNumber(5.0, unit='dimensionless', variance=3.0, display_name='test'), ), ( - DescriptorArray('test', [[2.0, 3.0]], 'dimensionless'), - DescriptorNumber('test', 5.0, 'dimensionless'), + DescriptorArray([[2.0, 3.0]], unit='dimensionless', display_name='test'), + DescriptorNumber(5.0, unit='dimensionless', display_name='test'), ), ], ids=[ @@ -1704,7 +1797,6 @@ def test_slice_assignment_exception(self, descriptor_dimensionless: DescriptorAr def test_sum(self, test, expected): result = test.sum() assert type(result) == DescriptorNumber - assert result.name == result.unique_name assert np.array_equal(result.value, expected.value) assert result.unit == expected.unit if test.variance is not None: @@ -1713,15 +1805,20 @@ def test_sum(self, test, expected): @pytest.mark.parametrize( 'expected, dim', [ - (DescriptorArray('test', [4.0, 6.0], 'm', [0.4, 0.6]), 'dim0'), - (DescriptorArray('test', [3.0, 7.0], 'm', [0.3, 0.7]), 'dim1'), + ( + DescriptorArray([4.0, 6.0], unit='m', variance=[0.4, 0.6], display_name='test'), + 'dim0', + ), + ( + DescriptorArray([3.0, 7.0], unit='m', variance=[0.3, 0.7], display_name='test'), + 'dim1', + ), ], ids=['descriptor_array_dim0', 'descriptor_array_dim1'], ) def test_sum_over_subset(self, descriptor, expected, dim): result = descriptor.sum(dim) assert type(result) == type(expected) - assert result.name == result.unique_name assert np.array_equal(result.value, expected.value) assert result.unit == expected.unit assert np.allclose(result.variance, expected.variance) @@ -1729,25 +1826,40 @@ def test_sum_over_subset(self, descriptor, expected, dim): @pytest.mark.parametrize( 'test, dimensions', [ - (DescriptorArray('test', [1.0], 'dimensionless', [1.0]), ['dim0']), ( - DescriptorArray('test', [[1.0, 1.0]], 'dimensionless', [[1.0, 1.0]]), + DescriptorArray([1.0], unit='dimensionless', variance=[1.0], display_name='test'), + ['dim0'], + ), + ( + DescriptorArray( + [[1.0, 1.0]], unit='dimensionless', variance=[[1.0, 1.0]], display_name='test' + ), ['dim0', 'dim1'], ), ( - DescriptorArray('test', [[1.0], [1.0]], 'dimensionless', [[1.0], [1.0]]), + DescriptorArray( + [[1.0], [1.0]], + unit='dimensionless', + variance=[[1.0], [1.0]], + display_name='test', + ), ['dim0', 'dim1'], ), ( - DescriptorArray('test', [[[1.0, 1.0, 1.0]]], 'dimensionless', [[[1.0, 1.0, 1.0]]]), + DescriptorArray( + [[[1.0, 1.0, 1.0]]], + unit='dimensionless', + variance=[[[1.0, 1.0, 1.0]]], + display_name='test', + ), ['dim0', 'dim1', 'dim2'], ), ( DescriptorArray( - 'test', - [[[1.0]], [[1.0]], [[1.0]]], - 'dimensionless', [[[1.0]], [[1.0]], [[1.0]]], + unit='dimensionless', + variance=[[[1.0]], [[1.0]], [[1.0]]], + display_name='test', ), ['dim0', 'dim1', 'dim2'], ), @@ -1762,7 +1874,9 @@ def test_array_set_dimensions_exception(self, descriptor): descriptor.dimensions = ['too_few'] assert 'must have the same shape' with pytest.raises(ValueError) as e: - DescriptorArray('test', [[1.0]], 'm', [[1.0]], dimensions=['dim']) + DescriptorArray( + [[1.0]], unit='m', variance=[[1.0]], dimensions=['dim'], display_name='test' + ) assert 'Length of dimensions' in str(e) def test_array_set_integer_value(self, descriptor): @@ -1785,7 +1899,9 @@ def test_array_create_with_mixed_integers_and_floats(self): value = [[1, 2], [3, 4]] variance = [[0.1, 0.2], [0.3, 0.4]] # Then Expect - descriptor = DescriptorArray('test', value, 'dimensionless', variance) # Should not raise + descriptor = DescriptorArray( + value, unit='dimensionless', variance=variance, display_name='test' + ) # Should not raise assert isinstance(descriptor.value[0][0], float) assert isinstance(descriptor.variance[0][0], float) diff --git a/tests/unit/variable/test_descriptor_base.py b/tests/unit/variable/test_descriptor_base.py index 9661afa3..980aac51 100644 --- a/tests/unit/variable/test_descriptor_base.py +++ b/tests/unit/variable/test_descriptor_base.py @@ -19,7 +19,6 @@ def descriptor(self): DescriptorBase.__repr__ = lambda x: 'DescriptorBase' self.objs_before_new_descriptor = len(global_object.map.created_objs) descriptor = DescriptorBase( - name='name', description='description', url='url', display_name='display_name', @@ -31,15 +30,15 @@ def clear(self): global_object.map._clear() @pytest.mark.parametrize( - 'name', - [1, True, 1.0, [], {}, (), None, object()], - ids=['int', 'bool', 'float', 'list', 'dict', 'tuple', 'None', 'object'], + 'unique_name', + [1, True, 1.0, [], {}, (), object()], + ids=['int', 'bool', 'float', 'list', 'dict', 'tuple', 'object'], ) - def test_init_name_type_error(self, name): + def test_init_unique_name_type_error(self, unique_name): # When Then with pytest.raises(TypeError): DescriptorBase( - name=name, + unique_name=unique_name, description='description', url='url', display_name='display_name', @@ -54,7 +53,6 @@ def test_init_display_name_type_error(self, display_name): # When Then with pytest.raises(TypeError): DescriptorBase( - name='name', description='description', url='url', display_name=display_name, @@ -69,7 +67,6 @@ def test_init_description_type_error(self, description): # When Then with pytest.raises(TypeError): DescriptorBase( - name='name', description=description, url='url', display_name='display_name', @@ -84,14 +81,12 @@ def test_init_url_type_error(self, url): # When Then with pytest.raises(TypeError): DescriptorBase( - name='name', description='description', url=url, display_name='display_name', ) def test_init(self, descriptor: DescriptorBase): - assert descriptor._name == 'name' assert descriptor._description == 'description' assert descriptor._url == 'url' assert descriptor._display_name == 'display_name' @@ -105,7 +100,7 @@ def test_display_name_none(self, descriptor: DescriptorBase): # When descriptor._display_name = None # Then Expect - assert descriptor.display_name == 'name' + assert descriptor.display_name == descriptor.unique_name def test_display_name_setter(self, descriptor: DescriptorBase): # When @@ -123,22 +118,6 @@ def test_display_name_setter_type_error(self, descriptor: DescriptorBase, displa with pytest.raises(TypeError): descriptor.display_name = display_name - def test_name_setter(self, descriptor: DescriptorBase): - # When - descriptor.name = 'new_name' - # Then Expect - assert descriptor.name == 'new_name' - - @pytest.mark.parametrize( - 'name', - [1, True, 1.0, [], {}, (), object(), None], - ids=['int', 'bool', 'float', 'list', 'dict', 'tuple', 'object', 'None'], - ) - def test_name_setter_type_error(self, descriptor: DescriptorBase, name): - # When Then - with pytest.raises(TypeError): - descriptor.name = name - def test_description_setter(self, descriptor: DescriptorBase): # When descriptor.description = 'new_description' @@ -193,18 +172,17 @@ def test_copy(self, descriptor: DescriptorBase): # Expect assert type(descriptor_copy) == DescriptorBase - assert descriptor_copy._name == descriptor._name assert descriptor_copy._description == descriptor._description assert descriptor_copy._url == descriptor._url assert descriptor_copy._display_name == descriptor._display_name def test_unique_name_generator(self, clear, descriptor: DescriptorBase): # When - second_descriptor = DescriptorBase(name='test', unique_name='DescriptorBase_2') + second_descriptor = DescriptorBase(display_name='test', unique_name='DescriptorBase_2') # Then - third_descriptor = DescriptorBase(name='test2') - fourth_descriptor = DescriptorBase(name='test3') + third_descriptor = DescriptorBase(display_name='test2') + fourth_descriptor = DescriptorBase(display_name='test3') # Expect assert descriptor.unique_name == 'DescriptorBase_0' diff --git a/tests/unit/variable/test_descriptor_bool.py b/tests/unit/variable/test_descriptor_bool.py index 48372485..7269734a 100644 --- a/tests/unit/variable/test_descriptor_bool.py +++ b/tests/unit/variable/test_descriptor_bool.py @@ -11,7 +11,6 @@ class TestDescriptorBool: @pytest.fixture def descriptor(self): descriptor = DescriptorBool( - name='name', value=True, description='description', url='url', @@ -28,7 +27,6 @@ def test_init(self, descriptor: DescriptorBool): assert descriptor._bool_value == True # From super - assert descriptor._name == 'name' assert descriptor._description == 'description' assert descriptor._url == 'url' assert descriptor._display_name == 'display_name' @@ -39,7 +37,6 @@ def test_init_bool_value_type_exception(self, bool_value): # When Then Expect with pytest.raises(ValueError): DescriptorBool( - name='name', value=bool_value, description='description', url='url', @@ -68,7 +65,7 @@ def test_repr(self, descriptor: DescriptorBool): repr_str = str(descriptor) # Expect - assert repr_str == "" + assert repr_str == "" def test_copy(self, descriptor: DescriptorBool): # When Then diff --git a/tests/unit/variable/test_descriptor_number.py b/tests/unit/variable/test_descriptor_number.py index 3d3f7331..8a88dbc4 100644 --- a/tests/unit/variable/test_descriptor_number.py +++ b/tests/unit/variable/test_descriptor_number.py @@ -13,7 +13,6 @@ class TestDescriptorNumber: @pytest.fixture def descriptor(self): descriptor = DescriptorNumber( - name='name', value=1, unit='m', variance=0.1, @@ -35,7 +34,6 @@ def test_init(self, descriptor: DescriptorNumber): assert descriptor._observers == [] # From super - assert descriptor._name == 'name' assert descriptor._description == 'description' assert descriptor._url == 'url' assert descriptor._display_name == 'display_name' @@ -43,7 +41,6 @@ def test_init(self, descriptor: DescriptorNumber): def test_init_sc_unit(self): # When Then descriptor = DescriptorNumber( - name='name', value=1, unit=sc.units.Unit('m'), variance=0.1, @@ -61,7 +58,6 @@ def test_init_sc_unit_unknown(self): # When Then Expect with pytest.raises(UnitError): DescriptorNumber( - name='name', value=1, unit='unknown', variance=0.1, @@ -77,7 +73,6 @@ def test_init_value_type_exception(self, value): # Then Expect with pytest.raises(TypeError): DescriptorNumber( - name='name', value=value, unit='m', variance=0.1, @@ -93,7 +88,6 @@ def test_init_variance_exception(self): # Then Expect with pytest.raises(ValueError): DescriptorNumber( - name='name', value=1, unit='m', variance=variance, @@ -108,7 +102,7 @@ def test_from_scipp(self): full_value = sc.scalar(1, unit='m') # Then - descriptor = DescriptorNumber.from_scipp(name='name', full_value=full_value) + descriptor = DescriptorNumber.from_scipp(display_name='name', full_value=full_value) # Expect assert descriptor._scalar.value == 1 @@ -129,7 +123,7 @@ def test_from_scipp(self): def test_from_scipp_type_exception(self, full_value): # When Then Expect with pytest.raises(TypeError): - DescriptorNumber.from_scipp(name='name', full_value=full_value) + DescriptorNumber.from_scipp(display_name='name', full_value=full_value) def test_full_value(self, descriptor: DescriptorNumber): # When Then Expect @@ -196,7 +190,7 @@ def test_repr(self, descriptor: DescriptorNumber): repr_str = str(descriptor) # Expect - assert repr_str == "" + assert repr_str == "" def test_copy(self, descriptor: DescriptorNumber): # When Then @@ -214,7 +208,7 @@ def test_copy(self, descriptor: DescriptorNumber): ) def test_base_unit(self, unit_string, expected): # When - descriptor = DescriptorNumber(name='name', value=1, unit=unit_string) + descriptor = DescriptorNumber(display_name='name', value=1, unit=unit_string) # Then base_unit = descriptor._base_unit() @@ -226,17 +220,12 @@ def test_base_unit(self, unit_string, expected): 'test, expected', [ ( - DescriptorNumber( - 'test', - 2, - 'm', - 0.01, - ), - DescriptorNumber('test + name', 3, 'm', 0.11), + DescriptorNumber(2, unit='m', variance=0.01, display_name='test'), + DescriptorNumber(3, unit='m', variance=0.11, display_name='test + name'), ), ( - DescriptorNumber('test', 2, 'cm', 0.01), - DescriptorNumber('test + name', 102, 'cm', 1000.01), + DescriptorNumber(2, unit='cm', variance=0.01, display_name='test'), + DescriptorNumber(102, unit='cm', variance=1000.01, display_name='test + name'), ), ], ids=['regular', 'unit_conversion'], @@ -247,7 +236,6 @@ def test_addition(self, descriptor: DescriptorNumber, test, expected): # Expect assert type(result) == DescriptorNumber - assert result.name == result.unique_name assert result.value == expected.value assert result.unit == expected.unit assert result.variance == expected.variance @@ -256,7 +244,7 @@ def test_addition(self, descriptor: DescriptorNumber, test, expected): def test_addition_with_scalar(self): # When - descriptor = DescriptorNumber(name='name', value=1, variance=0.1) + descriptor = DescriptorNumber(display_name='name', value=1, variance=0.1) # Then result = descriptor + 1.0 @@ -264,13 +252,11 @@ def test_addition_with_scalar(self): # Expect assert type(result) == DescriptorNumber - assert result.name == result.unique_name assert result.value == 2.0 assert result.unit == 'dimensionless' assert result.variance == 0.1 assert type(result_reverse) == DescriptorNumber - assert result_reverse.name == result_reverse.unique_name assert result_reverse.value == 2.0 assert result_reverse.unit == 'dimensionless' assert result_reverse.variance == 0.1 @@ -279,11 +265,7 @@ def test_addition_with_scalar(self): 'test', [ 1.0, - DescriptorNumber( - 'test', - 2, - 's', - ), + DescriptorNumber(2, unit='s', display_name='test'), ], ids=['add_scalar_to_unit', 'incompatible_units'], ) @@ -298,17 +280,12 @@ def test_addition_exception(self, descriptor: DescriptorNumber, test): 'test, expected', [ ( - DescriptorNumber( - 'test', - 2, - 'm', - 0.01, - ), - DescriptorNumber('test - name', 1, 'm', 0.11), + DescriptorNumber(2, unit='m', variance=0.01, display_name='test'), + DescriptorNumber(1, unit='m', variance=0.11, display_name='test - name'), ), ( - DescriptorNumber('test', 2, 'cm', 0.01), - DescriptorNumber('test - name', -98, 'cm', 1000.01), + DescriptorNumber(2, unit='cm', variance=0.01, display_name='test'), + DescriptorNumber(-98, unit='cm', variance=1000.01, display_name='test - name'), ), ], ids=['regular', 'unit_conversion'], @@ -319,7 +296,6 @@ def test_subtraction(self, descriptor: DescriptorNumber, test, expected): # Expect assert type(result) == DescriptorNumber - assert result.name == result.unique_name assert result.value == expected.value assert result.unit == expected.unit assert result.variance == expected.variance @@ -328,7 +304,7 @@ def test_subtraction(self, descriptor: DescriptorNumber, test, expected): def test_subtraction_with_scalar(self): # When - descriptor = DescriptorNumber(name='name', value=2, variance=0.1) + descriptor = DescriptorNumber(display_name='name', value=2, variance=0.1) # Then result = descriptor - 1.0 @@ -336,13 +312,11 @@ def test_subtraction_with_scalar(self): # Expect assert type(result) == DescriptorNumber - assert result.name == result.unique_name assert result.value == 1.0 assert result.unit == 'dimensionless' assert result.variance == 0.1 assert type(result_reverse) == DescriptorNumber - assert result_reverse.name == result_reverse.unique_name assert result_reverse.value == -1.0 assert result_reverse.unit == 'dimensionless' assert result_reverse.variance == 0.1 @@ -351,11 +325,7 @@ def test_subtraction_with_scalar(self): 'test', [ 1.0, - DescriptorNumber( - 'test', - 2, - 's', - ), + DescriptorNumber(2, unit='s', display_name='test'), ], ids=['sub_scalar_to_unit', 'incompatible_units'], ) @@ -370,17 +340,12 @@ def test_subtraction_exception(self, descriptor: DescriptorNumber, test): 'test, expected', [ ( - DescriptorNumber( - 'test', - 2, - 'm', - 0.01, - ), - DescriptorNumber('test * name', 2, 'm^2', 0.41), + DescriptorNumber(2, unit='m', variance=0.01, display_name='test'), + DescriptorNumber(2, unit='m^2', variance=0.41, display_name='test * name'), ), ( - DescriptorNumber('test', 2, 'dm', 0.01), - DescriptorNumber('test * name', 0.2, 'm^2', 0.0041), + DescriptorNumber(2, unit='dm', variance=0.01, display_name='test'), + DescriptorNumber(0.2, unit='m^2', variance=0.0041, display_name='test * name'), ), ], ids=['regular', 'base_unit_conversion'], @@ -391,7 +356,6 @@ def test_multiplication(self, descriptor: DescriptorNumber, test, expected): # Expect assert type(result) == DescriptorNumber - assert result.name == result.unique_name assert result.value == expected.value assert result.unit == expected.unit assert result.variance == pytest.approx(expected.variance) @@ -403,13 +367,11 @@ def test_multiplication_with_scalar(self, descriptor: DescriptorNumber): # Expect assert type(result) == DescriptorNumber - assert result.name == result.unique_name assert result.value == 2.0 assert result.unit == 'm' assert result.variance == 0.4 assert type(result_reverse) == DescriptorNumber - assert result_reverse.name == result_reverse.unique_name assert result_reverse.value == 2.0 assert result_reverse.unit == 'm' assert result_reverse.variance == 0.4 @@ -418,19 +380,14 @@ def test_multiplication_with_scalar(self, descriptor: DescriptorNumber): 'test, expected, expected_reverse', [ ( - DescriptorNumber( - 'test', - 2, - 'm^2', - 0.01, - ), - DescriptorNumber('name / test', 0.5, '1/m', 0.025625), - DescriptorNumber('test / name', 2, 'm', 0.41), + DescriptorNumber(2, unit='m^2', variance=0.01, display_name='test'), + DescriptorNumber(0.5, unit='1/m', variance=0.025625, display_name='name / test'), + DescriptorNumber(2, unit='m', variance=0.41, display_name='test / name'), ), ( 2, - DescriptorNumber('name / 2', 0.5, 'm', 0.025), - DescriptorNumber('2 / name', 2, '1/m', 0.4), + DescriptorNumber(0.5, unit='m', variance=0.025, display_name='name / 2'), + DescriptorNumber(2, unit='1/m', variance=0.4, display_name='2 / name'), ), ], ids=['descriptorNumber', 'scalar'], @@ -442,19 +399,19 @@ def test_division(self, descriptor: DescriptorNumber, test, expected, expected_r # Expect assert type(result) == DescriptorNumber - assert result.name == result.unique_name assert result.value == expected.value assert result.unit == expected.unit assert result.variance == pytest.approx(expected.variance) assert type(result_reverse) == DescriptorNumber - assert result_reverse.name == result_reverse.unique_name assert result_reverse.value == expected_reverse.value assert result_reverse.unit == expected_reverse.unit assert result_reverse.variance == pytest.approx(expected_reverse.variance) @pytest.mark.parametrize( - 'test', [0, DescriptorNumber('test', 0, 'm', 0.01)], ids=['zero', 'zero_descriptor'] + 'test', + [0, DescriptorNumber(0, unit='m', variance=0.01, display_name='test')], + ids=['zero', 'zero_descriptor'], ) def test_division_exception(self, descriptor: DescriptorNumber, test): # When Then Expect @@ -463,7 +420,7 @@ def test_division_exception(self, descriptor: DescriptorNumber, test): def test_division_exception_reverse(self): # When - descriptor = DescriptorNumber(name='name', value=0, variance=0.1) + descriptor = DescriptorNumber(display_name='name', value=0, variance=0.1) # Then Expect with pytest.raises(ZeroDivisionError): @@ -473,38 +430,41 @@ def test_division_exception_reverse(self): 'test, expected', [ ( - DescriptorNumber('test', 2), - DescriptorNumber('name ** test', 4, unit='m^2', variance=1.6), + DescriptorNumber(2, display_name='test'), + DescriptorNumber(4, unit='m^2', variance=1.6, display_name='name ** test'), + ), + (2, DescriptorNumber(4, unit='m^2', variance=1.6, display_name='name ** 2')), + ( + -2, + DescriptorNumber(0.25, unit='1/m^2', variance=0.00625, display_name='name ** -2'), ), - (2, DescriptorNumber('name ** 2', 4, unit='m^2', variance=1.6)), - (-2, DescriptorNumber('name ** -2', 0.25, unit='1/m^2', variance=0.00625)), ], ids=['descriptorNumber', 'scalar', 'negative_scalar'], ) def test_power_of_descriptor(self, test, expected): # When - descriptor = DescriptorNumber(name='name', value=2, unit='m', variance=0.1) + descriptor = DescriptorNumber(display_name='name', value=2, unit='m', variance=0.1) # Then result = descriptor**test # Expect assert type(result) == DescriptorNumber - assert result.name == result.unique_name assert result.value == expected.value assert result.unit == expected.unit assert result.variance == expected.variance def test_power_of_dimensionless_descriptor(self): # When - descriptor = DescriptorNumber(name='name', value=2, unit='dimensionless', variance=0.1) + descriptor = DescriptorNumber( + display_name='name', value=2, unit='dimensionless', variance=0.1 + ) # Then result = descriptor**0.5 # Expect assert type(result) == DescriptorNumber - assert result.name == result.unique_name assert result.value == 1.4142135623730951 assert result.unit == 'dimensionless' assert result.variance == pytest.approx(0.0125) @@ -512,10 +472,18 @@ def test_power_of_dimensionless_descriptor(self): @pytest.mark.parametrize( 'descriptor, exponent, exception', [ - (DescriptorNumber('name', 2), DescriptorNumber('test', 2, unit='m'), UnitError), - (DescriptorNumber('name', 2), DescriptorNumber('test', 2, variance=0.1), ValueError), - (DescriptorNumber('name', 2, unit='m'), 0.5, UnitError), - (DescriptorNumber('name', -2), 0.5, ValueError), + ( + DescriptorNumber(2, display_name='name'), + DescriptorNumber(2, unit='m', display_name='test'), + UnitError, + ), + ( + DescriptorNumber(2, display_name='name'), + DescriptorNumber(2, variance=0.1, display_name='test'), + ValueError, + ), + (DescriptorNumber(2, unit='m', display_name='name'), 0.5, UnitError), + (DescriptorNumber(-2, display_name='name'), 0.5, ValueError), ], ids=[ 'descriptor_unit', @@ -531,7 +499,7 @@ def test_power_of_descriptor_exceptions(self, descriptor, exponent, exception): def test_descriptor_as_exponentiation(self): # When - descriptor = DescriptorNumber(name='name', value=2) + descriptor = DescriptorNumber(display_name='name', value=2) # Then result = 2**descriptor @@ -542,8 +510,8 @@ def test_descriptor_as_exponentiation(self): @pytest.mark.parametrize( 'exponent, exception', [ - (DescriptorNumber('test', 2, unit='m'), UnitError), - (DescriptorNumber('test', 2, variance=0.1), ValueError), + (DescriptorNumber(2, unit='m', display_name='test'), UnitError), + (DescriptorNumber(2, variance=0.1, display_name='test'), ValueError), ], ids=['descriptor_unit', 'descriptor_variance'], ) @@ -554,28 +522,26 @@ def test_descriptor_as_exponentiation_exception(self, exponent, exception): def test_negation(self): # When - descriptor = DescriptorNumber(name='name', unit='m', value=2, variance=0.1) + descriptor = DescriptorNumber(display_name='name', unit='m', value=2, variance=0.1) # Then result = -descriptor # Expect assert type(result) == DescriptorNumber - assert result.name == result.unique_name assert result.value == -2 assert result.unit == 'm' assert result.variance == 0.1 def test_abs(self): # When - descriptor = DescriptorNumber(name='name', unit='m', value=-2, variance=0.1) + descriptor = DescriptorNumber(display_name='name', unit='m', value=-2, variance=0.1) # Then result = abs(descriptor) # Expect assert type(result) == DescriptorNumber - assert result.name == result.unique_name assert result.value == 2 assert result.unit == 'm' assert result.variance == 0.1 diff --git a/tests/unit/variable/test_descriptor_str.py b/tests/unit/variable/test_descriptor_str.py index 36b721c1..91ce0bde 100644 --- a/tests/unit/variable/test_descriptor_str.py +++ b/tests/unit/variable/test_descriptor_str.py @@ -11,7 +11,6 @@ class TestDescriptorStr: @pytest.fixture def descriptor(self): descriptor = DescriptorStr( - name='name', value='string', description='description', url='url', @@ -28,7 +27,6 @@ def test_init(self, descriptor: DescriptorStr): assert descriptor._string == 'string' # From super - assert descriptor._name == 'name' assert descriptor._description == 'description' assert descriptor._url == 'url' assert descriptor._display_name == 'display_name' @@ -38,7 +36,6 @@ def test_init_string_type_exception(self, string): # When Then Expect with pytest.raises(ValueError): DescriptorStr( - name='name', value=string, description='description', url='url', @@ -67,7 +64,7 @@ def test_repr(self, descriptor: DescriptorStr): repr_str = str(descriptor) # Expect - assert repr_str == "" + assert repr_str == "" def test_copy(self, descriptor: DescriptorStr): # When Then diff --git a/tests/unit/variable/test_parameter.py b/tests/unit/variable/test_parameter.py index 5376edf3..794a644a 100644 --- a/tests/unit/variable/test_parameter.py +++ b/tests/unit/variable/test_parameter.py @@ -19,7 +19,6 @@ class TestParameter: def parameter(self) -> Parameter: self.mock_callback = MagicMock() parameter = Parameter( - name='name', value=1, unit='m', variance=0.01, @@ -34,14 +33,7 @@ def parameter(self) -> Parameter: @pytest.fixture def normal_parameter(self) -> Parameter: - parameter = Parameter( - name='name', - value=1, - unit='m', - variance=0.01, - min=0, - max=10, - ) + parameter = Parameter(display_name='name', value=1, unit='m', variance=0.01, min=0, max=10) return parameter @pytest.fixture @@ -70,7 +62,6 @@ def test_init(self, parameter: Parameter): assert parameter._scalar.value == 1 assert parameter._scalar.unit == 'm' assert parameter._scalar.variance == 0.01 - assert parameter._name == 'name' assert parameter._description == 'description' assert parameter._url == 'url' assert parameter._display_name == 'display_name' @@ -85,7 +76,6 @@ def test_init_value_min_exception(self): # Then Expect with pytest.raises(ValueError): Parameter( - name='name', value=value, unit='m', variance=0.01, @@ -105,7 +95,6 @@ def test_init_value_max_exception(self): # Then Expect with pytest.raises(ValueError): Parameter( - name='name', value=value, unit='m', variance=0.01, @@ -120,7 +109,7 @@ def test_init_value_max_exception(self): def test_make_dependent_on(self, normal_parameter: Parameter): # When independent_parameter = Parameter( - name='independent', value=1, unit='m', variance=0.01, min=0, max=10 + display_name='independent', value=1, unit='m', variance=0.01, min=0, max=10 ) # Then @@ -147,7 +136,7 @@ def test_dependent_parameter_update_pushes_value_to_callback(self, parameter: Pa self.mock_callback.fget.side_effect = lambda: calculator['value'] self.mock_callback.fset.side_effect = lambda value: calculator.update(value=value) independent_parameter = Parameter( - name='independent', value=1, unit='m', variance=0.01, min=0, max=10 + display_name='independent', value=1, unit='m', variance=0.01, min=0, max=10 ) # Then @@ -178,7 +167,7 @@ def test_dependent_parameter_update_pushes_value_to_callback_with_desired_unit( self.mock_callback.fget.side_effect = lambda: calculator['value'] self.mock_callback.fset.side_effect = lambda value: calculator.update(value=value) independent_parameter = Parameter( - name='independent', value=1, unit='m', variance=0.01, min=0, max=10 + display_name='independent', value=1, unit='m', variance=0.01, min=0, max=10 ) # Then @@ -204,7 +193,7 @@ def test_dependent_parameter_make_dependent_on_with_desired_unit( ): # When independent_parameter = Parameter( - name='independent', value=1, unit='m', variance=0.01, min=0, max=10 + display_name='independent', value=1, unit='m', variance=0.01, min=0, max=10 ) # Then @@ -284,7 +273,7 @@ def test_dependent_parameter_make_dependent_on_with_desired_unit_incompatible_un ): # When independent_parameter = Parameter( - name='independent', value=1, unit='m', variance=0.01, min=0, max=10 + display_name='independent', value=1, unit='m', variance=0.01, min=0, max=10 ) # Then Expect @@ -300,7 +289,7 @@ def test_dependent_parameter_make_dependent_on_with_incorrect_unit_raises( ): # When independent_parameter = Parameter( - name='independent', value=1, unit='m', variance=0.01, min=0, max=10 + display_name='independent', value=1, unit='m', variance=0.01, min=0, max=10 ) # Then Expect @@ -316,7 +305,6 @@ def test_dependent_parameter_make_dependent_on_with_incorrect_unit_raises( def test_parameter_from_dependency(self, normal_parameter: Parameter): # When Then dependent_parameter = Parameter.from_dependency( - name='dependent', dependency_expression='2*a', dependency_map={'a': normal_parameter}, display_name='display_name', @@ -326,7 +314,6 @@ def test_parameter_from_dependency(self, normal_parameter: Parameter): assert dependent_parameter._independent == False assert dependent_parameter.dependency_expression == '2*a' assert dependent_parameter.dependency_map == {'a': normal_parameter} - assert dependent_parameter.name == 'dependent' assert dependent_parameter.display_name == 'display_name' self.compare_parameters(dependent_parameter, 2 * normal_parameter) @@ -339,7 +326,6 @@ def test_parameter_from_dependency(self, normal_parameter: Parameter): def test_parameter_from_dependency_with_desired_unit(self, normal_parameter: Parameter): # When Then dependent_parameter = Parameter.from_dependency( - name='dependent', dependency_expression='2*a', dependency_map={'a': normal_parameter}, display_name='display_name', @@ -350,7 +336,6 @@ def test_parameter_from_dependency_with_desired_unit(self, normal_parameter: Par assert dependent_parameter._independent == False assert dependent_parameter.dependency_expression == '2*a' assert dependent_parameter.dependency_map == {'a': normal_parameter} - assert dependent_parameter.name == 'dependent' assert dependent_parameter.display_name == 'display_name' assert dependent_parameter.value == 200 * normal_parameter.value @@ -383,7 +368,6 @@ def test_parameter_from_dependency_with_desired_unit_incompatible_unit_raises( # When Then Expect with pytest.raises(UnitError): dependent_parameter = Parameter.from_dependency( - name='dependent', dependency_expression='2*a', dependency_map={'a': normal_parameter}, display_name='display_name', @@ -393,8 +377,7 @@ def test_parameter_from_dependency_with_desired_unit_incompatible_unit_raises( def test_dependent_parameter_with_unique_name(self, clear, normal_parameter: Parameter): # When Then dependent_parameter = Parameter.from_dependency( - name='dependent', - dependency_expression='2*"Parameter_0"', + display_name='dependent', dependency_expression='2*"Parameter_0"' ) # Expect @@ -413,7 +396,7 @@ def test_process_dependency_unique_names_double_quotes( ): # When independent_parameter = Parameter( - name='independent', + display_name='independent', value=1, unit='m', variance=0.01, @@ -435,7 +418,7 @@ def test_process_dependency_unique_names_single_quotes( ): # When independent_parameter = Parameter( - name='independent', + display_name='independent', value=1, unit='m', variance=0.01, @@ -444,7 +427,7 @@ def test_process_dependency_unique_names_single_quotes( unique_name='Special_name', ) independent_parameter_2 = Parameter( - name='independent_2', + display_name='independent_2', value=1, unit='m', variance=0.01, @@ -498,9 +481,9 @@ def test_process_dependency_unique_names_exception_not_a_descriptorNumber( @pytest.mark.parametrize( 'dependency_expression, dependency_map', [ - (2, {'a': Parameter(name='a', value=1)}), - ('2*a', ['a', Parameter(name='a', value=1)]), - ('2*a', {4: Parameter(name='a', value=1)}), + (2, {'a': Parameter(display_name='a', value=1)}), + ('2*a', ['a', Parameter(display_name='a', value=1)]), + ('2*a', {4: Parameter(display_name='a', value=1)}), ('2*a', {'a': ObjBase(name='a')}), ], ids=[ @@ -516,7 +499,7 @@ def test_parameter_from_dependency_input_exceptions( # When Then Expect with pytest.raises(TypeError): Parameter.from_dependency( - name='dependent', + display_name='dependent', dependency_expression=dependency_expression, dependency_map=dependency_map, ) @@ -540,9 +523,11 @@ def test_parameter_make_dependent_on_exceptions_cleanup_previously_dependent( self, normal_parameter, dependency_expression, error ): # When - independent_parameter = Parameter(name='independent', value=10, unit='s', variance=0.02) + independent_parameter = Parameter( + display_name='independent', value=10, unit='s', variance=0.02 + ) dependent_parameter = Parameter.from_dependency( - name='dependent', + display_name='dependent', dependency_expression='best', dependency_map={'best': independent_parameter}, ) @@ -565,7 +550,9 @@ def test_parameter_make_dependent_on_exceptions_cleanup_previously_independent( self, normal_parameter ): # When - independent_parameter = Parameter(name='independent', value=10, unit='s', variance=0.02) + independent_parameter = Parameter( + display_name='independent', value=10, unit='s', variance=0.02 + ) # Then Expect # Check that the correct error is raised with pytest.raises(NameError): @@ -582,7 +569,7 @@ def test_parameter_make_dependent_on_exceptions_cleanup_previously_independent( def test_dependent_parameter_updates(self, normal_parameter: Parameter): # When dependent_parameter = Parameter.from_dependency( - name='dependent', + display_name='dependent', dependency_expression='2*a', dependency_map={'a': normal_parameter}, ) @@ -609,17 +596,17 @@ def test_dependent_parameter_updates(self, normal_parameter: Parameter): def test_dependent_parameter_indirect_updates(self, normal_parameter: Parameter): # When dependent_parameter = Parameter.from_dependency( - name='dependent', + display_name='dependent', dependency_expression='2*a', dependency_map={'a': normal_parameter}, ) dependent_parameter_2 = Parameter.from_dependency( - name='dependent_2', + display_name='dependent_2', dependency_expression='10*a', dependency_map={'a': normal_parameter}, ) dependent_parameter_3 = Parameter.from_dependency( - name='dependent_3', + display_name='dependent_3', dependency_expression='b+c', dependency_map={'b': dependent_parameter, 'c': dependent_parameter_2}, ) @@ -636,12 +623,12 @@ def test_dependent_parameter_indirect_updates(self, normal_parameter: Parameter) def test_dependent_parameter_cyclic_dependencies(self, normal_parameter: Parameter): # When dependent_parameter = Parameter.from_dependency( - name='dependent', + display_name='dependent', dependency_expression='2*a', dependency_map={'a': normal_parameter}, ) dependent_parameter_2 = Parameter.from_dependency( - name='dependent_2', + display_name='dependent_2', dependency_expression='2*b', dependency_map={'b': dependent_parameter}, ) @@ -661,7 +648,7 @@ def test_dependent_parameter_cyclic_dependencies(self, normal_parameter: Paramet def test_dependent_parameter_logical_dependency(self, normal_parameter: Parameter): # When dependent_parameter = Parameter.from_dependency( - name='dependent', + display_name='dependent', dependency_expression='a if a.value > 0 else -a', dependency_map={'a': normal_parameter}, ) @@ -675,11 +662,13 @@ def test_dependent_parameter_logical_dependency(self, normal_parameter: Paramete def test_dependent_parameter_return_is_descriptor_number(self): # When - descriptor_number = DescriptorNumber(name='descriptor', value=1, unit='m', variance=0.01) + descriptor_number = DescriptorNumber( + display_name='descriptor', value=1, unit='m', variance=0.01 + ) # Then dependent_parameter = Parameter.from_dependency( - name='dependent', + display_name='dependent', dependency_expression='2*descriptor', dependency_map={'descriptor': descriptor_number}, ) @@ -699,12 +688,9 @@ def test_dependent_parameter_division_expression_order(self): would work correctly. """ # When - angstrom = DescriptorNumber('angstrom', 1e-10, unit='m') + angstrom = DescriptorNumber(1e-10, unit='m', display_name='angstrom') jump_length = Parameter( - name='jump_length', - value=float(1.0), - fixed=False, - unit='angstrom', + display_name='jump_length', value=float(1.0), fixed=False, unit='angstrom' ) expression = 'jump_length / angstrom' @@ -718,7 +704,7 @@ def test_dependent_parameter_division_expression_order(self): expected_value = expected_result.value # Then - This should not raise an error - dependent_param = Parameter(name='a', value=1.0) + dependent_param = Parameter(display_name='a', value=1.0) dependent_param.make_dependent_on( dependency_expression=expression, dependency_map=dependency_map, @@ -729,7 +715,7 @@ def test_dependent_parameter_division_expression_order(self): # Also test the alternative expression that previously worked expression_alt = '1/angstrom * jump_length' - dependent_param_alt = Parameter(name='b', value=1.0) + dependent_param_alt = Parameter(display_name='b', value=1.0) dependent_param_alt.make_dependent_on( dependency_expression=expression_alt, dependency_map=dependency_map, @@ -739,7 +725,7 @@ def test_dependent_parameter_division_expression_order(self): def test_dependent_parameter_overwrite_dependency(self, normal_parameter: Parameter): # When dependent_parameter = Parameter.from_dependency( - name='dependent', + display_name='dependent', dependency_expression='2*a', dependency_map={'a': normal_parameter}, ) @@ -747,7 +733,7 @@ def test_dependent_parameter_overwrite_dependency(self, normal_parameter: Parame # Then normal_parameter_2 = Parameter( - name='a2', value=-2, unit='m', variance=0.01, min=-10, max=0 + display_name='a2', value=-2, unit='m', variance=0.01, min=-10, max=0 ) dependent_parameter.make_dependent_on( dependency_expression='3*a2', dependency_map={'a2': normal_parameter_2} @@ -763,7 +749,7 @@ def test_dependent_parameter_overwrite_dependency(self, normal_parameter: Parame def test_make_independent(self, normal_parameter: Parameter): # When dependent_parameter = Parameter.from_dependency( - name='dependent', + display_name='dependent', dependency_expression='2*a', dependency_map={'a': normal_parameter}, ) @@ -797,7 +783,7 @@ def test_independent_parameter_dependency_expression(self, normal_parameter: Par def test_dependent_parameter_dependency_expression_setter(self, normal_parameter: Parameter): # When dependent_parameter = Parameter.from_dependency( - name='dependent', + display_name='dependent', dependency_expression='2*a', dependency_map={'a': normal_parameter}, ) @@ -814,7 +800,7 @@ def test_independent_parameter_dependency_map(self, normal_parameter: Parameter) def test_dependent_parameter_dependency_map_setter(self, normal_parameter: Parameter): # When dependent_parameter = Parameter.from_dependency( - name='dependent', + display_name='dependent', dependency_expression='2*a', dependency_map={'a': normal_parameter}, ) @@ -839,7 +825,7 @@ def test_set_min(self, parameter: Parameter): def test_set_min_dependent_parameter(self, normal_parameter: Parameter): # When dependent_parameter = Parameter.from_dependency( - name='dependent', + display_name='dependent', dependency_expression='2*a', dependency_map={'a': normal_parameter}, ) @@ -863,7 +849,7 @@ def test_set_max(self, parameter: Parameter): def test_set_max_dependent_parameter(self, normal_parameter: Parameter): # When dependent_parameter = Parameter.from_dependency( - name='dependent', + display_name='dependent', dependency_expression='2*a', dependency_map={'a': normal_parameter}, ) @@ -890,7 +876,6 @@ def test_convert_unit(self, parameter: Parameter): def test_set_desired_unit(self, normal_parameter: Parameter): # When Then dependent_parameter = Parameter.from_dependency( - name='dependent', dependency_expression='2*a', dependency_map={'a': normal_parameter}, display_name='display_name', @@ -928,7 +913,6 @@ def test_set_desired_unit(self, normal_parameter: Parameter): def test_set_desired_unit_incompatible_units_raises(self, normal_parameter: Parameter): # When Then dependent_parameter = Parameter.from_dependency( - name='dependent', dependency_expression='2*a', dependency_map={'a': normal_parameter}, display_name='display_name', @@ -944,7 +928,6 @@ def test_set_desired_unit_incompatible_units_raises(self, normal_parameter: Para def test_set_desired_unit_None(self, normal_parameter: Parameter): # When Then dependent_parameter = Parameter.from_dependency( - name='dependent', dependency_expression='2*a', dependency_map={'a': normal_parameter}, display_name='display_name', @@ -972,7 +955,6 @@ def test_set_desired_unit_independent_parameter_raises(self, normal_parameter: P def test_set_desired_unit_incorrect_unit_type_raises(self, normal_parameter: Parameter): # When Then dependent_parameter = Parameter.from_dependency( - name='dependent', dependency_expression='2*a', dependency_map={'a': normal_parameter}, display_name='display_name', @@ -992,7 +974,7 @@ def test_set_fixed(self, parameter: Parameter): def test_set_fixed_dependent_parameter(self, normal_parameter: Parameter): # When dependent_parameter = Parameter.from_dependency( - name='dependent', + display_name='dependent', dependency_expression='2*a', dependency_map={'a': normal_parameter}, ) @@ -1031,7 +1013,9 @@ def test_set_error_exception(self, parameter: Parameter): def test_repr(self, parameter: Parameter): # When Then Expect - assert repr(parameter) == "" + assert ( + repr(parameter) == "" + ) def test_repr_fixed(self, parameter: Parameter): # When @@ -1039,7 +1023,8 @@ def test_repr_fixed(self, parameter: Parameter): # Then Expect assert ( - repr(parameter) == "" + repr(parameter) + == "" ) def test_value_match_callback(self, parameter: Parameter): @@ -1075,7 +1060,7 @@ def test_set_value(self, parameter: Parameter): def test_set_value_dependent_parameter(self, normal_parameter: Parameter): # When dependent_parameter = Parameter.from_dependency( - name='dependent', + display_name='dependent', dependency_expression='2*a', dependency_map={'a': normal_parameter}, ) @@ -1092,7 +1077,7 @@ def test_set_full_value(self, parameter: Parameter): def test_set_variance_dependent_parameter(self, normal_parameter: Parameter): # When dependent_parameter = Parameter.from_dependency( - name='dependent', + display_name='dependent', dependency_expression='2*a', dependency_map={'a': normal_parameter}, ) @@ -1104,7 +1089,7 @@ def test_set_variance_dependent_parameter(self, normal_parameter: Parameter): def test_set_error_dependent_parameter(self, normal_parameter: Parameter): # When dependent_parameter = Parameter.from_dependency( - name='dependent', + display_name='dependent', dependency_expression='2*a', dependency_map={'a': normal_parameter}, ) @@ -1123,7 +1108,6 @@ def test_copy(self, parameter: Parameter): assert id(parameter_copy._scalar) != id(parameter._scalar) assert isinstance(parameter_copy._callback, property) - assert parameter_copy._name == parameter._name assert parameter_copy._scalar == parameter._scalar assert parameter_copy._min == parameter._min assert parameter_copy._max == parameter._max @@ -1137,19 +1121,32 @@ def test_copy(self, parameter: Parameter): 'test, expected, expected_reverse', [ ( - Parameter('test', 2, 'm', 0.01, -10, 20), - Parameter('name + test', 3, 'm', 0.02, -10, 30), - Parameter('test + name', 3, 'm', 0.02, -10, 30), + Parameter(2, unit='m', variance=0.01, min=-10, max=20, display_name='test'), + Parameter(3, unit='m', variance=0.02, min=-10, max=30, display_name='name + test'), + Parameter(3, unit='m', variance=0.02, min=-10, max=30, display_name='test + name'), ), ( - Parameter('test', 2, 'm', 0.01), - Parameter('name + test', 3, 'm', 0.02, min=-np.inf, max=np.inf), - Parameter('test + name', 3, 'm', 0.02, min=-np.inf, max=np.inf), + Parameter(2, unit='m', variance=0.01, display_name='test'), + Parameter( + 3, unit='m', variance=0.02, min=-np.inf, max=np.inf, display_name='name + test' + ), + Parameter( + 3, unit='m', variance=0.02, min=-np.inf, max=np.inf, display_name='test + name' + ), ), ( - Parameter('test', 2, 'cm', 0.01, -10, 10), - Parameter('name + test', 1.02, 'm', 0.010001, -0.1, 10.1), - Parameter('test + name', 102, 'cm', 100.01, -10, 1010), + Parameter(2, unit='cm', variance=0.01, min=-10, max=10, display_name='test'), + Parameter( + 1.02, + unit='m', + variance=0.010001, + min=-0.1, + max=10.1, + display_name='name + test', + ), + Parameter( + 102, unit='cm', variance=100.01, min=-10, max=1010, display_name='test + name' + ), ), ], ids=['regular', 'no_bounds', 'unit_conversion'], @@ -1169,14 +1166,12 @@ def test_addition_with_parameter( result_reverse = test + parameter # Expect - assert result.name == result.unique_name assert result.value == expected.value assert result.unit == expected.unit assert result.variance == expected.variance assert result.min == expected.min assert result.max == expected.max - assert result_reverse.name == result_reverse.unique_name assert result_reverse.value == expected_reverse.value assert result_reverse.unit == expected_reverse.unit assert result_reverse.variance == expected_reverse.variance @@ -1187,21 +1182,19 @@ def test_addition_with_parameter( def test_addition_with_scalar(self): # When - parameter = Parameter(name='name', value=1, variance=0.01, min=0, max=10) + parameter = Parameter(display_name='name', value=1, variance=0.01, min=0, max=10) # Then result = parameter + 1.0 result_reverse = 1.0 + parameter # Expect - assert result.name == result.unique_name assert result.value == 2.0 assert result.unit == 'dimensionless' assert result.variance == 0.01 assert result.min == 1.0 assert result.max == 11.0 - assert result_reverse.name == result_reverse.unique_name assert result_reverse.value == 2.0 assert result_reverse.unit == 'dimensionless' assert result_reverse.variance == 0.01 @@ -1211,7 +1204,7 @@ def test_addition_with_scalar(self): def test_addition_with_descriptor_number(self, parameter: Parameter): # When parameter._callback = property() - descriptor_number = DescriptorNumber(name='test', value=1, variance=0.1, unit='cm') + descriptor_number = DescriptorNumber(display_name='test', value=1, variance=0.1, unit='cm') # Then result = parameter + descriptor_number @@ -1219,7 +1212,6 @@ def test_addition_with_descriptor_number(self, parameter: Parameter): # Expect assert type(result) == Parameter - assert result.name == result.unique_name assert result.value == 1.01 assert result.unit == 'm' assert result.variance == 0.01001 @@ -1227,7 +1219,6 @@ def test_addition_with_descriptor_number(self, parameter: Parameter): assert result.max == 10.01 assert type(result_reverse) == Parameter - assert result_reverse.name == result_reverse.unique_name assert result_reverse.value == 101.0 assert result_reverse.unit == 'cm' assert result_reverse.variance == 100.1 @@ -1241,11 +1232,7 @@ def test_addition_with_descriptor_number(self, parameter: Parameter): 'test', [ 1.0, - Parameter( - 'test', - 2, - 's', - ), + Parameter(2, unit='s', display_name='test'), ], ids=['add_scalar_to_unit', 'incompatible_units'], ) @@ -1260,19 +1247,39 @@ def test_addition_exception(self, parameter: Parameter, test): 'test, expected, expected_reverse', [ ( - Parameter('test', 2, 'm', 0.01, -20, 20), - Parameter('name - test', -1, 'm', 0.02, -20, 30), - Parameter('test - name', 1, 'm', 0.02, -30, 20), + Parameter(2, unit='m', variance=0.01, min=-20, max=20, display_name='test'), + Parameter( + -1, unit='m', variance=0.02, min=-20, max=30, display_name='name - test' + ), + Parameter(1, unit='m', variance=0.02, min=-30, max=20, display_name='test - name'), ), ( - Parameter('test', 2, 'm', 0.01), - Parameter('name - test', -1, 'm', 0.02, min=-np.inf, max=np.inf), - Parameter('test - name', 1, 'm', 0.02, min=-np.inf, max=np.inf), + Parameter(2, unit='m', variance=0.01, display_name='test'), + Parameter( + -1, + unit='m', + variance=0.02, + min=-np.inf, + max=np.inf, + display_name='name - test', + ), + Parameter( + 1, unit='m', variance=0.02, min=-np.inf, max=np.inf, display_name='test - name' + ), ), ( - Parameter('test', 2, 'cm', 0.01, -10, 10), - Parameter('name - test', 0.98, 'm', 0.010001, -0.1, 10.1), - Parameter('test - name', -98, 'cm', 100.01, -1010, 10), + Parameter(2, unit='cm', variance=0.01, min=-10, max=10, display_name='test'), + Parameter( + 0.98, + unit='m', + variance=0.010001, + min=-0.1, + max=10.1, + display_name='name - test', + ), + Parameter( + -98, unit='cm', variance=100.01, min=-1010, max=10, display_name='test - name' + ), ), ], ids=['regular', 'no_bounds', 'unit_conversion'], @@ -1292,14 +1299,12 @@ def test_subtraction_with_parameter( result_reverse = test - parameter # Expect - assert result.name == result.unique_name assert result.value == expected.value assert result.unit == expected.unit assert result.variance == expected.variance assert result.min == expected.min assert result.max == expected.max - assert result_reverse.name == result_reverse.unique_name assert result_reverse.value == expected_reverse.value assert result_reverse.unit == expected_reverse.unit assert result_reverse.variance == expected_reverse.variance @@ -1310,22 +1315,20 @@ def test_subtraction_with_parameter( def test_subtraction_with_parameter_nan_cases(self): # When - parameter = Parameter(name='name', value=1, variance=0.01, min=-np.inf, max=np.inf) - test = Parameter(name='test', value=2, variance=0.01, min=-np.inf, max=np.inf) + parameter = Parameter(display_name='name', value=1, variance=0.01, min=-np.inf, max=np.inf) + test = Parameter(display_name='test', value=2, variance=0.01, min=-np.inf, max=np.inf) # Then result = parameter - test result_reverse = test - parameter # Expect - assert result.name == result.unique_name assert result.value == -1.0 assert result.unit == 'dimensionless' assert result.variance == 0.02 assert result.min == -np.inf assert result.max == np.inf - assert result_reverse.name == result_reverse.unique_name assert result_reverse.value == 1.0 assert result_reverse.unit == 'dimensionless' assert result_reverse.variance == 0.02 @@ -1334,21 +1337,19 @@ def test_subtraction_with_parameter_nan_cases(self): def test_subtraction_with_scalar(self): # When - parameter = Parameter(name='name', value=2, variance=0.01, min=0, max=10) + parameter = Parameter(display_name='name', value=2, variance=0.01, min=0, max=10) # Then result = parameter - 1.0 result_reverse = 1.0 - parameter # Expect - assert result.name == result.unique_name assert result.value == 1.0 assert result.unit == 'dimensionless' assert result.variance == 0.01 assert result.min == -1.0 assert result.max == 9.0 - assert result_reverse.name == result_reverse.unique_name assert result_reverse.value == -1.0 assert result_reverse.unit == 'dimensionless' assert result_reverse.variance == 0.01 @@ -1358,7 +1359,7 @@ def test_subtraction_with_scalar(self): def test_subtraction_with_descriptor_number(self, parameter: Parameter): # When parameter._callback = property() - descriptor_number = DescriptorNumber(name='test', value=1, variance=0.1, unit='cm') + descriptor_number = DescriptorNumber(display_name='test', value=1, variance=0.1, unit='cm') # Then result = parameter - descriptor_number @@ -1366,7 +1367,6 @@ def test_subtraction_with_descriptor_number(self, parameter: Parameter): # Expect assert type(result) == Parameter - assert result.name == result.unique_name assert result.value == 0.99 assert result.unit == 'm' assert result.variance == 0.01001 @@ -1374,7 +1374,6 @@ def test_subtraction_with_descriptor_number(self, parameter: Parameter): assert result.max == 9.99 assert type(result_reverse) == Parameter - assert result_reverse.name == result_reverse.unique_name assert result_reverse.value == -99.0 assert result_reverse.unit == 'cm' assert result_reverse.variance == 100.1 @@ -1388,11 +1387,7 @@ def test_subtraction_with_descriptor_number(self, parameter: Parameter): 'test', [ 1.0, - Parameter( - 'test', - 2, - 's', - ), + Parameter(2, unit='s', display_name='test'), ], ids=['sub_scalar_to_unit', 'incompatible_units'], ) @@ -1407,19 +1402,41 @@ def test_subtraction_exception(self, parameter: Parameter, test): 'test, expected, expected_reverse', [ ( - Parameter('test', 2, 'm', 0.01, -10, 20), - Parameter('name * test', 2, 'm^2', 0.05, -100, 200), - Parameter('test * name', 2, 'm^2', 0.05, -100, 200), + Parameter(2, unit='m', variance=0.01, min=-10, max=20, display_name='test'), + Parameter( + 2, unit='m^2', variance=0.05, min=-100, max=200, display_name='name * test' + ), + Parameter( + 2, unit='m^2', variance=0.05, min=-100, max=200, display_name='test * name' + ), ), ( - Parameter('test', 2, 'm', 0.01), - Parameter('name * test', 2, 'm^2', 0.05, min=-np.inf, max=np.inf), - Parameter('test * name', 2, 'm^2', 0.05, min=-np.inf, max=np.inf), + Parameter(2, unit='m', variance=0.01, display_name='test'), + Parameter( + 2, + unit='m^2', + variance=0.05, + min=-np.inf, + max=np.inf, + display_name='name * test', + ), + Parameter( + 2, + unit='m^2', + variance=0.05, + min=-np.inf, + max=np.inf, + display_name='test * name', + ), ), ( - Parameter('test', 2, 'dm', 0.01, -10, 20), - Parameter('name * test', 0.2, 'm^2', 0.0005, -10, 20), - Parameter('test * name', 0.2, 'm^2', 0.0005, -10, 20), + Parameter(2, unit='dm', variance=0.01, min=-10, max=20, display_name='test'), + Parameter( + 0.2, unit='m^2', variance=0.0005, min=-10, max=20, display_name='name * test' + ), + Parameter( + 0.2, unit='m^2', variance=0.0005, min=-10, max=20, display_name='test * name' + ), ), ], ids=['regular', 'no_bounds', 'base_unit_conversion'], @@ -1439,14 +1456,12 @@ def test_multiplication_with_parameter( result_reverse = test * parameter # Expect - assert result.name == result.unique_name assert result.value == expected.value assert result.unit == expected.unit assert result.variance == pytest.approx(expected.variance) assert result.min == expected.min assert result.max == expected.max - assert result_reverse.name == result_reverse.unique_name assert result_reverse.value == expected_reverse.value assert result_reverse.unit == expected_reverse.unit assert result_reverse.variance == pytest.approx(expected_reverse.variance) @@ -1457,35 +1472,61 @@ def test_multiplication_with_parameter( 'test, expected, expected_reverse', [ ( - Parameter('test', 0, '', 0.01, -10, 0), - Parameter('name * test', 0.0, 'dimensionless', 0.01, -np.inf, 0), - Parameter('test * name', 0, 'dimensionless', 0.01, -np.inf, 0), + Parameter(0, unit='', variance=0.01, min=-10, max=0, display_name='test'), + Parameter( + 0.0, + unit='dimensionless', + variance=0.01, + min=-np.inf, + max=0, + display_name='name * test', + ), + Parameter( + 0, + unit='dimensionless', + variance=0.01, + min=-np.inf, + max=0, + display_name='test * name', + ), ), ( - Parameter('test', 0, '', 0.01, 0, 10), - Parameter('name * test', 0.0, 'dimensionless', 0.01, 0, np.inf), - Parameter('test * name', 0, 'dimensionless', 0.01, 0, np.inf), + Parameter(0, unit='', variance=0.01, min=0, max=10, display_name='test'), + Parameter( + 0.0, + unit='dimensionless', + variance=0.01, + min=0, + max=np.inf, + display_name='name * test', + ), + Parameter( + 0, + unit='dimensionless', + variance=0.01, + min=0, + max=np.inf, + display_name='test * name', + ), ), ], ids=['zero_min', 'zero_max'], ) def test_multiplication_with_parameter_nan_cases(self, test, expected, expected_reverse): # When - parameter = Parameter(name='name', value=1, variance=0.01, min=1, max=np.inf) + parameter = Parameter(display_name='name', value=1, variance=0.01, min=1, max=np.inf) # Then result = parameter * test result_reverse = test * parameter # Expect - assert result.name == result.unique_name assert result.value == expected.value assert result.unit == expected.unit assert result.variance == expected.variance assert result.min == expected.min assert result.max == expected.max - assert result_reverse.name == result_reverse.unique_name assert result_reverse.value == expected_reverse.value assert result_reverse.unit == expected_reverse.unit assert result_reverse.variance == expected_reverse.variance @@ -1496,14 +1537,18 @@ def test_multiplication_with_parameter_nan_cases(self, test, expected, expected_ 'test, expected, expected_reverse', [ ( - DescriptorNumber(name='test', value=2, variance=0.1, unit='cm'), - Parameter('name * test', 2, 'dm^2', 0.14, 0, 20), - Parameter('test * name', 2, 'dm^2', 0.14, 0, 20), + DescriptorNumber(display_name='test', value=2, variance=0.1, unit='cm'), + Parameter( + 2, unit='dm^2', variance=0.14, min=0, max=20, display_name='name * test' + ), + Parameter( + 2, unit='dm^2', variance=0.14, min=0, max=20, display_name='test * name' + ), ), ( - DescriptorNumber(name='test', value=0, variance=0.1, unit='cm'), - DescriptorNumber('name * test', 0, 'dm^2', 0.1), - DescriptorNumber('test * name', 0, 'dm^2', 0.1), + DescriptorNumber(display_name='test', value=0, variance=0.1, unit='cm'), + DescriptorNumber(0, unit='dm^2', variance=0.1, display_name='name * test'), + DescriptorNumber(0, unit='dm^2', variance=0.1, display_name='test * name'), ), ], ids=['regular', 'zero_value'], @@ -1520,7 +1565,6 @@ def test_multiplication_with_descriptor_number( # Expect assert type(result) == type(expected) - assert result.name == result.unique_name assert result.value == expected.value assert result.unit == expected.unit assert result.variance == expected.variance @@ -1529,7 +1573,6 @@ def test_multiplication_with_descriptor_number( assert result.max == expected.max assert type(result_reverse) == type(expected_reverse) - assert result_reverse.name == result_reverse.unique_name assert result_reverse.value == expected_reverse.value assert result_reverse.unit == expected_reverse.unit assert result_reverse.variance == expected_reverse.variance @@ -1542,13 +1585,13 @@ def test_multiplication_with_descriptor_number( [ ( 2, - Parameter('name * 2', 2, 'm', 0.04, 0, 20), - Parameter('2 * name', 2, 'm', 0.04, 0, 20), + Parameter(2, unit='m', variance=0.04, min=0, max=20, display_name='name * 2'), + Parameter(2, unit='m', variance=0.04, min=0, max=20, display_name='2 * name'), ), ( 0, - DescriptorNumber('name * 0', 0, 'm', 0), - DescriptorNumber('0 * name', 0, 'm', 0), + DescriptorNumber(0, unit='m', variance=0, display_name='name * 0'), + DescriptorNumber(0, unit='m', variance=0, display_name='0 * name'), ), ], ids=['regular', 'zero_value'], @@ -1565,7 +1608,6 @@ def test_multiplication_with_scalar( # Expect assert type(result) == type(expected) - assert result.name == result.unique_name assert result.value == expected.value assert result.unit == expected.unit assert result.variance == expected.variance @@ -1573,7 +1615,6 @@ def test_multiplication_with_scalar( assert result.min == expected.min assert result.max == expected.max - assert result_reverse.name == result_reverse.unique_name assert result_reverse.value == expected_reverse.value assert result_reverse.unit == expected_reverse.unit assert result_reverse.variance == expected_reverse.variance @@ -1585,19 +1626,51 @@ def test_multiplication_with_scalar( 'test, expected, expected_reverse', [ ( - Parameter('test', 2, 's', 0.01, -10, 20), - Parameter('name / test', 0.5, 'm/s', 0.003125, -np.inf, np.inf), - Parameter('test / name', 2, 's/m', 0.05, -np.inf, np.inf), + Parameter(2, unit='s', variance=0.01, min=-10, max=20, display_name='test'), + Parameter( + 0.5, + unit='m/s', + variance=0.003125, + min=-np.inf, + max=np.inf, + display_name='name / test', + ), + Parameter( + 2, + unit='s/m', + variance=0.05, + min=-np.inf, + max=np.inf, + display_name='test / name', + ), ), ( - Parameter('test', 2, 's', 0.01, 0, 20), - Parameter('name / test', 0.5, 'm/s', 0.003125, 0.0, np.inf), - Parameter('test / name', 2, 's/m', 0.05, 0.0, np.inf), + Parameter(2, unit='s', variance=0.01, min=0, max=20, display_name='test'), + Parameter( + 0.5, + unit='m/s', + variance=0.003125, + min=0.0, + max=np.inf, + display_name='name / test', + ), + Parameter( + 2, unit='s/m', variance=0.05, min=0.0, max=np.inf, display_name='test / name' + ), ), ( - Parameter('test', -2, 's', 0.01, -10, 0), - Parameter('name / test', -0.5, 'm/s', 0.003125, -np.inf, 0.0), - Parameter('test / name', -2, 's/m', 0.05, -np.inf, 0.0), + Parameter(-2, unit='s', variance=0.01, min=-10, max=0, display_name='test'), + Parameter( + -0.5, + unit='m/s', + variance=0.003125, + min=-np.inf, + max=0.0, + display_name='name / test', + ), + Parameter( + -2, unit='s/m', variance=0.05, min=-np.inf, max=0.0, display_name='test / name' + ), ), ], ids=['crossing_zero', 'only_positive', 'only_negative'], @@ -1612,7 +1685,6 @@ def test_division_with_parameter(self, parameter: Parameter, test, expected, exp # Expect assert type(result) == Parameter - assert result.name == result.unique_name assert result.value == pytest.approx(expected.value) assert result.unit == expected.unit assert result.variance == pytest.approx(expected.variance) @@ -1620,7 +1692,6 @@ def test_division_with_parameter(self, parameter: Parameter, test, expected, exp assert result.max == expected.max assert type(result) == Parameter - assert result_reverse.name == result_reverse.unique_name assert result_reverse.value == pytest.approx(expected_reverse.value) assert result_reverse.unit == expected_reverse.unit assert result_reverse.variance == pytest.approx(expected_reverse.variance) @@ -1631,19 +1702,35 @@ def test_division_with_parameter(self, parameter: Parameter, test, expected, exp 'first, second, expected', [ ( - Parameter('name', 1, 'm', 0.01, -10, 20), - Parameter('test', -2, 's', 0.01, -10, 0), - Parameter('name / test', -0.5, 'm/s', 0.003125, -np.inf, np.inf), + Parameter(1, unit='m', variance=0.01, min=-10, max=20, display_name='name'), + Parameter(-2, unit='s', variance=0.01, min=-10, max=0, display_name='test'), + Parameter( + -0.5, + unit='m/s', + variance=0.003125, + min=-np.inf, + max=np.inf, + display_name='name / test', + ), ), ( - Parameter('name', -10, 'm', 0.01, -20, -10), - Parameter('test', -2, 's', 0.01, -10, 0), - Parameter('name / test', 5.0, 'm/s', 0.065, 1, np.inf), + Parameter(-10, unit='m', variance=0.01, min=-20, max=-10, display_name='name'), + Parameter(-2, unit='s', variance=0.01, min=-10, max=0, display_name='test'), + Parameter( + 5.0, unit='m/s', variance=0.065, min=1, max=np.inf, display_name='name / test' + ), ), ( - Parameter('name', 10, 'm', 0.01, 10, 20), - Parameter('test', -20, 's', 0.01, -20, -10), - Parameter('name / test', -0.5, 'm/s', 3.125e-5, -2, -0.5), + Parameter(10, unit='m', variance=0.01, min=10, max=20, display_name='name'), + Parameter(-20, unit='s', variance=0.01, min=-20, max=-10, display_name='test'), + Parameter( + -0.5, + unit='m/s', + variance=3.125e-5, + min=-2, + max=-0.5, + display_name='name / test', + ), ), ], ids=[ @@ -1657,7 +1744,6 @@ def test_division_with_parameter_remaining_cases(self, first, second, expected): result = first / second # Expect - assert result.name == result.unique_name assert result.value == expected.value assert result.unit == expected.unit assert result.variance == expected.variance @@ -1668,14 +1754,20 @@ def test_division_with_parameter_remaining_cases(self, first, second, expected): 'test, expected, expected_reverse', [ ( - DescriptorNumber(name='test', value=2, variance=0.1, unit='s'), - Parameter('name / test', 0.5, 'm/s', 0.00875, 0, 5), - Parameter('test / name', 2, 's/m', 0.14, 0.2, np.inf), + DescriptorNumber(display_name='test', value=2, variance=0.1, unit='s'), + Parameter( + 0.5, unit='m/s', variance=0.00875, min=0, max=5, display_name='name / test' + ), + Parameter( + 2, unit='s/m', variance=0.14, min=0.2, max=np.inf, display_name='test / name' + ), ), ( 2, - Parameter('name / 2', 0.5, 'm', 0.0025, 0, 5), - Parameter('2 / name', 2, 'm**-1', 0.04, 0.2, np.inf), + Parameter(0.5, unit='m', variance=0.0025, min=0, max=5, display_name='name / 2'), + Parameter( + 2, unit='m**-1', variance=0.04, min=0.2, max=np.inf, display_name='2 / name' + ), ), ], ids=['descriptor_number', 'number'], @@ -1692,7 +1784,6 @@ def test_division_with_descriptor_number_and_number( # Expect assert type(result) == Parameter - assert result.name == result.unique_name assert result.value == expected.value assert result.unit == expected.unit assert result.variance == expected.variance @@ -1700,7 +1791,6 @@ def test_division_with_descriptor_number_and_number( assert result.max == expected.max assert type(result_reverse) == Parameter - assert result_reverse.name == result_reverse.unique_name assert result_reverse.value == expected_reverse.value assert result_reverse.unit == expected_reverse.unit assert result_reverse.variance == expected_reverse.variance @@ -1711,10 +1801,10 @@ def test_division_with_descriptor_number_and_number( 'test, expected', [ ( - DescriptorNumber(name='test', value=0, variance=0.1, unit='s'), - DescriptorNumber('test / name', 0.0, 's/m', 0.1), + DescriptorNumber(display_name='test', value=0, variance=0.1, unit='s'), + DescriptorNumber(0.0, unit='s/m', variance=0.1, display_name='test / name'), ), - (0, DescriptorNumber('0 / name', 0.0, '1/m', 0.0)), + (0, DescriptorNumber(0.0, unit='1/m', variance=0.0, display_name='0 / name')), ], ids=['descriptor_number', 'number'], ) @@ -1727,7 +1817,6 @@ def test_zero_value_divided_by_parameter(self, parameter: Parameter, test, expec # Expect assert type(result) == DescriptorNumber - assert result.name == result.unique_name assert result.value == expected.value assert result.unit == expected.unit assert result.variance == expected.variance @@ -1736,29 +1825,59 @@ def test_zero_value_divided_by_parameter(self, parameter: Parameter, test, expec 'first, second, expected', [ ( - DescriptorNumber('name', 1, 'm', 0.01), - Parameter('test', 2, 's', 0.1, -10, 10), - Parameter('name / test', 0.5, 'm/s', 0.00875, -np.inf, np.inf), + DescriptorNumber(1, unit='m', variance=0.01, display_name='name'), + Parameter(2, unit='s', variance=0.1, min=-10, max=10, display_name='test'), + Parameter( + 0.5, + unit='m/s', + variance=0.00875, + min=-np.inf, + max=np.inf, + display_name='name / test', + ), ), ( - DescriptorNumber('name', -1, 'm', 0.01), - Parameter('test', 2, 's', 0.1, 0, 10), - Parameter('name / test', -0.5, 'm/s', 0.00875, -np.inf, -0.1), + DescriptorNumber(-1, unit='m', variance=0.01, display_name='name'), + Parameter(2, unit='s', variance=0.1, min=0, max=10, display_name='test'), + Parameter( + -0.5, + unit='m/s', + variance=0.00875, + min=-np.inf, + max=-0.1, + display_name='name / test', + ), ), ( - DescriptorNumber('name', 1, 'm', 0.01), - Parameter('test', -2, 's', 0.1, -10, 0), - Parameter('name / test', -0.5, 'm/s', 0.00875, -np.inf, -0.1), + DescriptorNumber(1, unit='m', variance=0.01, display_name='name'), + Parameter(-2, unit='s', variance=0.1, min=-10, max=0, display_name='test'), + Parameter( + -0.5, + unit='m/s', + variance=0.00875, + min=-np.inf, + max=-0.1, + display_name='name / test', + ), ), ( - DescriptorNumber('name', -1, 'm', 0.01), - Parameter('test', -2, 's', 0.1, -10, 0), - Parameter('name / test', 0.5, 'm/s', 0.00875, 0.1, np.inf), + DescriptorNumber(-1, unit='m', variance=0.01, display_name='name'), + Parameter(-2, unit='s', variance=0.1, min=-10, max=0, display_name='test'), + Parameter( + 0.5, + unit='m/s', + variance=0.00875, + min=0.1, + max=np.inf, + display_name='name / test', + ), ), ( - DescriptorNumber('name', 1, 'm', 0.01), - Parameter('test', 2, 's', 0.1, 1, 10), - Parameter('name / test', 0.5, 'm/s', 0.00875, 0.1, 1), + DescriptorNumber(1, unit='m', variance=0.01, display_name='name'), + Parameter(2, unit='s', variance=0.1, min=1, max=10, display_name='test'), + Parameter( + 0.5, unit='m/s', variance=0.00875, min=0.1, max=1, display_name='name / test' + ), ), ], ids=[ @@ -1774,7 +1893,6 @@ def test_division_with_descriptor_number_missing_cases(self, first, second, expe result = first / second # Expect - assert result.name == result.unique_name assert result.value == expected.value assert result.unit == expected.unit assert result.variance == expected.variance @@ -1783,7 +1901,7 @@ def test_division_with_descriptor_number_missing_cases(self, first, second, expe @pytest.mark.parametrize( 'test', - [0, DescriptorNumber('test', 0, 's', 0.1)], + [0, DescriptorNumber(0, unit='s', variance=0.1, display_name='test')], ids=['number', 'descriptor_number'], ) def test_divide_parameter_by_zero(self, parameter: Parameter, test): @@ -1796,8 +1914,8 @@ def test_divide_parameter_by_zero(self, parameter: Parameter, test): def test_divide_by_zero_value_parameter(self): # When - descriptor = DescriptorNumber('test', 1, 's', 0.1) - parameter = Parameter('name', 0, 'm', 0.01) + descriptor = DescriptorNumber(1, unit='s', variance=0.1, display_name='test') + parameter = Parameter(0, unit='m', variance=0.01, display_name='name') # Then Expect with pytest.raises(ZeroDivisionError): @@ -1806,14 +1924,41 @@ def test_divide_by_zero_value_parameter(self): @pytest.mark.parametrize( 'test, expected', [ - (3, Parameter('name ** 3', 125, 'm^3', 281.25, -125, 1000)), - (2, Parameter('name ** 2', 25, 'm^2', 5.0, 0, 100)), - (-1, Parameter('name ** -1', 0.2, '1/m', 8e-5, -np.inf, np.inf)), - (-2, Parameter('name ** -2', 0.04, '1/m^2', 1.28e-5, 0, np.inf)), - (0, DescriptorNumber('name ** 0', 1, 'dimensionless', 0)), ( - DescriptorNumber('test', 2), - Parameter('name ** test', 25, 'm^2', 5.0, 0, 100), + 3, + Parameter( + 125, unit='m^3', variance=281.25, min=-125, max=1000, display_name='name ** 3' + ), + ), + (2, Parameter(25, unit='m^2', variance=5.0, min=0, max=100, display_name='name ** 2')), + ( + -1, + Parameter( + 0.2, + unit='1/m', + variance=8e-5, + min=-np.inf, + max=np.inf, + display_name='name ** -1', + ), + ), + ( + -2, + Parameter( + 0.04, + unit='1/m^2', + variance=1.28e-5, + min=0, + max=np.inf, + display_name='name ** -2', + ), + ), + (0, DescriptorNumber(1, unit='dimensionless', variance=0, display_name='name ** 0')), + ( + DescriptorNumber(2, display_name='test'), + Parameter( + 25, unit='m^2', variance=5.0, min=0, max=100, display_name='name ** test' + ), ), ], ids=[ @@ -1827,14 +1972,13 @@ def test_divide_by_zero_value_parameter(self): ) def test_power_of_parameter(self, test, expected): # When - parameter = Parameter('name', 5, 'm', 0.05, -5, 10) + parameter = Parameter(5, unit='m', variance=0.05, min=-5, max=10, display_name='name') # Then result = parameter**test # Expect assert type(result) == type(expected) - assert result.name == result.unique_name assert result.value == expected.value assert result.unit == expected.unit assert result.variance == expected.variance @@ -1846,46 +1990,73 @@ def test_power_of_parameter(self, test, expected): 'test, exponent, expected', [ ( - Parameter('name', 5, 'm', 0.05, 0, 10), + Parameter(5, unit='m', variance=0.05, min=0, max=10, display_name='name'), -1, - Parameter('name ** -1', 0.2, '1/m', 8e-5, 0.1, np.inf), + Parameter( + 0.2, unit='1/m', variance=8e-5, min=0.1, max=np.inf, display_name='name ** -1' + ), ), ( - Parameter('name', -5, 'm', 0.05, -5, 0), + Parameter(-5, unit='m', variance=0.05, min=-5, max=0, display_name='name'), -1, - Parameter('name ** -1', -0.2, '1/m', 8e-5, -np.inf, -0.2), + Parameter( + -0.2, + unit='1/m', + variance=8e-5, + min=-np.inf, + max=-0.2, + display_name='name ** -1', + ), ), ( - Parameter('name', 5, 'm', 0.05, 5, 10), + Parameter(5, unit='m', variance=0.05, min=5, max=10, display_name='name'), -1, - Parameter('name ** -1', 0.2, '1/m', 8e-5, 0.1, 0.2), + Parameter( + 0.2, unit='1/m', variance=8e-5, min=0.1, max=0.2, display_name='name ** -1' + ), ), ( - Parameter('name', -5, 'm', 0.05, -10, -5), + Parameter(-5, unit='m', variance=0.05, min=-10, max=-5, display_name='name'), -1, - Parameter('name ** -1', -0.2, '1/m', 8e-5, -0.2, -0.1), + Parameter( + -0.2, unit='1/m', variance=8e-5, min=-0.2, max=-0.1, display_name='name ** -1' + ), ), ( - Parameter('name', -5, 'm', 0.05, -10, -5), + Parameter(-5, unit='m', variance=0.05, min=-10, max=-5, display_name='name'), -2, - Parameter('name ** -2', 0.04, '1/m^2', 1.28e-5, 0.01, 0.04), + Parameter( + 0.04, + unit='1/m^2', + variance=1.28e-5, + min=0.01, + max=0.04, + display_name='name ** -2', + ), ), ( - Parameter('name', 5, '', 0.1, 1, 10), + Parameter(5, unit='', variance=0.1, min=1, max=10, display_name='name'), 0.3, Parameter( - 'name ** 0.3', 1.6206565966927624, - '', - 0.0009455500095853564, - 1, - 1.9952623149688795, + unit='', + variance=0.0009455500095853564, + min=1, + max=1.9952623149688795, + display_name='name ** 0.3', ), ), ( - Parameter('name', 5, '', 0.1), + Parameter(5, unit='', variance=0.1, display_name='name'), 0.5, - Parameter('name ** 0.5', 2.23606797749979, '', 0.005, 0, np.inf), + Parameter( + 2.23606797749979, + unit='', + variance=0.005, + min=0, + max=np.inf, + display_name='name ** 0.5', + ), ), ], ids=[ @@ -1903,7 +2074,6 @@ def test_power_of_diffent_parameters(self, test, exponent, expected): result = test**exponent # Expect - assert result.name == result.unique_name assert result.value == expected.value assert result.unit == expected.unit assert result.variance == expected.variance @@ -1914,17 +2084,17 @@ def test_power_of_diffent_parameters(self, test, exponent, expected): 'parameter, exponent, expected', [ ( - Parameter('name', 5, 'm'), - DescriptorNumber('test', 2, unit='s'), + Parameter(5, unit='m', display_name='name'), + DescriptorNumber(2, unit='s', display_name='test'), UnitError, ), ( - Parameter('name', 5, 'm'), - DescriptorNumber('test', 2, variance=0.01), + Parameter(5, unit='m', display_name='name'), + DescriptorNumber(2, variance=0.01, display_name='test'), ValueError, ), - (Parameter('name', 5, 'm'), 0.5, UnitError), - (Parameter('name', -5, ''), 0.5, ValueError), + (Parameter(5, unit='m', display_name='name'), 0.5, UnitError), + (Parameter(-5, unit='', display_name='name'), 0.5, ValueError), ], ids=[ 'exponent_unit', @@ -1940,13 +2110,12 @@ def test_power_exceptions(self, parameter, exponent, expected): def test_negation(self): # When - parameter = Parameter('name', 5, 'm', 0.05, -5, 10) + parameter = Parameter(5, unit='m', variance=0.05, min=-5, max=10, display_name='name') # Then result = -parameter # Expect - assert result.name == result.unique_name assert result.value == -5 assert result.unit == 'm' assert result.variance == 0.05 @@ -1957,12 +2126,12 @@ def test_negation(self): 'test, expected', [ ( - Parameter('name', -5, 'm', 0.05, -10, -5), - Parameter('abs(name)', 5, 'm', 0.05, 5, 10), + Parameter(-5, unit='m', variance=0.05, min=-10, max=-5, display_name='name'), + Parameter(5, unit='m', variance=0.05, min=5, max=10, display_name='abs(name)'), ), ( - Parameter('name', 5, 'm', 0.05, -10, 10), - Parameter('abs(name)', 5, 'm', 0.05, 0, 10), + Parameter(5, unit='m', variance=0.05, min=-10, max=10, display_name='name'), + Parameter(5, unit='m', variance=0.05, min=0, max=10, display_name='abs(name)'), ), ], ids=['pure_negative', 'crossing_zero'], @@ -1972,9 +2141,27 @@ def test_abs(self, test, expected): result = abs(test) # Expect - assert result.name == result.unique_name assert result.value == expected.value assert result.unit == expected.unit assert result.variance == expected.variance assert result.min == expected.min assert result.max == expected.max + + +@pytest.mark.parametrize('label', [None, '', 'label'], ids=['unset', 'empty', 'explicit']) +def test_display_name_serialization_preserves_unset_state(label): + # Given + p = Parameter(2, display_name=label) + + # When + encoded = p.to_dict() + + # Then Expect: an unset label is omitted rather than stored as the fallback + if label is None: + assert 'display_name' not in encoded + else: + assert encoded['display_name'] == label + + restored = Parameter.from_dict(p.to_dict(skip=['unique_name'])) + assert restored.unique_name != p.unique_name + assert restored.display_name == (restored.unique_name if label is None else label) diff --git a/tests/unit/variable/test_parameter_dependency_serialization.py b/tests/unit/variable/test_parameter_dependency_serialization.py index 98daed45..5618b606 100644 --- a/tests/unit/variable/test_parameter_dependency_serialization.py +++ b/tests/unit/variable/test_parameter_dependency_serialization.py @@ -37,7 +37,7 @@ def clear_global_map(self): def test_independent_parameter_serialization(self, clear_global_map): """Test that independent parameters serialize normally without dependency info.""" - param = Parameter(name='test', value=5.0, unit='m', min=0, max=10) + param = Parameter(display_name='test', value=5.0, unit='m', min=0, max=10) # Serialize serialized = param.to_dict() @@ -52,7 +52,7 @@ def test_independent_parameter_serialization(self, clear_global_map): new_param = Parameter.from_dict(serialized) # Should be identical - assert new_param.name == param.name + assert new_param.display_name == param.display_name assert new_param.value == param.value assert new_param.unit == param.unit assert new_param.independent is True @@ -60,11 +60,11 @@ def test_independent_parameter_serialization(self, clear_global_map): def test_dependent_parameter_serialization(self, clear_global_map): """Test serialization of parameters with dependencies.""" # Create independent parameter - a = Parameter(name='a', value=2.0, unit='m', min=0, max=10) + a = Parameter(display_name='a', value=2.0, unit='m', min=0, max=10) # Create dependent parameter b = Parameter.from_dependency( - name='b', dependency_expression='2 * a', dependency_map={'a': a}, unit='m' + display_name='b', dependency_expression='2 * a', dependency_map={'a': a}, unit='m' ) # Serialize dependent parameter @@ -92,11 +92,11 @@ def test_dependent_parameter_serialization(self, clear_global_map): def test_dependency_resolution_after_deserialization(self, clear_global_map): """Test that dependencies are properly resolved after deserialization.""" # Create test parameters with dependencies - a = Parameter(name='a', value=2.0, unit='m', min=0, max=10) - b = Parameter(name='b', value=3.0, unit='m', min=0, max=10) + a = Parameter(display_name='a', value=2.0, unit='m', min=0, max=10) + b = Parameter(display_name='b', value=3.0, unit='m', min=0, max=10) c = Parameter.from_dependency( - name='c', + display_name='c', dependency_expression='a + b', dependency_map={'a': a, 'b': b}, unit='m', @@ -136,11 +136,11 @@ def test_dependency_resolution_after_deserialization(self, clear_global_map): def test_dependency_resolution_after_deserialization_desired_unit(self, clear_global_map): """Test that dependencies are properly resolved after deserialization.""" # Create test parameters with dependencies - a = Parameter(name='a', value=2.0, unit='m', min=0, max=10) - b = Parameter(name='b', value=3.0, unit='m', min=0, max=10) + a = Parameter(display_name='a', value=2.0, unit='m', min=0, max=10) + b = Parameter(display_name='b', value=3.0, unit='m', min=0, max=10) c = Parameter.from_dependency( - name='c', + display_name='c', dependency_expression='a + b', dependency_map={'a': a, 'b': b}, desired_unit='cm', @@ -182,13 +182,11 @@ def test_dependency_resolution_after_deserialization_desired_unit(self, clear_gl def test_unique_name_dependency_serialization(self, clear_global_map): """Test serialization of dependencies using unique names.""" - a = Parameter(name='a', value=3.0, unit='m', min=0, max=10) + a = Parameter(display_name='a', value=3.0, unit='m', min=0, max=10) # Create dependent parameter using unique name b = Parameter.from_dependency( - name='b', - dependency_expression='2 * "Parameter_0"', # Using unique name - unit='m', + display_name='b', dependency_expression='2 * "Parameter_0"', unit='m' ) # Serialize both parameters @@ -206,7 +204,7 @@ def test_unique_name_dependency_serialization(self, clear_global_map): # Deserialize both and resolve global_object.map._clear() c = Parameter( - name='c', value=0.0 + display_name='c', value=0.0 ) # Dummy to occupy unique name, to force new unique_names # Remove unique_name from serialized data to force generation of new unique names @@ -225,11 +223,11 @@ def test_unique_name_dependency_serialization(self, clear_global_map): def test_json_serialization_roundtrip(self, clear_global_map): """Test that parameter dependencies survive JSON serialization.""" # Create parameters with dependencies - length = Parameter(name='length', value=10.0, unit='m', min=0, max=100) - width = Parameter(name='width', value=5.0, unit='m', min=0, max=50) + length = Parameter(display_name='length', value=10.0, unit='m', min=0, max=100) + width = Parameter(display_name='width', value=5.0, unit='m', min=0, max=50) area = Parameter.from_dependency( - name='area', + display_name='area', dependency_expression='length * width', dependency_map={'length': length, 'width': width}, unit='m^2', @@ -263,14 +261,14 @@ def test_json_serialization_roundtrip(self, clear_global_map): def test_multiple_dependent_parameters(self, clear_global_map): """Test serialization with multiple dependent parameters.""" # Create a chain of dependencies - x = Parameter(name='x', value=2.0, unit='m', min=0, max=10) + x = Parameter(display_name='x', value=2.0, unit='m', min=0, max=10) y = Parameter.from_dependency( - name='y', dependency_expression='2 * x', dependency_map={'x': x}, unit='m' + display_name='y', dependency_expression='2 * x', dependency_map={'x': x}, unit='m' ) z = Parameter.from_dependency( - name='z', + display_name='z', dependency_expression='y + x', dependency_map={'y': y, 'x': x}, unit='m', @@ -306,12 +304,10 @@ def test_dependency_with_descriptor_number(self, clear_global_map): # When - x = DescriptorNumber(name='x', value=3.0, unit='m') - y = Parameter(name='y', value=4.0, unit='m') + x = DescriptorNumber(display_name='x', value=3.0, unit='m') + y = Parameter(display_name='y', value=4.0, unit='m') z = Parameter.from_dependency( - name='z', - dependency_expression='x + y', - dependency_map={'x': x, 'y': y}, + display_name='z', dependency_expression='x + y', dependency_map={'x': x, 'y': y} ) # Verify original functionality @@ -344,9 +340,9 @@ def test_dependency_with_descriptor_number(self, clear_global_map): def test_get_parameters_with_pending_dependencies(self, clear_global_map): """Test utility function for finding parameters with pending dependencies.""" # Create parameters - a = Parameter(name='a', value=1.0, unit='m') + a = Parameter(display_name='a', value=1.0, unit='m') b = Parameter.from_dependency( - name='b', dependency_expression='2 * a', dependency_map={'a': a}, unit='m' + display_name='b', dependency_expression='2 * a', dependency_map={'a': a}, unit='m' ) # Serialize and deserialize @@ -360,7 +356,7 @@ def test_get_parameters_with_pending_dependencies(self, clear_global_map): pending = get_parameters_with_pending_dependencies(new_params) assert len(pending) == 1 - assert pending[0].name == 'b' + assert pending[0].display_name == 'b' assert hasattr(pending[0], '_pending_dependency_string') # After resolution, should be empty @@ -370,9 +366,9 @@ def test_get_parameters_with_pending_dependencies(self, clear_global_map): def test_error_handling_missing_dependency(self, clear_global_map): """Test error handling when dependency cannot be resolved.""" - a = Parameter(name='a', value=1.0, unit='m') + a = Parameter(display_name='a', value=1.0, unit='m') b = Parameter.from_dependency( - name='b', dependency_expression='2 * a', dependency_map={'a': a}, unit='m' + display_name='b', dependency_expression='2 * a', dependency_map={'a': a}, unit='m' ) # Serialize b but not a @@ -391,9 +387,9 @@ def test_backward_compatibility_base_deserializer(self, clear_global_map): from easyscience.io.serializer_dict import SerializerDict # Create dependent parameter - a = Parameter(name='a', value=2.0, unit='m') + a = Parameter(display_name='a', value=2.0, unit='m') b = Parameter.from_dependency( - name='b', dependency_expression='3 * a', dependency_map={'a': a}, unit='m' + display_name='b', dependency_expression='3 * a', dependency_map={'a': a}, unit='m' ) # Use base serializer path (SerializerDict.decode) @@ -405,7 +401,7 @@ def test_backward_compatibility_base_deserializer(self, clear_global_map): # Should be a valid Parameter (but without dependency resolution) assert isinstance(deserialized, Parameter) - assert deserialized.name == 'b' + assert deserialized.display_name == 'b' assert deserialized.independent is True # Base path doesn't handle dependencies @pytest.mark.parametrize( @@ -422,11 +418,11 @@ def test_serializer_id_system_order_independence(self, clear_global_map, order): """Test that dependency IDs allow parameters to be loaded in any order.""" # WHEN # Create parameters with dependencies - x = Parameter(name='x', value=5.0, unit='m', min=0, max=20) - y = Parameter(name='y', value=10.0, unit='m', min=0, max=30) + x = Parameter(display_name='x', value=5.0, unit='m', min=0, max=20) + y = Parameter(display_name='y', value=10.0, unit='m', min=0, max=30) z = Parameter.from_dependency( - name='z', + display_name='z', dependency_expression='x * y', dependency_map={'x': x, 'y': y}, unit='m^2', @@ -478,11 +474,11 @@ def test_serializer_id_system_order_independence(self, clear_global_map, order): def test_deserialize_and_resolve_parameters_helper(self, clear_global_map): """Test the convenience helper function for deserialization and dependency resolution.""" # Create test parameters with dependencies - a = Parameter(name='a', value=2.0, unit='m', min=0, max=10) - b = Parameter(name='b', value=3.0, unit='m', min=0, max=10) + a = Parameter(display_name='a', value=2.0, unit='m', min=0, max=10) + b = Parameter(display_name='b', value=3.0, unit='m', min=0, max=10) c = Parameter.from_dependency( - name='c', + display_name='c', dependency_expression='a + b', dependency_map={'a': a, 'b': b}, unit='m', @@ -507,16 +503,16 @@ def test_deserialize_and_resolve_parameters_helper(self, clear_global_map): assert 'c' in new_params # Check that independent parameters work - assert new_params['a'].name == 'a' + assert new_params['a'].display_name == 'a' assert new_params['a'].value == 2.0 assert new_params['a'].independent is True - assert new_params['b'].name == 'b' + assert new_params['b'].display_name == 'b' assert new_params['b'].value == 3.0 assert new_params['b'].independent is True # Check that dependent parameter is properly resolved - assert new_params['c'].name == 'c' + assert new_params['c'].display_name == 'c' assert new_params['c'].value == 5.0 # 2 + 3 assert new_params['c'].independent is False