|
44 | 44 |
|
45 | 45 | import operator
|
46 | 46 | import io
|
| 47 | +import imp |
47 | 48 | import pickle
|
48 | 49 | import struct
|
49 | 50 | import sys
|
@@ -134,8 +135,19 @@ def save_module(self, obj):
|
134 | 135 | """
|
135 | 136 | Save a module as an import
|
136 | 137 | """
|
| 138 | + mod_name = obj.__name__ |
| 139 | + # If module is successfully found then it is not a dynamically created module |
| 140 | + try: |
| 141 | + _find_module(mod_name) |
| 142 | + is_dynamic = False |
| 143 | + except ImportError: |
| 144 | + is_dynamic = True |
| 145 | + |
137 | 146 | self.modules.add(obj)
|
138 |
| - self.save_reduce(subimport, (obj.__name__,), obj=obj) |
| 147 | + if is_dynamic: |
| 148 | + self.save_reduce(dynamic_subimport, (obj.__name__, vars(obj)), obj=obj) |
| 149 | + else: |
| 150 | + self.save_reduce(subimport, (obj.__name__,), obj=obj) |
139 | 151 | dispatch[types.ModuleType] = save_module
|
140 | 152 |
|
141 | 153 | def save_codeobject(self, obj):
|
@@ -313,7 +325,7 @@ def extract_func_data(self, func):
|
313 | 325 | return (code, f_globals, defaults, closure, dct, base_globals)
|
314 | 326 |
|
315 | 327 | def save_builtin_function(self, obj):
|
316 |
| - if obj.__module__ is "__builtin__": |
| 328 | + if obj.__module__ == "__builtin__": |
317 | 329 | return self.save_global(obj)
|
318 | 330 | return self.save_function(obj)
|
319 | 331 | dispatch[types.BuiltinFunctionType] = save_builtin_function
|
@@ -584,11 +596,20 @@ def save_file(self, obj):
|
584 | 596 | self.save(retval)
|
585 | 597 | self.memoize(obj)
|
586 | 598 |
|
| 599 | + def save_ellipsis(self, obj): |
| 600 | + self.save_reduce(_gen_ellipsis, ()) |
| 601 | + |
| 602 | + def save_not_implemented(self, obj): |
| 603 | + self.save_reduce(_gen_not_implemented, ()) |
| 604 | + |
587 | 605 | if PY3:
|
588 | 606 | dispatch[io.TextIOWrapper] = save_file
|
589 | 607 | else:
|
590 | 608 | dispatch[file] = save_file
|
591 | 609 |
|
| 610 | + dispatch[type(Ellipsis)] = save_ellipsis |
| 611 | + dispatch[type(NotImplemented)] = save_not_implemented |
| 612 | + |
592 | 613 | """Special functions for Add-on libraries"""
|
593 | 614 | def inject_addons(self):
|
594 | 615 | """Plug in system. Register additional pickling functions if modules already loaded"""
|
@@ -620,6 +641,12 @@ def subimport(name):
|
620 | 641 | return sys.modules[name]
|
621 | 642 |
|
622 | 643 |
|
| 644 | +def dynamic_subimport(name, vars): |
| 645 | + mod = imp.new_module(name) |
| 646 | + mod.__dict__.update(vars) |
| 647 | + sys.modules[name] = mod |
| 648 | + return mod |
| 649 | + |
623 | 650 | # restores function attributes
|
624 | 651 | def _restore_attr(obj, attr):
|
625 | 652 | for key, val in attr.items():
|
@@ -663,6 +690,11 @@ def _genpartial(func, args, kwds):
|
663 | 690 | kwds = {}
|
664 | 691 | return partial(func, *args, **kwds)
|
665 | 692 |
|
| 693 | +def _gen_ellipsis(): |
| 694 | + return Ellipsis |
| 695 | + |
| 696 | +def _gen_not_implemented(): |
| 697 | + return NotImplemented |
666 | 698 |
|
667 | 699 | def _fill_function(func, globals, defaults, dict):
|
668 | 700 | """ 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):
|
698 | 730 | None, None, closure)
|
699 | 731 |
|
700 | 732 |
|
| 733 | +def _find_module(mod_name): |
| 734 | + """ |
| 735 | + Iterate over each part instead of calling imp.find_module directly. |
| 736 | + This function is able to find submodules (e.g. sickit.tree) |
| 737 | + """ |
| 738 | + path = None |
| 739 | + for part in mod_name.split('.'): |
| 740 | + if path is not None: |
| 741 | + path = [path] |
| 742 | + file, path, description = imp.find_module(part, path) |
| 743 | + return file, path, description |
| 744 | + |
701 | 745 | """Constructors for 3rd party libraries
|
702 | 746 | Note: These can never be renamed due to client compatibility issues"""
|
703 | 747 |
|
|
0 commit comments