Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PortNamespace: Make dynamic apply recursively #263

Merged
merged 1 commit into from
Apr 3, 2023

Conversation

sphuber
Copy link
Collaborator

@sphuber sphuber commented Apr 3, 2023

The dynamic attribute of a port namespace indicates whether it should accept ports that are not explicitly defined. This was mostly used during validation, when a dictionary of port values was matched against a given PortNamespace.

This was, however, not being applied recursively and only during validation. For example, given a dynamic portnamespace, validating a dictionary:

{
    'nested': {
        'output': 'some_value'
    }
}

would pass validation without problems. However, the Process.out call that would actually attempt to attach the output to the process instance would call:

self.spec().outputs.get_port(namespace_separator.join(namespace))

which would raise, since get_port would raise a ValueError:

ValueError: port 'output' does not exist in port namespace 'nested'

The problem is that the nested namespace is expected, because the top level namespace was marked as dynamic, however, it itself would not also be treated as dynamic and so attempting to retrieve some_value from the nested namespace, would trigger a KeyError.

Here the logic in PortNamespace.get_port is updated to check in advance whether the port exists in the namespace, and if not the case and the namespace is dynamic, the nested port namespace is created. The attributes of the new namespace are inherited from its parent namespace, making the dynamic attribute act recursively.

@sphuber sphuber requested review from unkcpz and muhrin April 3, 2023 12:05
@sphuber
Copy link
Collaborator Author

sphuber commented Apr 3, 2023

@unkcpz This change is required for aiidateam/aiida-core#5954 So in order to provide the proper context, it may make sense to read through that aiida-core PR as well. It is only a few lines, so should be quick.

@codecov
Copy link

codecov bot commented Apr 3, 2023

Codecov Report

Patch and project coverage have no change.

Comparison is base (6f5d326) 90.82% compared to head (6f5d326) 90.82%.

❗ Current head 6f5d326 differs from pull request most recent head 5d50128. Consider uploading reports for the commit 5d50128 to get more accurate results

Additional details and impacted files
@@               Coverage Diff               @@
##           support/0.21.x     #263   +/-   ##
===============================================
  Coverage           90.82%   90.82%           
===============================================
  Files                  21       21           
  Lines                2971     2971           
===============================================
  Hits                 2698     2698           
  Misses                273      273           

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

☔ View full report in Codecov by Sentry.
📢 Do you have feedback about the report comment? Let us know in this issue.

The `dynamic` attribute of a port namespace indicates whether it should
accept ports that are not explicitly defined. This was mostly used
during validation, when a dictionary of port values was matched against
a given `PortNamespace`.

This was, however, not being applied recursively _and_ only during
validation. For example, given a dynamic portnamespace, validating a
dictionary:

    {
        'nested': {
	    'output': 'some_value'
        }
    }

would pass validation without problems. However, the `Process.out` call
that would actually attempt to attach the output to the process instance
would call:

    self.spec().outputs.get_port(namespace_separator.join(namespace))

which would raise, since `get_port` would raise a `ValueError`:

    ValueError: port 'output' does not exist in port namespace 'nested'

The problem is that the `nested` namespace is expected, because the top
level namespace was marked as dynamic, however, it itself would not also
be treated as dynamic and so attempting to retrieve `some_value` from
the `nested` namespace, would trigger a `KeyError`.

Here the logic in `PortNamespace.get_port` is updated to check in
advance whether the port exists in the namespace, and if not the case
_and_ the namespace is dynamic, the nested port namespace is created.
The attributes of the new namespace are inherited from its parent
namespace, making the `dynamic` attribute act recursively.
@sphuber sphuber force-pushed the fix/dynamic-nested-output-namespaces branch from c5e2129 to 5d50128 Compare April 3, 2023 17:27
Copy link
Member

@unkcpz unkcpz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me!

@sphuber sphuber merged commit 4c29f44 into support/0.21.x Apr 3, 2023
@sphuber sphuber deleted the fix/dynamic-nested-output-namespaces branch April 3, 2023 20:43
sphuber added a commit that referenced this pull request Apr 20, 2023
The `dynamic` attribute of a port namespace indicates whether it should
accept ports that are not explicitly defined. This was mostly used
during validation, when a dictionary of port values was matched against
a given `PortNamespace`.

This was, however, not being applied recursively _and_ only during
validation. For example, given a dynamic portnamespace, validating a
dictionary:

    {
        'nested': {
	    'output': 'some_value'
        }
    }

would pass validation without problems. However, the `Process.out` call
that would actually attempt to attach the output to the process instance
would call:

    self.spec().outputs.get_port(namespace_separator.join(namespace))

which would raise, since `get_port` would raise a `ValueError`:

    ValueError: port 'output' does not exist in port namespace 'nested'

The problem is that the `nested` namespace is expected, because the top
level namespace was marked as dynamic, however, it itself would not also
be treated as dynamic and so attempting to retrieve `some_value` from
the `nested` namespace, would trigger a `KeyError`.

Here the logic in `PortNamespace.get_port` is updated to check in
advance whether the port exists in the namespace, and if not the case
_and_ the namespace is dynamic, the nested port namespace is created.
The attributes of the new namespace are inherited from its parent
namespace, making the `dynamic` attribute act recursively.

Cherry-pick: 4c29f44
unkcpz pushed a commit to unkcpz/plumpy that referenced this pull request Dec 14, 2024
The `dynamic` attribute of a port namespace indicates whether it should
accept ports that are not explicitly defined. This was mostly used
during validation, when a dictionary of port values was matched against
a given `PortNamespace`.

This was, however, not being applied recursively _and_ only during
validation. For example, given a dynamic portnamespace, validating a
dictionary:

    {
        'nested': {
	    'output': 'some_value'
        }
    }

would pass validation without problems. However, the `Process.out` call
that would actually attempt to attach the output to the process instance
would call:

    self.spec().outputs.get_port(namespace_separator.join(namespace))

which would raise, since `get_port` would raise a `ValueError`:

    ValueError: port 'output' does not exist in port namespace 'nested'

The problem is that the `nested` namespace is expected, because the top
level namespace was marked as dynamic, however, it itself would not also
be treated as dynamic and so attempting to retrieve `some_value` from
the `nested` namespace, would trigger a `KeyError`.

Here the logic in `PortNamespace.get_port` is updated to check in
advance whether the port exists in the namespace, and if not the case
_and_ the namespace is dynamic, the nested port namespace is created.
The attributes of the new namespace are inherited from its parent
namespace, making the `dynamic` attribute act recursively.

Cherry-pick: 4c29f44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants