Skip to content

Commit

Permalink
Merge pull request #696 from jerynmathew/fix/693-config-pyc
Browse files Browse the repository at this point in the history
Fix for #693
  • Loading branch information
tilgovi committed Mar 17, 2014
2 parents 4c7b17e + b6f3cb8 commit 21ea843
Showing 1 changed file with 62 additions and 2 deletions.
64 changes: 62 additions & 2 deletions gunicorn/six.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,63 @@ def StringIO(buf=''):
_add_doc(u, """Text literal""")


def _check_if_pyc(fname):
""" Returns 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


if PY3:

import builtins
Expand All @@ -300,7 +357,7 @@ def reraise(tp, value, tb=None):
print_ = getattr(builtins, "print")

def execfile_(fname, *args):
return exec_(compile(open(fname, 'rb').read(), fname, 'exec'), *args)
return exec_(_get_codeobj(fname), *args)


del builtins
Expand All @@ -323,7 +380,10 @@ def exec_(code, globs=None, locs=None):
raise tp, value, tb
""")

execfile_ = execfile
def execfile_(fname, *args):
""" Overriding PY2 execfile() implementation to support .pyc files """
return exec_(_get_codeobj(fname), *args)


def print_(*args, **kwargs):
"""The new-style print function."""
Expand Down

0 comments on commit 21ea843

Please sign in to comment.