diff --git a/src/ansys/dpf/core/dpf_operator.py b/src/ansys/dpf/core/dpf_operator.py index c8191bfa9de..5ccc4192445 100644 --- a/src/ansys/dpf/core/dpf_operator.py +++ b/src/ansys/dpf/core/dpf_operator.py @@ -680,7 +680,7 @@ def id(self) -> int: return self._id @property - def inputs(self): + def inputs(self) -> Inputs: """Inputs connected to the operator. Returns @@ -702,7 +702,7 @@ def inputs(self): return self._inputs @property - def outputs(self): + def outputs(self) -> Outputs: """Outputs from the operator's evaluation. Returns diff --git a/src/ansys/dpf/core/inputs.py b/src/ansys/dpf/core/inputs.py index 9a2fbf1dff5..0dfdce4ac74 100644 --- a/src/ansys/dpf/core/inputs.py +++ b/src/ansys/dpf/core/inputs.py @@ -63,6 +63,7 @@ def __init__(self, spec, pin, operator, count_ellipsis=-1): self._python_expected_types.append(map_types_to_python[cpp_type]) if len(self._spec.type_names) == 0: self._python_expected_types.append("Any") + self.aliases = self._spec.aliases docstr = self.__str__() self.name = self._spec.name if self._count_ellipsis != -1: @@ -187,6 +188,8 @@ def __str__(self): docstr += "\n".join(wrap(self._spec.document.capitalize())) + "\n" if self._count_ellipsis >= 0: docstr += "is ellipsis\n" + if self.aliases: + docstr += f"aliases: {self.aliases}\n" return docstr def __inc_if_ellipsis(self): @@ -317,6 +320,9 @@ def _add_input(self, pin, spec, count_ellipsis=-1): def __call__(self, inpt): self.connect(inpt) + def __getitem__(self, item) -> Input: + return self._inputs[item] + # Dynamic class Inputs class Inputs(_Inputs): diff --git a/src/ansys/dpf/core/operator_specification.py b/src/ansys/dpf/core/operator_specification.py index 830cea44695..1bbe5aaaad6 100644 --- a/src/ansys/dpf/core/operator_specification.py +++ b/src/ansys/dpf/core/operator_specification.py @@ -78,6 +78,7 @@ class PinSpecification: optional: bool ellipsis: bool name_derived_class = str + aliases: list[str] def __init__( self, @@ -87,6 +88,7 @@ def __init__( optional=False, ellipsis=False, name_derived_class="", + aliases=[], ): self.name = name self.type_names = type_names @@ -94,6 +96,7 @@ def __init__( self.document = document self.ellipsis = ellipsis self.name_derived_class = name_derived_class + self.aliases = aliases @property def type_names(self) -> list[str]: @@ -140,6 +143,7 @@ def _get_copy(other, changed_types) -> PinSpecification: other.optional, other.ellipsis, other.name_derived_class, + other.aliases, ) def __repr__(self): @@ -367,7 +371,7 @@ def description(self) -> str: return "" @property - def inputs(self) -> dict: + def inputs(self) -> dict[int, PinSpecification]: """Returns a dictionary mapping the input pin numbers to their ``PinSpecification``. Returns @@ -382,7 +386,7 @@ def inputs(self) -> dict: True >>> operator.specification.inputs[4] PinSpecification(name='data_sources', _type_names=['data_sources'], ...set', ellipsis=False, - name_derived_class='') + name_derived_class='', aliases=[...]) """ if self._map_input_pin_spec is None: self._map_input_pin_spec = {} @@ -390,7 +394,7 @@ def inputs(self) -> dict: return self._map_input_pin_spec @property - def outputs(self) -> dict: + def outputs(self) -> dict[int, PinSpecification]: """Returns a dictionary mapping the output pin numbers to their ``PinSpecification``. Returns @@ -403,7 +407,7 @@ def outputs(self) -> dict: >>> operator = dpf.operators.mesh.mesh_provider() >>> operator.specification.outputs {0: PinSpecification(name='mesh', _type_names=['abstract_meshed_region'], ...=False, - name_derived_class='')} + name_derived_class='', aliases=[...])} """ if self._map_output_pin_spec is None: self._map_output_pin_spec = {} @@ -429,7 +433,18 @@ def _fill_pins(self, binput, to_fill): self._api.operator_specification_get_pin_type_name(self, binput, i_pin, i_type) for i_type in range(n_types) ] - + pin_aliases = [] + if server_meet_version("10.0", self._server) and hasattr( + self._api, "operator_specification_get_pin_num_aliases" + ): + for i_alias in range( + self._api.operator_specification_get_pin_num_aliases(self, binput, i_pin) + ): + pin_aliases.append( + self._api.operator_specification_get_pin_alias( + self, binput, i_pin, i_alias + ) + ) pin_derived_class_type_name = "" if server_meet_version("7.0", self._server) and hasattr( self._api, "operator_specification_get_pin_derived_class_type_name" @@ -448,6 +463,7 @@ def _fill_pins(self, binput, to_fill): pin_opt, pin_ell, pin_derived_class_type_name, + pin_aliases, ) @property diff --git a/src/ansys/dpf/core/operators/build.py b/src/ansys/dpf/core/operators/build.py index 88189e2da73..95a31887db4 100644 --- a/src/ansys/dpf/core/operators/build.py +++ b/src/ansys/dpf/core/operators/build.py @@ -101,6 +101,9 @@ def build_pin_data(pins, output=False): "document": document, "document_pin_docstring": document_pin_docstring, "ellipsis": 0 if specification.ellipsis else -1, + "has_aliases": len(specification.aliases) > 0, + "aliases_list": [dict([("alias", alias)]) for alias in specification.aliases], + "aliases": str(specification.aliases), } if specification.ellipsis: @@ -127,11 +130,13 @@ def build_operator( input_pins = [] if specification.inputs: input_pins = build_pin_data(specification.inputs) + has_input_aliases = any(len(pin["aliases_list"]) > 0 for pin in input_pins) output_pins = [] if specification.outputs: output_pins = build_pin_data(specification.outputs, output=True) multiple_output_types = any(pin["multiple_types"] for pin in output_pins) + has_output_aliases = any(len(pin["aliases_list"]) > 0 for pin in output_pins) docstring = build_docstring(specification_description) @@ -150,6 +155,8 @@ def build_operator( "multiple_output_types": multiple_output_types, "category": category, "date_and_time": date_and_time, + "has_input_aliases": has_input_aliases, + "has_output_aliases": has_output_aliases, } this_path = os.path.dirname(os.path.abspath(__file__)) @@ -164,7 +171,7 @@ def build_operator( def build_operators(): - print(f"Generating operators for server {dpf.SERVER.version}") + print(f"Generating operators for server {dpf.SERVER.version} ({dpf.SERVER.ansys_path})") time_0 = time.time() this_path = os.path.dirname(os.path.abspath(__file__)) @@ -228,6 +235,7 @@ def build_operators(): # Write to operator file operator_file = os.path.join(category_path, scripting_name + ".py") with open(operator_file, "wb") as f: + operator_str = scripting_name try: operator_str = build_operator( specification, diff --git a/src/ansys/dpf/core/operators/math/accumulate.py b/src/ansys/dpf/core/operators/math/accumulate.py index 0f1b3f30d5b..8b793d6a18b 100644 --- a/src/ansys/dpf/core/operators/math/accumulate.py +++ b/src/ansys/dpf/core/operators/math/accumulate.py @@ -61,7 +61,13 @@ class accumulate(Operator): """ def __init__( - self, fieldA=None, weights=None, time_scoping=None, config=None, server=None + self, + fieldA=None, + weights=None, + time_scoping=None, + config=None, + server=None, + ponderation=None, ): super().__init__(name="accumulate", config=config, server=server) self._inputs = InputsAccumulate(self) @@ -70,6 +76,13 @@ def __init__( self.inputs.fieldA.connect(fieldA) if weights is not None: self.inputs.weights.connect(weights) + elif ponderation is not None: + warn( + DeprecationWarning( + f'Operator accumulate: Input name "ponderation" is deprecated in favor of "weights".' + ) + ) + self.inputs.weights.connect(ponderation) if time_scoping is not None: self.inputs.time_scoping.connect(time_scoping) @@ -92,6 +105,7 @@ def _spec() -> Specification: type_names=["field"], optional=True, document=r"""Field containing weights, one weight per entity""", + aliases=["ponderation"], ), 2: PinSpecification( name="time_scoping", @@ -243,6 +257,18 @@ def time_scoping(self) -> Input: """ return self._time_scoping + def __getattr__(self, name): + if name in ["ponderation"]: + warn( + DeprecationWarning( + f'Operator accumulate: Input name "{name}" is deprecated in favor of "weights".' + ) + ) + return self.weights + raise AttributeError( + f"'{self.__class__.__name__}' object has no attribute '{name}'." + ) + class OutputsAccumulate(_Outputs): """Intermediate class used to get outputs from diff --git a/src/ansys/dpf/core/operators/math/accumulate_fc.py b/src/ansys/dpf/core/operators/math/accumulate_fc.py index 9ac04700a60..63e99210b56 100644 --- a/src/ansys/dpf/core/operators/math/accumulate_fc.py +++ b/src/ansys/dpf/core/operators/math/accumulate_fc.py @@ -67,6 +67,7 @@ def __init__( time_scoping=None, config=None, server=None, + ponderation=None, ): super().__init__(name="accumulate_fc", config=config, server=server) self._inputs = InputsAccumulateFc(self) @@ -75,6 +76,13 @@ def __init__( self.inputs.fields_container.connect(fields_container) if weights is not None: self.inputs.weights.connect(weights) + elif ponderation is not None: + warn( + DeprecationWarning( + f'Operator accumulate_fc: Input name "ponderation" is deprecated in favor of "weights".' + ) + ) + self.inputs.weights.connect(ponderation) if time_scoping is not None: self.inputs.time_scoping.connect(time_scoping) @@ -97,6 +105,7 @@ def _spec() -> Specification: type_names=["field"], optional=True, document=r"""Field containing weights, one weight per entity""", + aliases=["ponderation"], ), 2: PinSpecification( name="time_scoping", @@ -248,6 +257,18 @@ def time_scoping(self) -> Input: """ return self._time_scoping + def __getattr__(self, name): + if name in ["ponderation"]: + warn( + DeprecationWarning( + f'Operator accumulate_fc: Input name "{name}" is deprecated in favor of "weights".' + ) + ) + return self.weights + raise AttributeError( + f"'{self.__class__.__name__}' object has no attribute '{name}'." + ) + class OutputsAccumulateFc(_Outputs): """Intermediate class used to get outputs from diff --git a/src/ansys/dpf/core/operators/math/add_constant.py b/src/ansys/dpf/core/operators/math/add_constant.py index b5c9b2c3852..9976b7f4ed3 100644 --- a/src/ansys/dpf/core/operators/math/add_constant.py +++ b/src/ansys/dpf/core/operators/math/add_constant.py @@ -53,7 +53,14 @@ class add_constant(Operator): >>> result_field = op.outputs.field() """ - def __init__(self, field=None, weights=None, config=None, server=None): + def __init__( + self, + field=None, + weights=None, + config=None, + server=None, + ponderation=None, + ): super().__init__(name="add_constant", config=config, server=server) self._inputs = InputsAddConstant(self) self._outputs = OutputsAddConstant(self) @@ -61,6 +68,13 @@ def __init__(self, field=None, weights=None, config=None, server=None): self.inputs.field.connect(field) if weights is not None: self.inputs.weights.connect(weights) + elif ponderation is not None: + warn( + DeprecationWarning( + f'Operator add_constant: Input name "ponderation" is deprecated in favor of "weights".' + ) + ) + self.inputs.weights.connect(ponderation) @staticmethod def _spec() -> Specification: @@ -80,6 +94,7 @@ def _spec() -> Specification: type_names=["double", "vector"], optional=False, document=r"""double or vector of double""", + aliases=["ponderation"], ), }, map_output_pin_spec={ @@ -200,6 +215,18 @@ def weights(self) -> Input: """ return self._weights + def __getattr__(self, name): + if name in ["ponderation"]: + warn( + DeprecationWarning( + f'Operator add_constant: Input name "{name}" is deprecated in favor of "weights".' + ) + ) + return self.weights + raise AttributeError( + f"'{self.__class__.__name__}' object has no attribute '{name}'." + ) + class OutputsAddConstant(_Outputs): """Intermediate class used to get outputs from diff --git a/src/ansys/dpf/core/operators/math/add_constant_fc.py b/src/ansys/dpf/core/operators/math/add_constant_fc.py index a16e704bcd0..c8f80e3aafd 100644 --- a/src/ansys/dpf/core/operators/math/add_constant_fc.py +++ b/src/ansys/dpf/core/operators/math/add_constant_fc.py @@ -53,7 +53,14 @@ class add_constant_fc(Operator): >>> result_fields_container = op.outputs.fields_container() """ - def __init__(self, fields_container=None, weights=None, config=None, server=None): + def __init__( + self, + fields_container=None, + weights=None, + config=None, + server=None, + ponderation=None, + ): super().__init__(name="add_constant_fc", config=config, server=server) self._inputs = InputsAddConstantFc(self) self._outputs = OutputsAddConstantFc(self) @@ -61,6 +68,13 @@ def __init__(self, fields_container=None, weights=None, config=None, server=None self.inputs.fields_container.connect(fields_container) if weights is not None: self.inputs.weights.connect(weights) + elif ponderation is not None: + warn( + DeprecationWarning( + f'Operator add_constant_fc: Input name "ponderation" is deprecated in favor of "weights".' + ) + ) + self.inputs.weights.connect(ponderation) @staticmethod def _spec() -> Specification: @@ -80,6 +94,7 @@ def _spec() -> Specification: type_names=["double", "vector"], optional=False, document=r"""double or vector of double""", + aliases=["ponderation"], ), }, map_output_pin_spec={ @@ -200,6 +215,18 @@ def weights(self) -> Input: """ return self._weights + def __getattr__(self, name): + if name in ["ponderation"]: + warn( + DeprecationWarning( + f'Operator add_constant_fc: Input name "{name}" is deprecated in favor of "weights".' + ) + ) + return self.weights + raise AttributeError( + f"'{self.__class__.__name__}' object has no attribute '{name}'." + ) + class OutputsAddConstantFc(_Outputs): """Intermediate class used to get outputs from diff --git a/src/ansys/dpf/core/operators/math/correlation.py b/src/ansys/dpf/core/operators/math/correlation.py index 29b122e6ac4..7c6780eab8c 100644 --- a/src/ansys/dpf/core/operators/math/correlation.py +++ b/src/ansys/dpf/core/operators/math/correlation.py @@ -77,6 +77,7 @@ def __init__( absoluteValue=None, config=None, server=None, + ponderation=None, ): super().__init__(name="correlation", config=config, server=server) self._inputs = InputsCorrelation(self) @@ -87,6 +88,13 @@ def __init__( self.inputs.fieldB.connect(fieldB) if weights is not None: self.inputs.weights.connect(weights) + elif ponderation is not None: + warn( + DeprecationWarning( + f'Operator correlation: Input name "ponderation" is deprecated in favor of "weights".' + ) + ) + self.inputs.weights.connect(ponderation) if absoluteValue is not None: self.inputs.absoluteValue.connect(absoluteValue) @@ -116,6 +124,7 @@ def _spec() -> Specification: type_names=["field", "fields_container"], optional=False, document=r"""Field M, optional weighting for correlation computation.""", + aliases=["ponderation"], ), 3: PinSpecification( name="absoluteValue", @@ -298,6 +307,18 @@ def absoluteValue(self) -> Input: """ return self._absoluteValue + def __getattr__(self, name): + if name in ["ponderation"]: + warn( + DeprecationWarning( + f'Operator correlation: Input name "{name}" is deprecated in favor of "weights".' + ) + ) + return self.weights + raise AttributeError( + f"'{self.__class__.__name__}' object has no attribute '{name}'." + ) + class OutputsCorrelation(_Outputs): """Intermediate class used to get outputs from diff --git a/src/ansys/dpf/core/operators/math/mac.py b/src/ansys/dpf/core/operators/math/mac.py index c19d315d2a3..86f6e7a201d 100644 --- a/src/ansys/dpf/core/operators/math/mac.py +++ b/src/ansys/dpf/core/operators/math/mac.py @@ -69,6 +69,7 @@ def __init__( weights=None, config=None, server=None, + ponderation=None, ): super().__init__(name="mac", config=config, server=server) self._inputs = InputsMac(self) @@ -79,6 +80,13 @@ def __init__( self.inputs.fields_containerB.connect(fields_containerB) if weights is not None: self.inputs.weights.connect(weights) + elif ponderation is not None: + warn( + DeprecationWarning( + f'Operator mac: Input name "ponderation" is deprecated in favor of "weights".' + ) + ) + self.inputs.weights.connect(ponderation) @staticmethod def _spec() -> Specification: @@ -107,6 +115,7 @@ def _spec() -> Specification: type_names=["field"], optional=False, document=r"""Field M, optional weighting for MAC Matrix computation.""", + aliases=["ponderation"], ), }, map_output_pin_spec={ @@ -252,6 +261,18 @@ def weights(self) -> Input: """ return self._weights + def __getattr__(self, name): + if name in ["ponderation"]: + warn( + DeprecationWarning( + f'Operator mac: Input name "{name}" is deprecated in favor of "weights".' + ) + ) + return self.weights + raise AttributeError( + f"'{self.__class__.__name__}' object has no attribute '{name}'." + ) + class OutputsMac(_Outputs): """Intermediate class used to get outputs from diff --git a/src/ansys/dpf/core/operators/math/scale.py b/src/ansys/dpf/core/operators/math/scale.py index 9fb2bd266a3..40483460a6c 100644 --- a/src/ansys/dpf/core/operators/math/scale.py +++ b/src/ansys/dpf/core/operators/math/scale.py @@ -74,6 +74,7 @@ def __init__( algorithm=None, config=None, server=None, + ponderation=None, ): super().__init__(name="scale", config=config, server=server) self._inputs = InputsScale(self) @@ -82,6 +83,13 @@ def __init__( self.inputs.field.connect(field) if weights is not None: self.inputs.weights.connect(weights) + elif ponderation is not None: + warn( + DeprecationWarning( + f'Operator scale: Input name "ponderation" is deprecated in favor of "weights".' + ) + ) + self.inputs.weights.connect(ponderation) if boolean is not None: self.inputs.boolean.connect(boolean) if algorithm is not None: @@ -108,6 +116,7 @@ def _spec() -> Specification: type_names=["double", "field", "vector"], optional=False, document=r"""Double/Field/Vector of doubles. When scoped on overall, same value(s) applied on all the data, when scoped elsewhere, corresponding values will be multiplied due to the scoping""", + aliases=["ponderation"], ), 2: PinSpecification( name="boolean", @@ -290,6 +299,18 @@ def algorithm(self) -> Input: """ return self._algorithm + def __getattr__(self, name): + if name in ["ponderation"]: + warn( + DeprecationWarning( + f'Operator scale: Input name "{name}" is deprecated in favor of "weights".' + ) + ) + return self.weights + raise AttributeError( + f"'{self.__class__.__name__}' object has no attribute '{name}'." + ) + class OutputsScale(_Outputs): """Intermediate class used to get outputs from diff --git a/src/ansys/dpf/core/operators/math/scale_fc.py b/src/ansys/dpf/core/operators/math/scale_fc.py index 2368b72ac97..f56c03af327 100644 --- a/src/ansys/dpf/core/operators/math/scale_fc.py +++ b/src/ansys/dpf/core/operators/math/scale_fc.py @@ -74,6 +74,7 @@ def __init__( algorithm=None, config=None, server=None, + ponderation=None, ): super().__init__(name="scale_fc", config=config, server=server) self._inputs = InputsScaleFc(self) @@ -82,6 +83,13 @@ def __init__( self.inputs.fields_container.connect(fields_container) if weights is not None: self.inputs.weights.connect(weights) + elif ponderation is not None: + warn( + DeprecationWarning( + f'Operator scale_fc: Input name "ponderation" is deprecated in favor of "weights".' + ) + ) + self.inputs.weights.connect(ponderation) if boolean is not None: self.inputs.boolean.connect(boolean) if algorithm is not None: @@ -113,6 +121,7 @@ def _spec() -> Specification: ], optional=False, document=r"""Double/Vector of doubles/Field/FieldsContainer. When scoped on overall, same value(s) applied on all the data, when scoped elsewhere, corresponding values will be multiplied due to the scoping""", + aliases=["ponderation"], ), 2: PinSpecification( name="boolean", @@ -295,6 +304,18 @@ def algorithm(self) -> Input: """ return self._algorithm + def __getattr__(self, name): + if name in ["ponderation"]: + warn( + DeprecationWarning( + f'Operator scale_fc: Input name "{name}" is deprecated in favor of "weights".' + ) + ) + return self.weights + raise AttributeError( + f"'{self.__class__.__name__}' object has no attribute '{name}'." + ) + class OutputsScaleFc(_Outputs): """Intermediate class used to get outputs from diff --git a/src/ansys/dpf/core/operators/operator.mustache b/src/ansys/dpf/core/operators/operator.mustache index 4ce10c61211..1e1be762c06 100644 --- a/src/ansys/dpf/core/operators/operator.mustache +++ b/src/ansys/dpf/core/operators/operator.mustache @@ -82,13 +82,20 @@ class {{class_name}}(Operator): {{/outputs}} """ - def __init__(self, {{#input_pins}}{{name}}=None, {{/input_pins}}config=None, server=None): + def __init__(self, {{#input_pins}}{{name}}=None, {{/input_pins}}config=None, server=None{{#has_input_aliases}}, {{#input_pins}}{{#aliases_list}}{{alias}}=None, {{/aliases_list}}{{/input_pins}}{{/has_input_aliases}}): super().__init__(name="{{operator_name}}", config=config, server=server) self._inputs = Inputs{{capital_class_name}}(self) self._outputs = Outputs{{capital_class_name}}(self) {{#input_pins}} if {{name}} is not None: self.inputs.{{name}}.connect({{name}}) + {{#has_input_aliases}} + {{#aliases_list}} + elif {{alias}} is not None: + warn(DeprecationWarning(f"Operator {{class_name}}: Input name \"{{alias}}\" is deprecated in favor of \"{{name}}\".")) + self.inputs.{{name}}.connect({{alias}}) + {{/aliases_list}} + {{/has_input_aliases}} {{/input_pins}} @staticmethod @@ -111,6 +118,9 @@ class {{class_name}}(Operator): {{#has_derived_class}} name_derived_class=["{{{derived_type_name}}}"], {{/has_derived_class}} + {{#has_aliases}} + aliases={{{aliases}}}, + {{/has_aliases}} ), {{/input_pins}} }, @@ -126,6 +136,9 @@ class {{class_name}}(Operator): {{#has_derived_class}} name_derived_class=["{{{derived_type_name}}}"], {{/has_derived_class}} + {{#has_aliases}} + aliases={{{aliases}}}, + {{/has_aliases}} ), {{/output_pins}} }, @@ -221,6 +234,18 @@ class Inputs{{capital_class_name}}(_Inputs): """ return self._{{name}} {{/input_pins}} + {{#has_input_aliases}} + + def __getattr__(self, name): + {{#input_pins}} + {{#has_aliases}} + if name in {{{aliases}}}: + warn(DeprecationWarning(f"Operator {{class_name}}: Input name \"{name}\" is deprecated in favor of \"{{name}}\".")) + return self.{{name}} + {{/has_aliases}} + {{/input_pins}} + raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{name}'.") + {{/has_input_aliases}} class Outputs{{capital_class_name}}(_Outputs): @@ -251,9 +276,9 @@ class Outputs{{capital_class_name}}(_Outputs): self._outputs.append(self._{{name}}) {{/multiple_types}} {{/output_pins}} - {{#output_pins}} {{^multiple_types}} + @property def {{name}}(self) -> Output: r"""Allows to get {{name}} output of the operator @@ -275,5 +300,16 @@ class Outputs{{capital_class_name}}(_Outputs): >>> result_{{name}} = op.outputs.{{name}}() """ return self._{{name}} -{{/multiple_types}} -{{/output_pins}} \ No newline at end of file +{{/multiple_types}}{{/output_pins}} +{{#has_output_aliases}} + + def __getattr__(self, name): + {{#output_pins}} + {{#has_aliases}} + if name in {{{aliases}}}: + warn(DeprecationWarning(f"Operator {{class_name}}: Output name \"{name}\" is deprecated in favor of \"{{name}}\".")) + return self.{{name}} + {{/has_aliases}} + {{/output_pins}} + raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{name}'.") +{{/has_output_aliases}} diff --git a/src/ansys/dpf/core/outputs.py b/src/ansys/dpf/core/outputs.py index 51eb731eeb1..d1a1ae73e94 100644 --- a/src/ansys/dpf/core/outputs.py +++ b/src/ansys/dpf/core/outputs.py @@ -54,6 +54,7 @@ def __init__(self, spec, pin, operator): self._python_expected_types = [] for cpp_type in self._spec.type_names: self._python_expected_types.append(map_types_to_python[cpp_type]) + self.aliases = self._spec.aliases def get_data(self): """Retrieve the output of the operator.""" @@ -118,6 +119,8 @@ def __str__(self): docstr += " -" + exp_types + "\n" if self._spec.document: docstr += "help: " + self._spec.document + "\n" + if self.aliases: + docstr += f"aliases: {self.aliases}\n" return docstr @@ -148,7 +151,7 @@ def _get_given_output(self, input_type_name): corresponding_pins.append(pin) return corresponding_pins - def __getitem__(self, index): + def __getitem__(self, index) -> Output: return self._outputs[index] def __str__(self): @@ -157,8 +160,9 @@ def __str__(self): tot_string = str(output._spec.name) input_string = tot_string.split("\n") input_string1 = input_string[0] - line = [" ", "- ", input_string1] - docstr += "{:<5}{:<4}{:<20}\n".format(*line) + aliases = tuple(output._spec.aliases) if output._spec.aliases else "" + line = [" ", "- ", input_string1, aliases] + docstr += "{:<5}{:<4}{:<20}{}\n".format(*line) for inputstr in input_string: if inputstr != input_string1: line = [" ", " ", inputstr] diff --git a/src/ansys/dpf/gate/operator_specification_grpcapi.py b/src/ansys/dpf/gate/operator_specification_grpcapi.py index ebcaf5e1e0a..e21a8fa2d87 100644 --- a/src/ansys/dpf/gate/operator_specification_grpcapi.py +++ b/src/ansys/dpf/gate/operator_specification_grpcapi.py @@ -82,6 +82,22 @@ def operator_specification_get_pin_type_name(specification, binput, numPin, numT else: return specification._internal_obj.map_output_pin_spec[numPin].type_names[numType] + @staticmethod + def operator_specification_get_pin_num_aliases(specification, binput, numPin): + if not hasattr(specification._internal_obj.map_input_pin_spec[numPin], "aliases"): + return 0 + if binput: + return len(specification._internal_obj.map_input_pin_spec[numPin].aliases) + else: + return len(specification._internal_obj.map_output_pin_spec[numPin].aliases) + + @staticmethod + def operator_specification_get_pin_alias(specification, binput, numPin, numAlias): + if binput: + return specification._internal_obj.map_input_pin_spec[numPin].aliases[numAlias] + else: + return specification._internal_obj.map_output_pin_spec[numPin].aliases[numAlias] + @staticmethod def operator_specification_get_pin_derived_class_type_name(specification, binput, numPin): if binput: diff --git a/tests/test_animation.py b/tests/test_animation.py index 9db70b56074..4c95f8c71f4 100644 --- a/tests/test_animation.py +++ b/tests/test_animation.py @@ -27,10 +27,6 @@ from ansys.dpf import core as dpf from ansys.dpf.core import animation, examples, misc -from conftest import SERVERS_VERSION_GREATER_THAN_OR_EQUAL_TO_10_0 - -if not SERVERS_VERSION_GREATER_THAN_OR_EQUAL_TO_10_0: - pytest.skip("skipping retro temporarily", allow_module_level=True) if misc.module_exists("pyvista"): HAS_PYVISTA = True diff --git a/tests/test_animator.py b/tests/test_animator.py index b0fedf5e198..402e4f66176 100644 --- a/tests/test_animator.py +++ b/tests/test_animator.py @@ -27,10 +27,6 @@ from ansys.dpf import core as dpf from ansys.dpf.core import Workflow, examples, misc -from conftest import SERVERS_VERSION_GREATER_THAN_OR_EQUAL_TO_10_0 - -if not SERVERS_VERSION_GREATER_THAN_OR_EQUAL_TO_10_0: - pytest.skip("skipping retro temporarily", allow_module_level=True) if misc.module_exists("pyvista"): HAS_PYVISTA = True diff --git a/tests/test_specification.py b/tests/test_specification.py new file mode 100644 index 00000000000..d8eccd8a264 --- /dev/null +++ b/tests/test_specification.py @@ -0,0 +1,111 @@ +# Copyright (C) 2020 - 2025 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import pytest + +import ansys.dpf.core as dpf +from conftest import SERVERS_VERSION_GREATER_THAN_OR_EQUAL_TO_10_0 + + +@pytest.mark.skipif( + condition=not SERVERS_VERSION_GREATER_THAN_OR_EQUAL_TO_10_0, + reason="Aliases available with DPF 10.0 (25R2).", +) +def test_pin_alias(server_type): + field = dpf.fields_factory.create_scalar_field( + num_entities=1, location=dpf.locations.nodal, server=server_type + ) + field.append(data=[1.0], scopingid=1) + weights = dpf.fields_factory.create_scalar_field( + num_entities=1, location=dpf.locations.nodal, server=server_type + ) + weights.append(data=[2.0], scopingid=1) + ponderation = dpf.fields_factory.create_scalar_field( + num_entities=1, location=dpf.locations.nodal, server=server_type + ) + ponderation.append(data=[3.0], scopingid=1) + + # Check new pin name + output: dpf.Field = dpf.operators.math.scale( + field=field, + weights=weights, + server=server_type, + ).eval() + assert output.data_as_list == [2.0] + + # Check alias (check warning) + with pytest.warns( + expected_warning=DeprecationWarning, + match='Operator scale: Input name "ponderation" is deprecated in favor of "weights".', + ): + output: dpf.Field = dpf.operators.math.scale( + field=field, + ponderation=ponderation, + server=server_type, + ).eval() + assert output.data_as_list == [3.0] + + # Check precedence of new pin name over alias + output: dpf.Field = dpf.operators.math.scale( + field=field, + weights=weights, + ponderation=ponderation, + server=server_type, + ).eval() + assert output.data_as_list == [2.0] + + # Check connection via inputs of new name + op = dpf.operators.math.scale( + field=field, + server=server_type, + ) + op.inputs.weights.connect(weights) + output: dpf.Field = op.eval() + assert output.data_as_list == [2.0] + + # Check connection via inputs of alias (check warning) + op = dpf.operators.math.scale( + field=field, + server=server_type, + ) + with pytest.warns( + expected_warning=DeprecationWarning, + match='Operator scale: Input name "ponderation" is deprecated in favor of "weights".', + ): + op.inputs.ponderation.connect(ponderation) + output: dpf.Field = op.eval() + assert output.data_as_list == [3.0] + + # Check effect of consecutive connections + op = dpf.operators.math.scale( + field=field, + server=server_type, + ) + op.inputs.weights.connect(weights) + output: dpf.Field = op.eval() + assert output.data_as_list == [2.0] + op.inputs.ponderation.connect(ponderation) + output: dpf.Field = op.eval() + assert output.data_as_list == [3.0] + op.inputs.weights.connect(weights) + output: dpf.Field = op.eval() + assert output.data_as_list == [2.0]