Skip to content

Commit

Permalink
Merge ff2f9f7 into 02de256
Browse files Browse the repository at this point in the history
  • Loading branch information
tfarago committed Apr 21, 2016
2 parents 02de256 + ff2f9f7 commit feae62f
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 3 deletions.
2 changes: 2 additions & 0 deletions bin/concert
Expand Up @@ -411,6 +411,7 @@ class StartCommand(Command):
self.run_shell(module)

def run_shell(self, module=None):
import concert
from concert.base import (UnitError, LimitError, ParameterError,
ReadAccessError, WriteAccessError, LockError)

Expand All @@ -435,6 +436,7 @@ class StartCommand(Command):

if not module:
from concert.quantities import q
concert.base._get_instance_variable_name.memo = {}

try:
shell = get_ipython_shell(config=config)
Expand Down
50 changes: 47 additions & 3 deletions concert/base.py
Expand Up @@ -312,9 +312,10 @@ def __set__(self, instance, value):
except AccessorNotImplementedError:
raise WriteAccessError(self.name)

msg = "set {}::{}='{}'"
name = instance.__class__.__name__
LOG.info(msg.format(name, self.name, value))
msg = "set {}:{}::{}='{}'"
cls = instance.__class__.__name__
name = _get_instance_variable_name(instance)
LOG.info(msg.format(cls, name, self.name, value))
except KeyboardInterrupt:
cancel_name = '_cancel_' + self.name
if hasattr(instance, cancel_name):
Expand Down Expand Up @@ -860,3 +861,46 @@ def unlock(self):
"""Unlock all the parameters for writing."""
for param in self:
param.unlock()


def _get_instance_variable_name(instance):
def parse_namespace(namespace, instance_type):
# We ignore some very low-level instantiations
blacklist = ['self', 'instance']
for key, obj in namespace.items():
if isinstance(obj, instance_type) and obj == instance and key not in blacklist:
return key

if (_get_instance_variable_name.memo is not None and hasattr(instance, '_name_cache') and
instance._name_cache in _get_instance_variable_name.memo):
# Only search the cache if allowed, i.e. when the session has started. In this case the memo
# variable is a dictionary
return _get_instance_variable_name.memo[instance._name_cache]
# Tag the instance to prevent ambiguity based on id. If an instance at a later time point
# shares the same id it doesn't have this attribute, hence it will invalidate the old
# entry
instance._name_cache = id(instance)

try:
# The actual lookup
frames = zip(*inspect.stack())[0]
frame = None
instance_type = type(instance)
# Search in top-down direction because the user-defined variable names are likely to appear
# at the top level
for frame in frames[::-1]:
name = parse_namespace(frame.f_globals, instance_type)
if not name:
name = parse_namespace(frame.f_locals, instance_type)
if name:
if _get_instance_variable_name.memo is not None:
_get_instance_variable_name.memo[instance._name_cache] = name
return name
return ''
finally:
# Do not create cyclic references on frames
del frame
del frames


_get_instance_variable_name.memo = None

0 comments on commit feae62f

Please sign in to comment.