loading.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. # Copyright 2012 Matt Chaput. All rights reserved.
  2. #
  3. # Redistribution and use in source and binary forms, with or without
  4. # modification, are permitted provided that the following conditions are met:
  5. #
  6. # 1. Redistributions of source code must retain the above copyright notice,
  7. # this list of conditions and the following disclaimer.
  8. #
  9. # 2. Redistributions in binary form must reproduce the above copyright
  10. # notice, this list of conditions and the following disclaimer in the
  11. # documentation and/or other materials provided with the distribution.
  12. #
  13. # THIS SOFTWARE IS PROVIDED BY MATT CHAPUT ``AS IS'' AND ANY EXPRESS OR
  14. # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  15. # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
  16. # EVENT SHALL MATT CHAPUT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  17. # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  18. # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
  19. # OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  20. # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  21. # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  22. # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  23. #
  24. # The views and conclusions contained in the software and documentation are
  25. # those of the authors and should not be interpreted as representing official
  26. # policies, either expressed or implied, of Matt Chaput.
  27. import pickle
  28. class RenamingUnpickler(pickle.Unpickler):
  29. """Subclasses ``pickle.Unpickler`` to allow remapping of class names before
  30. loading them.
  31. """
  32. def __init__(self, f, objmap, shortcuts=None):
  33. pickle.Unpickler.__init__(self, f)
  34. if shortcuts:
  35. objmap = dict((k % shortcuts, v % shortcuts)
  36. for k, v in objmap.items())
  37. self._objmap = objmap
  38. def find_class(self, modulename, objname):
  39. fqname = "%s.%s" % (modulename, objname)
  40. if fqname in self._objmap:
  41. fqname = self._objmap[fqname]
  42. try:
  43. obj = find_object(fqname)
  44. except ImportError:
  45. raise ImportError("Couldn't find %r" % fqname)
  46. return obj
  47. def find_object(name, blacklist=None, whitelist=None):
  48. """Imports and returns an object given a fully qualified name.
  49. >>> find_object("whoosh.analysis.StopFilter")
  50. <class 'whoosh.analysis.StopFilter'>
  51. """
  52. if blacklist:
  53. for pre in blacklist:
  54. if name.startswith(pre):
  55. raise TypeError("%r: can't instantiate names starting with %r"
  56. % (name, pre))
  57. if whitelist:
  58. passes = False
  59. for pre in whitelist:
  60. if name.startswith(pre):
  61. passes = True
  62. break
  63. if not passes:
  64. raise TypeError("Can't instantiate %r" % name)
  65. lastdot = name.rfind(".")
  66. assert lastdot > -1, "Name %r must be fully qualified" % name
  67. modname = name[:lastdot]
  68. clsname = name[lastdot + 1:]
  69. mod = __import__(modname, fromlist=[clsname])
  70. cls = getattr(mod, clsname)
  71. return cls