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):
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):
"""
@ -69,17 +78,25 @@ class SettingsContainer(object):
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)
"""
for name, value in module.__dict__.iteritems():
for name, value in dict.iteritems():
if name.isupper():
setattr(self, name, value)
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
def from_module(cls, module):
"""
@ -94,11 +111,10 @@ class SettingsContainer(object):
def update_with_file(self, filepath):
"""
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))
module_name = os.path.splitext(os.path.basename(filepath))[0]
return self.update_with_module(__import__(module_name))
settings = run_path(filepath)
return self.update_with_dict(settings)
settings = SettingsContainer()