Use SourceFileLoader instead instead of execfile_ (#2046)

This commit is contained in:
Masashi SHIBATA 2019-05-27 04:09:52 +09:00 committed by Berker Peksag
parent 3701ad9f26
commit a13a2096ed
3 changed files with 17 additions and 81 deletions

View File

@ -1,65 +0,0 @@
def _check_if_pyc(fname):
"""Return True if the extension is .pyc, False if .py
and None if otherwise"""
from imp import find_module
from os.path import realpath, dirname, basename, splitext
# Normalize the file-path for the find_module()
filepath = realpath(fname)
dirpath = dirname(filepath)
module_name = splitext(basename(filepath))[0]
# Validate and fetch
try:
fileobj, fullpath, (_, _, pytype) = find_module(module_name, [dirpath])
except ImportError:
raise IOError("Cannot find config file. "
"Path maybe incorrect! : {0}".format(filepath))
return pytype, fileobj, fullpath
def _get_codeobj(pyfile):
""" Returns the code object, given a python file """
from imp import PY_COMPILED, PY_SOURCE
result, fileobj, fullpath = _check_if_pyc(pyfile)
# WARNING:
# fp.read() can blowup if the module is extremely large file.
# Lookout for overflow errors.
try:
data = fileobj.read()
finally:
fileobj.close()
# This is a .pyc file. Treat accordingly.
if result is PY_COMPILED:
# .pyc format is as follows:
# 0 - 4 bytes: Magic number, which changes with each create of .pyc file.
# First 2 bytes change with each marshal of .pyc file. Last 2 bytes is "\r\n".
# 4 - 8 bytes: Datetime value, when the .py was last changed.
# 8 - EOF: Marshalled code object data.
# So to get code object, just read the 8th byte onwards till EOF, and
# UN-marshal it.
import marshal
code_obj = marshal.loads(data[8:])
elif result is PY_SOURCE:
# This is a .py file.
code_obj = compile(data, fullpath, 'exec')
else:
# Unsupported extension
raise Exception("Input file is unknown format: {0}".format(fullpath))
# Return code object
return code_obj
def execfile_(fname, *args):
if fname.endswith(".pyc"):
code = _get_codeobj(fname)
else:
with open(fname, 'rb') as file:
code = compile(file.read(), fname, 'exec')
return exec(code, *args)

View File

@ -2,16 +2,18 @@
#
# This file is part of gunicorn released under the MIT license.
# See the NOTICE for more information.
import importlib.machinery
import os
import sys
import traceback
import types
from gunicorn._compat import execfile_
from gunicorn import util
from gunicorn.arbiter import Arbiter
from gunicorn.config import Config, get_default_config_file
from gunicorn import debug
class BaseApplication(object):
"""
An application interface for configuring and loading
@ -93,22 +95,18 @@ class Application(BaseApplication):
if not os.path.exists(filename):
raise RuntimeError("%r doesn't exist" % filename)
cfg = {
"__builtins__": __builtins__,
"__name__": "__config__",
"__file__": filename,
"__doc__": None,
"__package__": None
}
try:
execfile_(filename, cfg, cfg)
module_name = '__config__'
mod = types.ModuleType(module_name)
loader = importlib.machinery.SourceFileLoader(module_name, filename)
loader.exec_module(mod)
except Exception:
print("Failed to read config file: %s" % filename, file=sys.stderr)
traceback.print_exc()
sys.stderr.flush()
sys.exit(1)
return cfg
return vars(mod)
def get_config_from_module_name(self, module_name):
return vars(util.import_module(module_name))

View File

@ -4,10 +4,11 @@
# under the MIT license.
import inspect
import importlib.machinery
import os
import random
import types
from gunicorn._compat import execfile_
from gunicorn.config import Config
from gunicorn.http.parser import RequestParser
from gunicorn.util import split_request_uri
@ -29,11 +30,13 @@ def uri(data):
def load_py(fname):
config = globals().copy()
config["uri"] = uri
config["cfg"] = Config()
execfile_(fname, config)
return config
module_name = '__config__'
mod = types.ModuleType(module_name)
setattr(mod, 'uri', uri)
setattr(mod, 'cfg', Config())
loader = importlib.machinery.SourceFileLoader(module_name, fname)
loader.exec_module(mod)
return vars(mod)
class request(object):