]> granicus.if.org Git - python/commitdiff
SF bug #488514: -Qnew needs work
authorTim Peters <tim.peters@gmail.com>
Thu, 6 Dec 2001 06:23:26 +0000 (06:23 +0000)
committerTim Peters <tim.peters@gmail.com>
Thu, 6 Dec 2001 06:23:26 +0000 (06:23 +0000)
Big Hammer to implement -Qnew as PEP 238 says it should work (a global
option affecting all instances of "/").

pydebug.h, main.c, pythonrun.c:  define a private _Py_QnewFlag flag, true
iff -Qnew is passed on the command line.  This should go away (as the
comments say) when true division becomes The Rule.  This is
deliberately not exposed to runtime inspection or modification:  it's
a one-way one-shot switch to pretend you're using Python 3.

ceval.c:  when _Py_QnewFlag is set, treat BINARY_DIVIDE as
BINARY_TRUE_DIVIDE.

test_{descr, generators, zipfile}.py:  fiddle so these pass under
-Qnew too.  This was just a matter of s!/!//! in test_generators and
test_zipfile.  test_descr was trickier, as testbinop() is passed
assumptions that "/" is the same as calling a "__div__" method; put
a temporary hack there to call "__truediv__" instead when the method
name is "__div__" and 1/2 evaluates to 0.5.

Three standard tests still fail under -Qnew (on Windows; somebody
please try the Linux tests with -Qnew too!  Linux runs a whole bunch
of tests Windows doesn't):
    test_augassign
    test_class
    test_coercion
I can't stay awake longer to stare at this (be my guest).  Offhand
cures weren't obvious, nor was it even obvious that cures are possible
without major hackery.

Question:  when -Qnew is in effect, should calls to __div__ magically
change into calls to __truediv__?  See "major hackery" at tail end of
last paragraph <wink>.

Include/pydebug.h
Lib/test/test_descr.py
Lib/test/test_generators.py
Lib/zipfile.py
Misc/NEWS
Modules/main.c
Python/ceval.c
Python/pythonrun.c

index 9ecd8a00d23c4a36ac355d38db515e18c368947e..d92161cd64a496791df10481dd06a67167101f12 100644 (file)
@@ -16,6 +16,10 @@ extern DL_IMPORT(int) Py_TabcheckFlag;
 extern DL_IMPORT(int) Py_UnicodeFlag;
 extern DL_IMPORT(int) Py_IgnoreEnvironmentFlag;
 extern DL_IMPORT(int) Py_DivisionWarningFlag;
+/* _XXX Py_QnewFlag should go away in 2.3.  It's true iff -Qnew is passed,
+  on the command line, and is used in 2.2 by ceval.c to make all "/" divisions
+  true divisions (which they will be in 2.3). */
+extern DL_IMPORT(int) _Py_QnewFlag;
 
 /* this is a wrapper around getenv() that pays attention to
    Py_IgnoreEnvironmentFlag.  It should be used for getting variables like
index 481ca0f7dfb43c31c1c194c8c79cd1ea1d7dc5e8..a0958df94e07a4818f4e8dcbc8f1549e82d32c09 100644 (file)
@@ -23,6 +23,11 @@ def testunop(a, res, expr="len(a)", meth="__len__"):
 def testbinop(a, b, res, expr="a+b", meth="__add__"):
     if verbose: print "checking", expr
     dict = {'a': a, 'b': b}
+
+    # XXX Hack so this passes before 2.3 when -Qnew is specified.
+    if meth == "__div__" and 1/2 == 0.5:
+        meth = "__truediv__"
+
     vereq(eval(expr, dict), res)
     t = type(a)
     m = getattr(t, meth)
index 118b1d9fce1749da80f12a3faa1c21b863aca9da..2c319e5db982901f4dee8df50a4faa4942af12f1 100644 (file)
@@ -182,7 +182,7 @@ Specification: Return
 Specification: Generators and Exception Propagation
 
     >>> def f():
-    ...     return 1/0
+    ...     return 1//0
     >>> def g():
     ...     yield f()  # the zero division exception propagates
     ...     yield 42   # and we'll never get here
@@ -206,7 +206,7 @@ Specification: Try/Except/Finally
     ...         yield 1
     ...         try:
     ...             yield 2
-    ...             1/0
+    ...             1//0
     ...             yield 3  # never get here
     ...         except ZeroDivisionError:
     ...             yield 4
@@ -253,7 +253,7 @@ Guido's binary tree example.
     ...     n = len(list)
     ...     if n == 0:
     ...         return []
-    ...     i = n / 2
+    ...     i = n // 2
     ...     return Tree(list[i], tree(list[:i]), tree(list[i+1:]))
 
     >>> # Show it off: create a tree.
@@ -691,7 +691,7 @@ SyntaxError: 'yield' not allowed in a 'try' block with a 'finally' clause (<stri
 >>> def f():
 ...     try:
 ...         try:
-...             1/0
+...             1//0
 ...         except ZeroDivisionError:
 ...             yield 666  # bad because *outer* try has finally
 ...         except:
@@ -708,7 +708,7 @@ But this is fine:
 ...     try:
 ...         try:
 ...             yield 12
-...             1/0
+...             1//0
 ...         except ZeroDivisionError:
 ...             yield 666
 ...         except:
@@ -751,7 +751,7 @@ SyntaxError: invalid syntax
 ...             pass
 ...         elif 0:
 ...             try:
-...                 1/0
+...                 1//0
 ...             except SyntaxError:
 ...                 pass
 ...             else:
index 4b59ac6dea60c47f53589565ee11f09ba7599cb5..0efcad3a8a4f38fd90bbb5164b5e201df717d5c0 100644 (file)
@@ -117,7 +117,7 @@ class ZipInfo:
         """Return the per-file header as a string."""
         dt = self.date_time
         dosdate = (dt[0] - 1980) << 9 | dt[1] << 5 | dt[2]
-        dostime = dt[3] << 11 | dt[4] << 5 | dt[5] / 2
+        dostime = dt[3] << 11 | dt[4] << 5 | (dt[5] // 2)
         if self.flag_bits & 0x08:
             # Set these to zero because we write them after the file data
             CRC = compress_size = file_size = 0
@@ -468,7 +468,7 @@ class ZipFile:
                 count = count + 1
                 dt = zinfo.date_time
                 dosdate = (dt[0] - 1980) << 9 | dt[1] << 5 | dt[2]
-                dostime = dt[3] << 11 | dt[4] << 5 | dt[5] / 2
+                dostime = dt[3] << 11 | dt[4] << 5 | (dt[5] // 2)
                 centdir = struct.pack(structCentralDir,
                   stringCentralDir, zinfo.create_version,
                   zinfo.create_system, zinfo.extract_version, zinfo.reserved,
index eabe9b60f561586f9c6158eb9b2f633c21252587..db38eca9730c872557352bd605d64bfdf3cbe7b8 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -39,6 +39,13 @@ Type/class unification and new-style classes
 
 Core and builtins
 
+- -Qnew now works as documented in PEP 238:  when -Qnew is passed on
+  the command line, all occurrences of "/" use true division instead
+  of classic division.  See the PEP for details.  Note that "all"
+  means all instances in library and 3rd-party modules, as well as in
+  your own code.  As the PEP says, -Qnew is intended for use only in
+  educational environments with control over the libraries in use.
+
 Extension modules
 
 - gc.get_referents was renamed to gc.get_referrers.
@@ -712,11 +719,15 @@ Core
   warnings are issued.  Using -Qwarn issues a run-time warning about
   all uses of classic division for int and long arguments; -Qwarnall
   also warns about classic division for float and complex arguments
-  (for use with fixdiv.py).  Using -Qnew is questionable; it turns on
-  new division by default, but only in the __main__ module.  You can
-  usefully combine -Qwarn or -Qwarnall and -Qnew: this gives the
-  __main__ module new division, and warns about classic division
-  everywhere else.
+  (for use with fixdiv.py).
+  [Note:  the remainder of this paragraph (preserved below) became
+   obsolete in 2.2c1 -- -Qnew has global effect in 2.2]
+  <obsolete>
+  Using -Qnew is questionable; it turns on new division by default, but
+  only in the __main__ module.  You can usefully combine -Qwarn or
+  -Qwarnall and -Qnew: this gives the __main__ module new division, and
+  warns about classic division everywhere else.
+  </obsolete>
 
 - Many built-in types can now be subclassed.  This applies to int,
   long, float, str, unicode, and tuple.  (The types complex, list and
index eea848fff5220e2c36b80505bd4d949c00a33b51..5f71ee2c0aaddba11abc424d7bbaefd16f3c047a 100644 (file)
@@ -169,8 +169,11 @@ Py_Main(int argc, char **argv)
                                break;
                        }
                        if (strcmp(_PyOS_optarg, "new") == 0) {
-                               /* XXX This only affects __main__ */
+                               /* This only affects __main__ */
                                cf.cf_flags |= CO_FUTURE_DIVISION;
+                               /* And this tells the eval loop to treat
+                                  BINARY_DIVIDE as BINARY_TRUE_DIVIDE */
+                               _Py_QnewFlag = 1;
                                break;
                        }
                        fprintf(stderr,
index 535851775f48d892c9a8aaa8100278204c0b7283..76424e107c85a3e5719ab91159b76715b6267344 100644 (file)
@@ -903,9 +903,22 @@ eval_frame(PyFrameObject *f)
                        break;
 
                case BINARY_DIVIDE:
+                       if (!_Py_QnewFlag) {
+                               w = POP();
+                               v = POP();
+                               x = PyNumber_Divide(v, w);
+                               Py_DECREF(v);
+                               Py_DECREF(w);
+                               PUSH(x);
+                               if (x != NULL) continue;
+                               break;
+                       }
+                       /* -Qnew is in effect:  fall through to
+                          BINARY_TRUE_DIVIDE */
+               case BINARY_TRUE_DIVIDE:
                        w = POP();
                        v = POP();
-                       x = PyNumber_Divide(v, w);
+                       x = PyNumber_TrueDivide(v, w);
                        Py_DECREF(v);
                        Py_DECREF(w);
                        PUSH(x);
@@ -922,16 +935,6 @@ eval_frame(PyFrameObject *f)
                        if (x != NULL) continue;
                        break;
 
-               case BINARY_TRUE_DIVIDE:
-                       w = POP();
-                       v = POP();
-                       x = PyNumber_TrueDivide(v, w);
-                       Py_DECREF(v);
-                       Py_DECREF(w);
-                       PUSH(x);
-                       if (x != NULL) continue;
-                       break;
-
                case BINARY_MODULO:
                        w = POP();
                        v = POP();
index 628058b8b8828533167ea046a726c31788f08f2a..a8ad84503df20a846134321713832515b07c4c7b 100644 (file)
@@ -64,6 +64,10 @@ int Py_UseClassExceptionsFlag = 1; /* Needed by bltinmodule.c: deprecated */
 int Py_FrozenFlag; /* Needed by getpath.c */
 int Py_UnicodeFlag = 0; /* Needed by compile.c */
 int Py_IgnoreEnvironmentFlag; /* e.g. PYTHONPATH, PYTHONHOME */
+/* _XXX Py_QnewFlag should go away in 2.3.  It's true iff -Qnew is passed,
+  on the command line, and is used in 2.2 by ceval.c to make all "/" divisions
+  true divisions (which they will be in 2.3). */
+int _Py_QnewFlag = 0;
 
 static int initialized = 0;