Skip to content

Commit

Permalink
Merge pull request #1738 from PrincetonUniversity/devel
Browse files Browse the repository at this point in the history
Devel
  • Loading branch information
dillontsmith authored Aug 10, 2020
2 parents 2fba3de + 59d8ef1 commit c1c423b
Show file tree
Hide file tree
Showing 15 changed files with 2,225 additions and 44 deletions.
34 changes: 3 additions & 31 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ arch:
- amd64
- arm64
- ppc64le
- s390x
# Disabled until the scheduling issues are fixed:
# https://travis-ci.community/t/s390x-build-fails-to-get-queued/9533
# - s390x

stages:
- precache
Expand All @@ -37,36 +39,6 @@ jobs:
stage: precache
env: PYTHON=3.6
arch: arm64
- script: true
after_script: true
stage: precache
env: PYTHON=3.8
arch: ppc64le
- script: true
after_script: true
stage: precache
env: PYTHON=3.7
arch: ppc64le
- script: true
after_script: true
stage: precache
env: PYTHON=3.6
arch: ppc64le
- script: true
after_script: true
stage: precache
env: PYTHON=3.8
arch: s390x
- script: true
after_script: true
stage: precache
env: PYTHON=3.7
arch: s390x
- script: true
after_script: true
stage: precache
env: PYTHON=3.6
arch: s390x

env:
jobs:
Expand Down
3 changes: 3 additions & 0 deletions psyneulink/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,18 @@
from . import globals
from . import llvm
from . import scheduling
from . import rpc

from .components import *
from .compositions import *
from .globals import *
from .llvm import *
from .scheduling import *
from .rpc import *

__all__ = list(components.__all__)
__all__.extend(llvm.__all__)
__all__.extend(compositions.__all__)
__all__.extend(globals.__all__)
__all__.extend(scheduling.__all__)
__all__.extend(rpc.__all__)
13 changes: 13 additions & 0 deletions psyneulink/core/components/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -3187,6 +3187,19 @@ def set_log_conditions(self, items, log_condition=LogCondition.EXECUTION):
"""
self.log.set_log_conditions(items=items, log_condition=log_condition)

def set_delivery_conditions(self, items, delivery_condition=LogCondition.EXECUTION):
"""
_set_delivery_conditions( \
items \
delivery_condition=EXECUTION \
)
Specifies items to be delivered to external application via gRPC; these must be be `loggable_items <Component.loggable_items>`
of the Component's `log <Component.log>`. This is a convenience method that calls the `_set_delivery_conditions <Log._set_delivery_conditions>`
method of the Component's `log <Component.log>`.
"""
self.log._set_delivery_conditions(items=items, delivery_condition=delivery_condition)

def log_values(self, entries):
"""
log_values( \
Expand Down
10 changes: 9 additions & 1 deletion psyneulink/core/globals/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
import warnings

from collections import defaultdict, namedtuple
from queue import Queue

import typecheck as tc

Expand Down Expand Up @@ -328,6 +329,10 @@ class Context():
references it, but it is possible that future uses will involve other messages. Note that this is *not* the
same as the `flags_string <Context.flags_string>` attribute (see `note <Context_String_Note>`).
rpc_pipeline : Queue
queue to populate with messages for external environment in cases where execution was triggered via RPC call
(e.g. through PsyNeuLinkView).
"""

__name__ = 'Context'
Expand All @@ -342,7 +347,9 @@ def __init__(self,
source=ContextFlags.NONE,
runmode=ContextFlags.DEFAULT_MODE,
execution_id=None,
string:str='', time=None):
string:str='',
time=None,
rpc_pipeline:Queue=None):

self.owner = owner
self.composition = composition
Expand All @@ -364,6 +371,7 @@ def __init__(self,
self.execution_id = execution_id
self.execution_time = None
self.string = string
self.rpc_pipeline = rpc_pipeline

__deepcopy__ = get_deepcopy_with_shared(_deepcopy_shared_keys)

Expand Down
103 changes: 101 additions & 2 deletions psyneulink/core/globals/log.py
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,6 @@

LogEntry = namedtuple('LogEntry', 'time, context, value')


class LogCondition(enum.IntFlag):
"""Used to specify the context in which a value of the Component or its attribute is `logged <Log_Conditions>`.
Expand Down Expand Up @@ -471,7 +470,6 @@ def from_string(string):
except KeyError:
raise LogError("\'{}\' is not a value of {}".format(string, LogCondition))


TIME_NOT_SPECIFIED = 'Time Not Specified'
EXECUTION_CONDITION_NAMES = {LogCondition.PROCESSING.name,
LogCondition.LEARNING.name,
Expand Down Expand Up @@ -833,6 +831,107 @@ def assign_log_condition(item, level):
else:
assign_log_condition(item[0], item[1])

def _set_delivery_conditions(self, items, delivery_condition=LogCondition.EXECUTION):
"""Specifies items to be delivered via gRPC under the specified `LogCondition`\\(s).
Arguments
---------
items : str, Component, tuple or List of these
specifies items to be logged; these must be be `loggable_items <Log.loggable_items>` of the Log.
Each item must be a:
* string that is the name of a `loggable_item` <Log.loggable_item>` of the Log's `owner <Log.owner>`;
* a reference to a Component;
* tuple, the first item of which is one of the above, and the second a `ContextFlags` to use for the item.
delivery_condition : LogCondition : default LogCondition.EXECUTION
specifies `LogCondition` to use as the default for items not specified in tuples (see above).
For convenience, the name of a LogCondition can be used in place of its full specification
(e.g., *EXECUTION* instead of `LogCondition.EXECUTION`).
params_set : list : default None
list of parameters to include as loggable items; these must be attributes of the `owner <Log.owner>`
(for example, Mechanism
"""
from psyneulink.core.components.component import Component
from psyneulink.core.globals.preferences.preferenceset import PreferenceEntry, PreferenceLevel
from psyneulink.core.globals.keywords import ALL

def assign_delivery_condition(item, level):

# Handle multiple level assignments (as LogCondition or strings in a list)
if not isinstance(level, list):
level = [level]
levels = LogCondition.OFF
for l in level:
if isinstance(l, str):
l = LogCondition.from_string(l)
levels |= l
level = levels

if item not in self.loggable_items:
# KDM 8/13/18: NOTE: add_entries is not defined anywhere
raise LogError("\'{0}\' is not a loggable item for {1} (try using \'{1}.log.add_entries()\')".
format(item, self.owner.name))

self._get_parameter_from_item_string(item).delivery_condition = level

if items == ALL:
for component in self.loggable_components:
component.logPref = PreferenceEntry(delivery_condition, PreferenceLevel.INSTANCE)

for item in self.all_items:
self._get_parameter_from_item_string(item).delivery_condition = delivery_condition
# self.logPref = PreferenceEntry(log_condition, PreferenceLevel.INSTANCE)
return

if not isinstance(items, list):
items = [items]

# allow multiple sets of conditions to be set for multiple items with one call
for item in items:
if isinstance(item, (str, Component)):
if isinstance(item, Component):
item = item.name
assign_delivery_condition(item, delivery_condition)
else:
assign_delivery_condition(item[0], item[1])

@tc.typecheck
@handle_external_context()
def _deliver_values(self, entries, context=None):
from psyneulink.core.globals.parameters import parse_context
"""Deliver the value of one or more Components programmatically.
This can be used to "manually" prepare the `value <Component.value>` of any of a Component's `loggable_items
<Component.loggable_items>` (including its own `value <Component.value>`) for delivery to an external application via gRPC.
If the call to _deliver_values is made while a Composition to which the Component belongs is being run (e.g.,
in a **call_before..** or **call_after...** argument of its `run <Composition.run>` method), then the time of
the LogEntry is assigned the value of the `Clock` of the Composition's `scheduler` or `scheduler_learning`,
whichever is currently executing (see `Composition_Scheduler`).
Arguments
---------
entries : string, Component or list containing either : default ALL
specifies the Components, the current `value <Component.value>`\\s of which should be added prepared for
transmission to an external application via gRPC.
they must be `loggable_items <Log.loggable_items>` of the owner's Log. If **entries** is *ALL* or is not
specified, then the `value <Component.value>`\\s of all `loggable_items <Log.loggable_items>` are logged.
"""
entries = self._validate_entries_arg(entries)
original_source = context.source
context.source = ContextFlags.COMMAND_LINE

# Validate the Component field of each LogEntry
for entry in entries:
param = self._get_parameter_from_item_string(entry)
context = parse_context(context)
param._deliver_value(param._get(context), context)

context.source = original_source

@tc.typecheck
def _log_value(
self,
Expand Down
Loading

0 comments on commit c1c423b

Please sign in to comment.