Source code for original
"""
Import hook extending pytz package with usable, generic timezones:
GMT-14 up to GMT+12.
Note that pytz already has Etc/GMT+X timezones, but
(quoting Wikipedia):
"In order to conform with the POSIX style, those zones beginning with "Etc/GMT"
have their sign reversed from what most people expect. In this style,
zones west of GMT have a positive sign and those east have a negative sign."
Because this is insane, we are simply introducing our own zones
that will not have this fatal flaw.
Alternatively one might prepend ti the __path__ attribute of a
module
"""
# Note: I setup DEBUG to hide the verbose output when one uses
# the module. This was used for testing the module and finding
# issues and will still be used as such. For day to day use it
# is presently disabled.
import os
import sys
import imp
from pprint import pprint
DEBUG = False
[docs]class OverlayImporter(object):
# PEP302 prescribes the use of two different classes, finder
# and loader, for finding and loading modules respectively.
# Each class respectively provides a single method, find_module
# and load_module.
def __init__(self, *args, **kvps):
if DEBUG : print("New Instance")
self.mask = "_{}_"
self.trap = None
[docs] def mapTarget(self, name) :
return self.mask.format(name)
[docs] def mapSource(self, name) :
mask = self.mask.split("{}")
return name[len(mask[0]):-len(mask[-1])]
[docs] def rename(self, name) :
# Currently this assumes the module is one level deep within
# the package, that is the following structure is expcted
#
# package\ The folder containing the __init__.py you are reading
# _module_ The module you are patching renamed with underscores
#
return ".".join([item if enum!=1 else "_{}_".format(item) for enum, item in enumerate(name.split('.'))])
[docs] def overlays(self) :
# This is simply the list of modules that are patched under
# this overlay.
modules = [os.path.splitext(item)[0] for item in os.listdir(__path__[0]) if os.path.splitext(item)[0] not in ["__init__","__pycache__"]]
if self.trap :
return [self.mapSource(os.path.splitext(item)[0]) for item in modules]
else :
return modules
[docs] def find_module(self, name, path=None):
# Deprecated use :
#
# Python > 3.3 use IMPORTLIB.UTIL.FIND_SPEC
# Python = 3.3 use IMPORTLIB.FIND_LOADER
#
bits = name.split('.')
if DEBUG : print("Searching > {1:<40} {0:<40}".format(name, str(path)))
if len(bits) > 1 and self.mapTarget(bits[-1]) in self.overlays(): # Note : the clamp on bit length is to ensure the importer rolls back to root to import patched modules.
self.path = path
if DEBUG : print("Discovered : {}".format(name))
return self
if bits[-1] == self.trap :
for meta in sys.meta_path :
if meta is not self :
self.temp = meta.find_module(name, path)
if self.temp :
if DEBUG : print("Discovered : {}".format(name))
return self
return None
[docs] def load_module(self, name):
# Deprecated replace with the classes in IMPORTLIB.MACHINERY
#
# If IMP.LOAD_MODULE was used with IMP.FIND_MODULE previously
# then IMPORTLIB.IMPORT_MODULE is a better substitute. If not
# then use the loader that pairs with the prior finder. That
# is one of :
#
# IMPORTLIB.UTIL.FIND_SPEC <->
# IMPORTLIB.FIND_LOADER <->
#
if DEBUG : print("Importing > {}".format(name))
parent, _, module = name.rpartition('.')
if self.trap :
self.trap = None
if DEBUG : print("Pass Trapped")
temp = self.temp.load_module()
sys.modules[self.mapTarget(name)] = temp
if DEBUG : print("Imported < {}".format(self.mapTarget(name)))
return temp
else :
if DEBUG : print("Pass Through")
# if module not in self.overlays(): # Not Importable
# raise ImportError("%s can only be used to import pytz!",self.__class__.__name__) # Inclde module name and possibly modules
if name in sys.modules: # Already Imported
return sys.modules[name] # Modules' absolute path
self.trap = module
file, path, desc = imp.find_module(self.mapTarget(module), self.path) # NB !!! This was psuedo
try:
temp = imp.load_module(name, file, path, desc)
finally:
if file:
file.close()
sys.modules[module] = temp
if DEBUG : print("Imported < {}".format(module))
return temp
sys.meta_path.insert(0,OverlayImporter())