From 8b49de4ad264d629a8ef6e267fe5588172338dd1 Mon Sep 17 00:00:00 2001 From: Jeryn Mathew Date: Thu, 6 Feb 2014 13:07:22 +0530 Subject: [PATCH] Fix for issue #693 - Made changes to read and fetch code object from .pyc files. - Error message "Non-ASCII character '\xf3' in file" is resolved. --- gunicorn/six.py | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/gunicorn/six.py b/gunicorn/six.py index e05e25f66..62c47be7b 100644 --- a/gunicorn/six.py +++ b/gunicorn/six.py @@ -286,6 +286,50 @@ 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 """ + # Make common lambda + test = lambda ext: True if fname.rfind(ext) == len(fname) - len(ext) else False + # Run test + if test(".pyc"): + # TODO: Actually check if file content is .pyc compliant + return True + elif test(".py"): + # TODO: Actually check if file is .py by trying to import + return False + else: + return None + + +def _get_codeobj(pyfile): + """ Returns the code object, given a python file """ + result = _check_if_pyc(pyfile) + if result is True: + # This is a .pyc file. Treat accordingly. + with open(pyfile, "rb") as pycfile: + data = pycfile.read() + + # .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 False: + # This is a .py file. + code_obj = compile(open(pyfile, 'rb').read(), pyfile, 'exec') + + else: + # Dunno what this is... + raise Exception("Input file is unknown format: {0}".format(pyfile)) + + # Return code object + return code_obj + + if PY3: import builtins