Skip to content

Commit

Permalink
SF bug #488514: -Qnew needs work
Browse files Browse the repository at this point in the history
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>.
  • Loading branch information
tim-one committed Dec 6, 2001
1 parent e50959a commit 3caca23
Show file tree
Hide file tree
Showing 8 changed files with 55 additions and 25 deletions.
4 changes: 4 additions & 0 deletions Include/pydebug.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions Lib/test/test_descr.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
12 changes: 6 additions & 6 deletions Lib/test/test_generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@
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
Expand All @@ -206,7 +206,7 @@
... yield 1
... try:
... yield 2
... 1/0
... 1//0
... yield 3 # never get here
... except ZeroDivisionError:
... yield 4
Expand Down Expand Up @@ -253,7 +253,7 @@
... 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.
Expand Down Expand Up @@ -691,7 +691,7 @@
>>> def f():
... try:
... try:
... 1/0
... 1//0
... except ZeroDivisionError:
... yield 666 # bad because *outer* try has finally
... except:
Expand All @@ -708,7 +708,7 @@
... try:
... try:
... yield 12
... 1/0
... 1//0
... except ZeroDivisionError:
... yield 666
... except:
Expand Down Expand Up @@ -751,7 +751,7 @@
... pass
... elif 0:
... try:
... 1/0
... 1//0
... except SyntaxError:
... pass
... else:
Expand Down
4 changes: 2 additions & 2 deletions Lib/zipfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ def FileHeader(self):
"""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
Expand Down Expand Up @@ -468,7 +468,7 @@ def close(self):
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,
Expand Down
21 changes: 16 additions & 5 deletions Misc/NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down
5 changes: 4 additions & 1 deletion Modules/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
25 changes: 14 additions & 11 deletions Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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();
Expand Down
4 changes: 4 additions & 0 deletions Python/pythonrun.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down

0 comments on commit 3caca23

Please sign in to comment.