Skip to content

Commit

Permalink
Fix/ parse port spec port as sender or recvr (#2728)
Browse files Browse the repository at this point in the history
* • port.py
  _parse_port_spec(): fix assignment of port if port_spec[PORT_SPEC_ARG] is a dict with a projection specified
  • Loading branch information
jdcpni authored Jul 11, 2023
1 parent 03008f7 commit 78c452b
Showing 1 changed file with 35 additions and 8 deletions.
43 changes: 35 additions & 8 deletions psyneulink/core/components/ports/port.py
Original file line number Diff line number Diff line change
Expand Up @@ -2884,22 +2884,49 @@ def _parse_port_spec(port_type=None,

# If it is a Port specification dictionary
if isinstance(port_spec[PORT_SPEC_ARG], dict):

# If the Port specification has a Projection that has a sender already assigned,
# then return that Port with the Projection assigned to it
# (this occurs, for example, if an instantiated ControlSignal is used to specify a parameter
# FIX: JDC 7/8/23 ??WHAT IF PORT SPECIFICATION DICT HAS OTHER SPECS, SUCH AS SIZE?
# POSSIBLY THIS SHOULD ONLY BE CALLED IF DICT CONTAINS *ONLY* A PROJECTION SPEC?
# If the Port specification has a Projection specification (instantiated or in deferred_init)
# (used to define its connection) then return port specified in the Projection.
# This can either the sender or the receiver of the specified Projection, depending on the caller:
# - if the sender is specified in the Projection, return port = receiver
# (e.g., projection is a ControlProjections with its receiver (ParameterPort) specified,
# so return port = sender -- i.e., ControlSignal to which ControlProjection should be connected)
# - if the receiver is specified in the Projection, return port = sender
# (e.g., projection is from an OutputPort with its sender specified,
# so return the port = receiver -- i.e., InputPort to which Projection should be connected)
# FIX: WHAT IF PORT SPECIFICATION DICT HAS OTHER SPECS, SUCH AS SIZE?
# FIX: POSSIBLY THIS SHOULD BE CALLED ONLY IF DICT CONTAINS *ONLY* A PROJECTION SPEC?
try:
projection = port_spec[PORT_SPEC_ARG][PROJECTIONS]
if isinstance(projection, list):
assert len(port_spec[PORT_SPEC_ARG][PROJECTIONS])==1
projection = port_spec[PORT_SPEC_ARG][PROJECTIONS][0]
port = projection.sender
if projection.initialization_status == ContextFlags.INITIALIZED:
sender = projection.sender
receiver = projection.receiver
elif projection.initialization_status == ContextFlags.DEFERRED_INIT:
port = projection._init_args[SENDER]
sender = projection._init_args[SENDER]
receiver = projection._init_args[RECEIVER]
else:
assert False, f"PROGRAM ERROR: Projection ('{projection.name}') specified for" \
f" {port_type.__name__} of '{owner.name}' has unrcognized initialization_status: " \
f"{projection.initialization_status.name}"
# Check whether sender and/or receiver is an instantiated Port
sender_instantiated = isinstance(sender, Port)
if sender_instantiated:
sender_instantiated = sender.initialization_status == ContextFlags.INITIALIZED
receiver_instantiated = isinstance(receiver, Port)
if receiver_instantiated:
receiver_instantiated = receiver.initialization_status == ContextFlags.INITIALIZED
# Ensure that *either* sender or receiver is an instantiated Port, but *not both*
assert sender_instantiated ^ receiver_instantiated, \
f"PROGRAM ERROR: Projection ('{projection.name}') specified for" \
f" {port_type.__name__} of '{owner.name}' has both sender and receiver instantiated: " \
f"sender: '{sender.name}'; receiver: '{receiver.name}'"
if sender_instantiated:
port = projection.receiver
else:
port = projection.sender

if port.initialization_status == ContextFlags.DEFERRED_INIT:
port._init_args[PROJECTIONS] = projection
else:
Expand Down

0 comments on commit 78c452b

Please sign in to comment.