1
0
mirror of https://github.com/Tygs/0bin.git synced 2023-08-10 21:13:00 +03:00

Use runpy.run_path() or execfile() instead of import machinery for --settings-file.

Problem with import is that it:

 - Reuses already-imported module.

  For example, --settings-file=/etc/zerobin.py won't be imported,
  because sys.modules will already contain 'zerobin' entry.

 - Alters sys.path.

  Importing module from a heavily-populated directory may potentially
  cause next imports to run code from totally unexpected places.

Using execfile() doesn't set some globals like __file__ as import does,
which has to be done manually.
It also might be a bit slower for large body of code in settings file.

runpy.run_path() can only be used on python-2.7, but does not seem
to have any downsides.
This commit is contained in:
Mike Kazantsev 2013-04-20 02:16:34 +06:00 committed by fraggod@sacrilege
parent dcefd57875
commit 04f44debaf

View File

@ -14,6 +14,15 @@ try:
except (AttributeError): except (AttributeError):
pass # privilege does't work on several plateform pass # privilege does't work on several plateform
try:
from runpy import run_path
except ImportError:
# python-2.6 or earlier - use simplier less-optimized execfile()
def run_path(file_path):
mod_globals = {'__file__': file_path}
execfile(file_path, mod_globals)
return mod_globals
def drop_privileges(user=None, group=None, wait=5): def drop_privileges(user=None, group=None, wait=5):
""" """
@ -69,17 +78,25 @@ class SettingsContainer(object):
return cls._instance return cls._instance
def update_with_module(self, module): def update_with_dict(self, dict):
""" """
Update settings with values from the given module. Update settings with values from the given mapping object.
(Taking only variable with uppercased name) (Taking only variable with uppercased name)
""" """
for name, value in module.__dict__.iteritems(): for name, value in dict.iteritems():
if name.isupper(): if name.isupper():
setattr(self, name, value) setattr(self, name, value)
return self return self
def update_with_module(self, module):
"""
Update settings with values from the given module.
Uses update_with_dict() behind the scenes.
"""
return self.update_with_dict(module.__dict__)
@classmethod @classmethod
def from_module(cls, module): def from_module(cls, module):
""" """
@ -94,11 +111,10 @@ class SettingsContainer(object):
def update_with_file(self, filepath): def update_with_file(self, filepath):
""" """
Update settings with values from the given module file. Update settings with values from the given module file.
User update_with_module() behind the scene Uses update_with_dict() behind the scenes.
""" """
sys.path.insert(0, os.path.dirname(filepath)) settings = run_path(filepath)
module_name = os.path.splitext(os.path.basename(filepath))[0] return self.update_with_dict(settings)
return self.update_with_module(__import__(module_name))
settings = SettingsContainer() settings = SettingsContainer()