-
Notifications
You must be signed in to change notification settings - Fork 180
Add ability to pickle dynamically create modules #52
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -44,6 +44,7 @@ | |
|
||
import operator | ||
import io | ||
import imp | ||
import pickle | ||
import struct | ||
import sys | ||
|
@@ -134,8 +135,19 @@ def save_module(self, obj): | |
""" | ||
Save a module as an import | ||
""" | ||
mod_name = obj.__name__ | ||
# If module is successfully found then it is not a dynamically created module | ||
try: | ||
_find_module(mod_name) | ||
is_dynamic = False | ||
except ImportError: | ||
is_dynamic = True | ||
|
||
self.modules.add(obj) | ||
self.save_reduce(subimport, (obj.__name__,), obj=obj) | ||
if is_dynamic: | ||
self.save_reduce(dynamic_subimport, (obj.__name__, vars(obj)), obj=obj) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
else: | ||
self.save_reduce(subimport, (obj.__name__,), obj=obj) | ||
dispatch[types.ModuleType] = save_module | ||
|
||
def save_codeobject(self, obj): | ||
|
@@ -313,7 +325,7 @@ def extract_func_data(self, func): | |
return (code, f_globals, defaults, closure, dct, base_globals) | ||
|
||
def save_builtin_function(self, obj): | ||
if obj.__module__ is "__builtin__": | ||
if obj.__module__ == "__builtin__": | ||
return self.save_global(obj) | ||
return self.save_function(obj) | ||
dispatch[types.BuiltinFunctionType] = save_builtin_function | ||
|
@@ -584,11 +596,20 @@ def save_file(self, obj): | |
self.save(retval) | ||
self.memoize(obj) | ||
|
||
def save_ellipsis(self, obj): | ||
self.save_reduce(_gen_ellipsis, ()) | ||
|
||
def save_not_implemented(self, obj): | ||
self.save_reduce(_gen_not_implemented, ()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Was this not handled by normal exceptions? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, my apologies, I was thinking of |
||
|
||
if PY3: | ||
dispatch[io.TextIOWrapper] = save_file | ||
else: | ||
dispatch[file] = save_file | ||
|
||
dispatch[type(Ellipsis)] = save_ellipsis | ||
dispatch[type(NotImplemented)] = save_not_implemented | ||
|
||
"""Special functions for Add-on libraries""" | ||
def inject_addons(self): | ||
"""Plug in system. Register additional pickling functions if modules already loaded""" | ||
|
@@ -620,6 +641,12 @@ def subimport(name): | |
return sys.modules[name] | ||
|
||
|
||
def dynamic_subimport(name, vars): | ||
mod = imp.new_module(name) | ||
mod.__dict__.update(vars) | ||
sys.modules[name] = mod | ||
return mod | ||
|
||
# restores function attributes | ||
def _restore_attr(obj, attr): | ||
for key, val in attr.items(): | ||
|
@@ -663,6 +690,11 @@ def _genpartial(func, args, kwds): | |
kwds = {} | ||
return partial(func, *args, **kwds) | ||
|
||
def _gen_ellipsis(): | ||
return Ellipsis | ||
|
||
def _gen_not_implemented(): | ||
return NotImplemented | ||
|
||
def _fill_function(func, globals, defaults, dict): | ||
""" Fills in the rest of function data into the skeleton function object | ||
|
@@ -698,6 +730,18 @@ def _make_skel_func(code, closures, base_globals = None): | |
None, None, closure) | ||
|
||
|
||
def _find_module(mod_name): | ||
""" | ||
Iterate over each part instead of calling imp.find_module directly. | ||
This function is able to find submodules (e.g. sickit.tree) | ||
""" | ||
path = None | ||
for part in mod_name.split('.'): | ||
if path is not None: | ||
path = [path] | ||
file, path, description = imp.find_module(part, path) | ||
return file, path, description | ||
|
||
"""Constructors for 3rd party libraries | ||
Note: These can never be renamed due to client compatibility issues""" | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it make sense to pull this logic out into a separate function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree