Repository: hylang/hy

Issue:
wr_long missing from python3.4, pyc generation toast
we might need to have a pre 3.4 and post 3.4 logic to this. Big changes in this file. Will look more at it later.



Discussion:

Resolving patch:
diff --git a/hy/_compat.py b/hy/_compat.py
--- a/hy/_compat.py
+++ b/hy/_compat.py
@@ -1,5 +1,6 @@
 # Copyright (c) 2013 Paul Tagliamonte <paultag@debian.org>
 # Copyright (c) 2013 Julien Danjou <julien@danjou.info>
+# Copyright (c) 2013 Berker Peksag <berker.peksag@gmail.com>
 #
 # Permission is hereby granted, free of charge, to any person obtaining a
 # copy of this software and associated documentation files (the "Software"),
@@ -23,9 +24,23 @@
     import __builtin__ as builtins
 except ImportError:
     import builtins  # NOQA
+try:
+    from py_compile import MAGIC, wr_long
+except ImportError:
+    # py_compile.MAGIC removed and imp.get_magic() deprecated in Python 3.4
+    from importlib.util import MAGIC_NUMBER as MAGIC  # NOQA
+
+    def wr_long(f, x):
+        """Internal; write a 32-bit int to a file in little-endian order."""
+        f.write(bytes([x & 0xff,
+                       (x >> 8) & 0xff,
+                       (x >> 16) & 0xff,
+                       (x >> 24) & 0xff]))
 import sys
 
 PY3 = sys.version_info[0] >= 3
+PY33 = sys.version_info >= (3, 3)
+PY34 = sys.version_info >= (3, 4)
 
 if PY3:
     str_type = str
diff --git a/hy/compiler.py b/hy/compiler.py
--- a/hy/compiler.py
+++ b/hy/compiler.py
@@ -39,7 +39,7 @@
 
 import hy.macros
 from hy.macros import require, macroexpand
-from hy._compat import str_type, long_type
+from hy._compat import str_type, long_type, PY33, PY3, PY34
 import hy.importer
 
 import traceback
@@ -77,7 +77,7 @@ def load_stdlib():
 
 
 def ast_str(foobar):
-    if sys.version_info[0] >= 3:
+    if PY3:
         return str(foobar)
 
     try:
@@ -754,7 +754,7 @@ def compile_try_expression(self, expr):
 
         ret = handler_results
 
-        if sys.version_info[0] >= 3 and sys.version_info[1] >= 3:
+        if PY33:
             # Python 3.3 features a merge of TryExcept+TryFinally into Try.
             return ret + ast.Try(
                 lineno=expr.start_line,
@@ -831,7 +831,7 @@ def _compile_catch_expression(self, expr, var):
                     exceptions,
                     "Exception storage target name must be a symbol.")
 
-            if sys.version_info[0] >= 3:
+            if PY3:
                 # Python3 features a change where the Exception handler
                 # moved the name from a Name() to a pure Python String type.
                 #
@@ -1199,7 +1199,7 @@ def compile_with_expression(self, expr):
                             optional_vars=thing,
                             body=body.stmts)
 
-        if sys.version_info[0] >= 3 and sys.version_info[1] >= 3:
+        if PY33:
             the_with.items = [ast.withitem(context_expr=ctx.force_expr,
                                            optional_vars=thing)]
 
@@ -1699,12 +1699,32 @@ def compile_function_def(self, expression):
         arglist = expression.pop(0)
         ret, args, defaults, stararg, kwargs = self._parse_lambda_list(arglist)
 
+        if PY34:
+            # Python 3.4+ requres that args are an ast.arg object, rather
+            # than an ast.Name or bare string.
+            args = [ast.arg(arg=ast_str(x),
+                            annotation=None,  # Fix me!
+                            lineno=x.start_line,
+                            col_offset=x.start_column) for x in args]
+
+            # XXX: Beware. Beware. This wasn't put into the parse lambda
+            # list because it's really just an internal parsing thing.
+
+            if kwargs:
+                kwargs = ast.arg(arg=kwargs, annotation=None)
+
+            if stararg:
+                stararg = ast.arg(arg=stararg, annotation=None)
+
+            # Let's find a better home for these guys.
+        else:
+            args = [ast.Name(arg=ast_str(x), id=ast_str(x),
+                             ctx=ast.Param(),
+                             lineno=x.start_line,
+                             col_offset=x.start_column) for x in args]
+
         args = ast.arguments(
-            args=[ast.Name(arg=ast_str(x), id=ast_str(x),
-                           ctx=ast.Param(),
-                           lineno=x.start_line,
-                           col_offset=x.start_column)
-                  for x in args],
+            args=args,
             vararg=stararg,
             kwarg=kwargs,
             kwonlyargs=[],
diff --git a/hy/importer.py b/hy/importer.py
--- a/hy/importer.py
+++ b/hy/importer.py
@@ -19,7 +19,6 @@
 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 # DEALINGS IN THE SOFTWARE.
 
-from py_compile import wr_long, MAGIC
 from hy.compiler import hy_compile, HyTypeError
 from hy.models import HyObject
 from hy.lex import tokenize, LexException
@@ -32,7 +31,7 @@
 import os
 import __future__
 
-from hy._compat import builtins, long_type
+from hy._compat import PY3, PY33, MAGIC, builtins, long_type, wr_long
 
 
 def ast_compile(ast, filename, mode):
@@ -139,12 +138,12 @@ def write_hy_as_pyc(fname):
     open_ = builtins.open
 
     with open_(cfile, 'wb') as fc:
-        if sys.version_info[0] >= 3:
+        if PY3:
             fc.write(b'\0\0\0\0')
         else:
             fc.write('\0\0\0\0')
         wr_long(fc, timestamp)
-        if (sys.version_info[0] >= 3 and sys.version_info[1] >= 3):
+        if PY33:
             wr_long(fc, st.st_size)
         marshal.dump(code, fc)
         fc.flush()


Test patch: