Skip to content

Commit

Permalink
Merge pull request #96 from ZLLentz/subdevice-ns-2
Browse files Browse the repository at this point in the history
ENH: Include Subcomponent in Class Namespace
  • Loading branch information
ZLLentz authored Apr 6, 2018
2 parents acdc3ae + d66c472 commit 6044411
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,6 @@ conda-bld-tst

# generated file
hutch_python/tests/tst/db.txt

# pytest
.pytest_cache
23 changes: 23 additions & 0 deletions hutch_python/namespace.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
from inspect import isfunction
import logging

from ophyd import Device

from .utils import (IterableNamespace, find_class, strip_prefix,
extract_objs)

Expand All @@ -22,6 +24,10 @@ def class_namespace(cls, scope=None):
Every object attached to the given modules will be considered for the
`class_namespace`. If ``scope`` is omitted, we'll check all objects
loaded by ``hutch-python`` and everything in the caller's global frame.
If anything is an instance of ``ophyd.Device``, we'll also include the
object's components as part of the scope, using the ``name`` attribute
to identify them rather than the attribute name on the device. This
will continue recursively.
Returns
-------
Expand All @@ -41,6 +47,23 @@ def class_namespace(cls, scope=None):
logger.debug(exc, exc_info=True)
return class_space

cache = set()

# Helper function to recursively add subdevices to the scope
def accumulate(obj, scope_objs, cache):
if obj not in cache:
cache.add(obj)
for comp_name in getattr(obj, 'component_names', []):
sub_obj = getattr(obj, comp_name)
accumulate(sub_obj, scope_objs, cache)
# Don't accidentally override
if obj.name not in scope_objs:
scope_objs[obj.name] = obj

for name, obj in scope_objs.copy().items():
if isinstance(obj, Device):
accumulate(obj, scope_objs, cache)

for name, obj in scope_objs.items():
include = False
if cls == 'function':
Expand Down
19 changes: 19 additions & 0 deletions hutch_python/tests/test_namespace.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import logging
from types import SimpleNamespace

from ophyd.device import Device, Component
from ophyd.signal import Signal

from hutch_python.namespace import class_namespace, metadata_namespace


Expand All @@ -22,6 +25,22 @@ def test_class_namespace():
assert len(err_space) == 0


class NormalDevice(Device):
apples = Component(Device)
oranges = Component(Signal)


def test_class_namespace_subdevices():
logger.debug('test_class_namespace_subdevices')
scope = SimpleNamespace(tree=NormalDevice(name='tree'))
device_space = class_namespace(Device, scope)
assert isinstance(device_space.tree_apples, Device)
assert isinstance(device_space.tree, NormalDevice)
assert not hasattr(device_space, 'apples')
assert not hasattr(device_space, 'oranges')
assert not hasattr(device_space, 'tree_oranges')


def test_metadata_namespace():
logger.debug('test_metadata_namespace')
obj1 = SimpleNamespace()
Expand Down

0 comments on commit 6044411

Please sign in to comment.