Skip to content

Commit

Permalink
adjust how canning deals with import strings
Browse files Browse the repository at this point in the history
* imports should only happen once
* errors should only be logged when *user* imports fail (not no-numpy)
  • Loading branch information
minrk committed Jul 30, 2012
1 parent 2ff8a90 commit 4bca5d9
Showing 1 changed file with 54 additions and 17 deletions.
71 changes: 54 additions & 17 deletions IPython/utils/pickleutil.py
Expand Up @@ -152,27 +152,56 @@ def CannedBuffer(CannedBytes):
# Functions
#-------------------------------------------------------------------------------

def _error(*args, **kwargs):
def _logger():
"""get the logger for the current Application
the root logger will be used if no Application is running
"""
if Application.initialized():
logger = Application.instance().log
else:
logger = logging.getLogger()
if not logger.handlers:
logging.basicConfig()
logger.error(*args, **kwargs)

return logger

def _import_mapping(mapping, original=None):
"""import any string-keys in a type mapping
"""
log = _logger()
log.debug("Importing canning map")
for key,value in mapping.items():
if isinstance(key, basestring):
try:
cls = import_item(key)
except Exception:
if original and key not in original:
# only message on user-added classes
log.error("cannning class not importable: %r", key, exc_info=True)
mapping.pop(key)
else:
mapping[cls] = mapping.pop(key)

def can(obj):
"""prepare an object for pickling"""

import_needed = False

for cls,canner in can_map.iteritems():
if isinstance(cls, basestring):
try:
cls = import_item(cls)
except Exception:
_error("cannning class not importable: %r", cls, exc_info=True)
cls = None
continue
if isinstance(obj, cls):
import_needed = True
break
elif isinstance(obj, cls):
return canner(obj)

if import_needed:
# perform can_map imports, then try again
# this will usually only happen once
_import_mapping(can_map, _original_can_map)
return can(obj)

return obj

def can_dict(obj):
Expand All @@ -195,16 +224,21 @@ def can_sequence(obj):

def uncan(obj, g=None):
"""invert canning"""

import_needed = False
for cls,uncanner in uncan_map.iteritems():
if isinstance(cls, basestring):
try:
cls = import_item(cls)
except Exception:
_error("uncanning class not importable: %r", cls, exc_info=True)
cls = None
continue
if isinstance(obj, cls):
import_needed = True
break
elif isinstance(obj, cls):
return uncanner(obj, g)

if import_needed:
# perform uncan_map imports, then try again
# this will usually only happen once
_import_mapping(uncan_map, _original_uncan_map)
return uncan(obj, g)

return obj

def uncan_dict(obj, g=None):
Expand All @@ -225,7 +259,7 @@ def uncan_sequence(obj, g=None):


#-------------------------------------------------------------------------------
# API dictionary
# API dictionaries
#-------------------------------------------------------------------------------

# These dicts can be extended for custom serialization of new objects
Expand All @@ -242,3 +276,6 @@ def uncan_sequence(obj, g=None):
CannedObject : lambda obj, g: obj.get_object(g),
}

# for use in _import_mapping:
_original_can_map = can_map.copy()
_original_uncan_map = uncan_map.copy()

0 comments on commit 4bca5d9

Please sign in to comment.