"""Odds and ends
"""
+import importlib as _importlib
+import pickle as _pickle
+import pickletools as _pickletools
import sys as _sys
import threading as _threading
elif self.isAlive():
raise _error.TimeoutError(time_limited_function=self)
return self.result
+
+
+def import_name(obj):
+ """Return the full import name for a Python object
+
+ Note that this does not always exist (e.g. for dynamically
+ generated functions). This function does it's best, using Pickle
+ for the heavy lifting. For example:
+
+ >>> import_name(import_name)
+ 'rss2email.util import_name'
+
+ Note the space between the module (``rss2email.util``) and the
+ function within the module (``import_name``).
+
+ Some objects can't be pickled:
+
+ >>> import_name(lambda x: 'muahaha')
+ Traceback (most recent call last):
+ ...
+ _pickle.PicklingError: Can't pickle <class 'function'>: attribute lookup builtins.function failed
+
+ Some objects don't have a global scope:
+
+ >>> import_name('abc')
+ Traceback (most recent call last):
+ ...
+ ValueError: abc
+ """
+ pickle = _pickle.dumps(obj)
+ for opcode,arg,pos in _pickletools.genops(pickle):
+ if opcode.name == 'GLOBAL':
+ return arg
+ raise ValueError(obj)
+
+def import_function(name):
+ """Import a function using the full import name
+
+ >>> import_function('rss2email.util import_function') # doctest: +ELLIPSIS
+ <function import_function at 0x...>
+ >>> import_function(import_name(import_function)) # doctest: +ELLIPSIS
+ <function import_function at 0x...>
+
+ >>> import_function('rss2email.util does_not_exist')
+ Traceback (most recent call last):
+ ...
+ AttributeError: 'module' object has no attribute 'does_not_exist'
+ >>> import_function('rss2email.util has invalid syntax')
+ Traceback (most recent call last):
+ ...
+ AttributeError: 'module' object has no attribute 'has invalid syntax'
+ >>> import_function('rss2email.util.no_space')
+ Traceback (most recent call last):
+ ...
+ ValueError: rss2email.util.no_space
+ """
+ try:
+ module_name,function_name = name.split(' ', 1)
+ except ValueError as e:
+ raise ValueError(name) from e
+ module = _importlib.import_module(module_name)
+ return getattr(module, function_name)