Discussion:
[PEAK] PEAK-Rules for Python3
Cara
2015-03-17 02:30:56 UTC
Permalink
I'm investigating trying to get PEAK-Rules running on Python 3. I
know that Hervé Coatanhay attempted this before, but their code is no
longer up at Bitbucket, so I'm starting from the code in the
repository as is. To make this less unmanageable and since breaking
some backwards compatibility is necessary, I'm planning to use the
futurize script from http://python-future.org/ to try to get the code
base into a state compatible with 2.6+ and 3.3+. If I get anywhere,
would you be interested in integrating patches, or would I have to
fork it? If I do fork it, is there a license file I need to include?
Would the commit logs be sufficient to fulfill the requirements?

Cara
Hervé Coatanhay
2015-03-17 11:23:45 UTC
Permalink
Hi Cara,

My attempt is stil available here https://bitbucket.org/Alzakath/peak-py3 <https://bitbucket.org/Alzakath/peak-py3>.

--
Hervé
Post by Cara
I'm investigating trying to get PEAK-Rules running on Python 3. I
know that Hervé Coatanhay attempted this before, but their code is no
longer up at Bitbucket, so I'm starting from the code in the
repository as is. To make this less unmanageable and since breaking
some backwards compatibility is necessary, I'm planning to use the
futurize script from http://python-future.org/ to try to get the code
base into a state compatible with 2.6+ and 3.3+. If I get anywhere,
would you be interested in integrating patches, or would I have to
fork it? If I do fork it, is there a license file I need to include?
Would the commit logs be sufficient to fulfill the requirements?
Cara
_______________________________________________
PEAK mailing list
http://www.eby-sarna.com/mailman/listinfo/peak
Cara
2015-03-17 14:18:13 UTC
Permalink
Oh, I see, the link in the list archives inappropriately included the
period at the end of the sentence. How far did you get? What license
is your code available under?

Cara
Hervé Coatanhay
2015-03-18 09:30:16 UTC
Permalink
I reached a point where multi dispatch worked. But sadly when PEAK-Rules needs to generate bytecode (predicate dispatch), things go awry.

As I see it, syntactic changes between python2 and python3 are small enough to have a code base working with both. But bytecode generation, needed to circumvent some python limitations, leads to another level of issues I do not completely understand.

As of licensing, it seems PEAK is licensed under PSF or ZPL.


Hervé
Post by Cara
Oh, I see, the link in the list archives inappropriately included the
period at the end of the sentence. How far did you get? What license
is your code available under?
Cara
_______________________________________________
PEAK mailing list
http://www.eby-sarna.com/mailman/listinfo/peak
PJ Eby
2015-03-23 04:44:20 UTC
Permalink
This post might be inappropriate. Click to display it.
Cara
2015-04-01 05:15:10 UTC
Permalink
This post might be inappropriate. Click to display it.
PJ Eby
2015-04-01 18:52:28 UTC
Permalink
Post by Cara
Before I touched the code base at all, I ran all the doctests in Python
Those results are incorrect; in fact there are only 3 shallow failures
for Python 2.7 across all the projects you listed. The correct way to
run the full tests is with "setup.py test". That will run both the
doctests and the unittests for each project, and with the correct
options for each file/project.

The only projects with failures on 2.7 are PEAK-Rules and
DecoratorTools, and in each case it's due to subtle repr differences
or internal refactorings in 2.7. Essentially, they work just fine on
2.7
Post by Cara
(The only functionality I could find
that was broken is that the class decorators don't seem to be working.)
Yes, and that's due to a fundamental limitation in Python 3, which
doesn't have any way to select a metaclass while within a class
definition suite, except by an even nastier global monkeypatching than
the way decoratortools works in general. This limitation is one of
the many reasons I probably won't be trying to port my projects to
Python 3. I previously raised the issue on Python-dev (see e.g.
https://mail.python.org/pipermail/python-dev/2012-April/118952.html ),
and there is a PEP (#422) that would address the issue, complete with
a patch ( http://bugs.python.org/issue17044 ), but which has been
languishing for a couple of years. A couple months ago, there was a
new proposal ( http://code.activestate.com/lists/python-ideas/32123/
), which could probably also be made to work for most uses, but of
course is also not implemented in any version of Python 3.
Post by Cara
1) Breaking backwards compatibility: Python has had, for instance,
class decorators since 2.6, which isn't even supported any more. I
don't have any interest in rewriting the frame-hacking for
DecoratorTools.decorator_class() to make it work on Python 3, so I'd
just refactor all the relevant code to use the built-in class
decorators.
This isn't actually possible, anyway: you would not be able to define
generic function methods in a class body unless you added an explicit
metaclass or class decorator to the class, and rewrote the API or
dropped the feature. (I guess I should say, it isn't possible while
retaining the features of class-level AddOns or of defining gf methods
in class bodies.)
Post by Cara
2) Implicit relative imports: most of the packages are filled with lines
like,
from peak.utils.decorators import ...
Huh? that's an explicit absolute import, not an implicit relative one.
Maybe you mean the "from core import *" stuff.
Post by Cara
In Python 3, these don't work and the automatic conversion tools don't
work on them. They're responsible for most of the failures I'm seeing
in the doctests. I could probably get everything running using
virtualenv and setuptools, but at that point I'm refactoring the entire
package structure. Breaking backwards compatibility by eliminating
dependencies would help but not solve the problem entirely.
This actually mostly sounds like a problem with the way you're running
the doctests.
Post by Cara
At this point I'm stopping for now, primarily because I've changed the
objective of the project I was planning on using PEAK-Rules for so it's
no longer useful. I didn't tackle any of the hard problems like
rewriting ByteCodeAssembler. My attempt is up at
https://github.com/ceridwen/PEAK-Rules If anyone
needs a Python 3-compatible version of Extremes or SymbolType, or a
mostly-compatible version of DecoratorTools, there they are.
If I were to drop compatibility with Python <2.6, BytecodeAssembler
and the most of the other ast stuff could be mostly replaced with the
Python 2.6+ "ast" module and the compile() builtin. Such a thing
would be vastly easier to make work with 3.x, I imagine. In practice,
I don't have time or interest at the moment sufficient to do it
myself. Such a thing might be better off as a fork, anyway.
Cara
2015-04-03 19:32:53 UTC
Permalink
Despite what I said last time, I did a little bit more on this.
Post by PJ Eby
Those results are incorrect; in fact there are only 3 shallow failures
for Python 2.7 across all the projects you listed. The correct way to
run the full tests is with "setup.py test". That will run both the
doctests and the unittests for each project, and with the correct
options for each file/project.
Mea culpa. I know next to nothing about setuptools and didn't
know that. I was hoping to look at how broken the functionality is in
Python 3 without having to deal with the packaging, but since apparently
the only way to run the tests correctly is to fix the packaging, I had
to do that first. This was rather involved even not counting all the
dead ends I went down. After setting up a virtualenv with Python 2 and
the packages from PyPi, I had to figure out that setuptools no longer
distributes ez_setup and that I needed the old version in the
repository, get it, and symlink in each of the individual package
directories. After that, I reran the conversion scripts, reapplied my
previous edits, and installed into a virtualenv successfully.
Post by PJ Eby
The only projects with failures on 2.7 are PEAK-Rules and
DecoratorTools, and in each case it's due to subtle repr differences
or internal refactorings in 2.7. Essentially, they work just fine on
2.7
This is also what I found. Note that trying to run the tests on 2.7
will fail because of the missing ez_setup.
Post by PJ Eby
Yes, and that's due to a fundamental limitation in Python 3, which
doesn't have any way to select a metaclass while within a class
definition suite, except by an even nastier global monkeypatching than
the way decoratortools works in general. This limitation is one of
the many reasons I probably won't be trying to port my projects to
Python 3. I previously raised the issue on Python-dev (see e.g.
https://mail.python.org/pipermail/python-dev/2012-April/118952.html ),
and there is a PEP (#422) that would address the issue, complete with
a patch ( http://bugs.python.org/issue17044 ), but which has been
languishing for a couple of years. A couple months ago, there was a
new proposal ( http://code.activestate.com/lists/python-ideas/32123/
), which could probably also be made to work for most uses, but of
course is also not implemented in any version of Python 3.
I'm aware of the problem and the PEPs that try to solve it, but I didn't
know it was the issue here. I'd like to see the functionality added,
but CPython development is CPython development. I can throw in a word
on python-dev if you want, for all that would do.
Post by PJ Eby
Post by Cara
1) Breaking backwards compatibility: Python has had, for instance,
class decorators since 2.6, which isn't even supported any more. I
don't have any interest in rewriting the frame-hacking for
DecoratorTools.decorator_class() to make it work on Python 3, so I'd
just refactor all the relevant code to use the built-in class
decorators.
This isn't actually possible, anyway: you would not be able to define
generic function methods in a class body unless you added an explicit
metaclass or class decorator to the class, and rewrote the API or
dropped the feature. (I guess I should say, it isn't possible while
retaining the features of class-level AddOns or of defining gf methods
in class bodies.)
I'm not sure I understand why this is.
Post by PJ Eby
If I were to drop compatibility with Python <2.6, BytecodeAssembler
and the most of the other ast stuff could be mostly replaced with the
Python 2.6+ "ast" module and the compile() builtin. Such a thing
would be vastly easier to make work with 3.x, I imagine. In practice,
I don't have time or interest at the moment sufficient to do it
myself. Such a thing might be better off as a fork, anyway.
I've gotten the Python 3 port to the point where everything installs and
most of the tests work. Extremes, SymbolType, and Importing pass all
their tests in both 2 and 3. There's an AmbiguousMethods error in
PEAK-Rules,

("peak.rules.core.AmbiguousMethods: ([Method(<built-in function
issubclass>, (<type 'type'>, <type 'type'>), 2, None), Method(<built-in
function issubclass>, (<type 'type'>, <type 'type'>), 3, None)], (<class
'peak.rules.core.TypeEngine'>, <class 'peak.rules.core.TypeEngine'>),
{})"

which I think comes from this section of code that I don't
understand in core.py:

ClassType = type
when(implies, (type, (ClassType, type) ))(issubclass)
when(implies, (ClassType, ClassType ))(issubclass)
when(implies, (istype, istype ))(lambda s1,s2:
s1==s2 or (s1.type is not s2.type and s1.match and not s2.match))
when(implies, (istype, type) )(lambda s1,s2: s1.match and
implies(s1.type,s2))

I added the ClassType = type assignment to bypass shallow NameErrors.

There's a collection of errors in Python 3 for the AddOns and
DecoratorTools tests that I suspect relate to the class creation and
decorators issued you mentioned: the tests involving Demo in the doc
tests and TypeErrors in testMixedMetas, testSingleExplicitMeta, and
testOrder, plus some shallow errors. From what you said, the changes to
metaclass handling make any kind of a direct port impossible because the
functionality isn't there on Python 3?

There's one error in testAlreadyTracing that appears on both Python 2
and 3:

Traceback (most recent call last):
File "/home/cara/code/peak-rules/DecoratorTools/test_decorators.py",
line 116, in testAlreadyTracing
'decorate_assignment', 'enclosing_frame', '<lambda>',
'failUnlessEqual',
AssertionError: Lists differ: ['tes[66 chars]>', 'assertEqual',
'_getAssertEqualityFunc', '[363 chars]ual'] != ['tes[66 chars]>',
'failUnlessEqual', 'decorate_assignment', [171 chars]ual']

First differing element 4:
assertEqual
failUnlessEqual

First list contains 9 additional elements.
First extra element 16:
...

And then there's a large collection of errors in BytecodeAssembler on
Python 2 I haven't assessed, plus it segfaults (no surprise there) on
Python 3. I posted the log for Python 3 here:
http://pastebin.com/UhCfyHJf . The log for Python 2 is too large to put
up anywhere.

Cara
PJ Eby
2015-04-03 21:58:13 UTC
Permalink
Post by Cara
Despite what I said last time, I did a little bit more on this.
Thanks!
Post by Cara
This is also what I found. Note that trying to run the tests on 2.7
will fail because of the missing ez_setup.
Not sure what you mean about missing ez_setup, but I'll look into it.
I don't use the newer versions of setuptools myself yet, so I haven't
run into that problem yet. ;-)
Post by Cara
I'm aware of the problem and the PEPs that try to solve it, but I didn't
know it was the issue here. I'd like to see the functionality added,
but CPython development is CPython development. I can throw in a word
on python-dev if you want, for all that would do.
At this point, it's not necessary. I had the discussion myself, and
the resolution seems to be that there might be a new protocol added
later, but for now, just go ahead and hook __build_class__ to get the
old capabilities back, then change it to something standardized later.
PyPy in any event has __build_class__ in its Python 3, so it won't be
a problem there, either.
Post by Cara
Post by PJ Eby
This isn't actually possible, anyway: you would not be able to define
generic function methods in a class body unless you added an explicit
metaclass or class decorator to the class, and rewrote the API or
dropped the feature. (I guess I should say, it isn't possible while
retaining the features of class-level AddOns or of defining gf methods
in class bodies.)
I'm not sure I understand why this is.
PEAK-Rules' decorators for methods defined in classes add in the
current class as a restriction on applicability of the method; to do
this, they need the class object, but that object can only be obtained
*after* the class is defined. They do this by *invisbly* decorating
the class, so they can be notified when the class is created. This is
why the whole PEP business was needed: the mechanism used for this
invisible class decoration in Python 2, went away in Python 3.
Post by Cara
I've gotten the Python 3 port to the point where everything installs and
most of the tests work. Extremes, SymbolType, and Importing pass all
their tests in both 2 and 3. There's an AmbiguousMethods error in
PEAK-Rules,
("peak.rules.core.AmbiguousMethods: ([Method(<built-in function
issubclass>, (<type 'type'>, <type 'type'>), 2, None), Method(<built-in
function issubclass>, (<type 'type'>, <type 'type'>), 3, None)], (<class
'peak.rules.core.TypeEngine'>, <class 'peak.rules.core.TypeEngine'>),
{})"
which I think comes from this section of code that I don't
ClassType = type
when(implies, (type, (ClassType, type) ))(issubclass)
when(implies, (ClassType, ClassType ))(issubclass)
s1==s2 or (s1.type is not s2.type and s1.match and not s2.match))
when(implies, (istype, type) )(lambda s1,s2: s1.match and
implies(s1.type,s2))
I added the ClassType = type assignment to bypass shallow NameErrors.
In the event that `ClassType is type`, only one of the
when(...)(issubclass) lines is needed, and the other is redundant.
i.e. a simple:

when(implies, (type, type))(issubclass)

is all that's necessary.

Basically, this code says, "when you want to know if 'a' implies 'b',
and both 'a' and 'b' are instances of 'type', call `issubclass(a, b)`
to find out." In Python 2, classic classes are ClassType instances,
not `type` instances. And you can have new-style classes that
subclass a ClassType. That's why two declarations are needed: the
first says, "if you have a new-style class, and want to check if it
inherits from either a classic or new-style class, use issubclass."
The second says, "If you have a classic class, and you want to check
if it inherits from a classic class, you can also use issubclass."
(But a classic class can never be a subclass of a new-style class, so
that's not listed anywhere.)

The `implies()` function in the core is used to tell whether some
criterion implies another criterion. In the core, the main criteria
are class objects and `istype` objects (hard type checks). But the
full predicate system has many more kinds of things, including
expressions and range checks and whatnot, so it adds more rules to the
`implies()` generic function later to cover those other kinds of
objects as they are introduced.

Yes, PEAK-Rules is written using its own generic functions. ;-)
Post by Cara
There's a collection of errors in Python 3 for the AddOns and
DecoratorTools tests that I suspect relate to the class creation and
decorators issued you mentioned: the tests involving Demo in the doc
tests and TypeErrors in testMixedMetas, testSingleExplicitMeta, and
testOrder, plus some shallow errors. From what you said, the changes to
metaclass handling make any kind of a direct port impossible because the
functionality isn't there on Python 3?
Yeah, DecoratorTools needs some significant work to port to Python 3,
in order for the class-decorating and metaclass-related features to
work, and PEAK-Rules actually does use some of them, directly or via
AddOns. I'm not sure how many of the test failures actually represent
sticking points for PEAK-Rules, though.
Post by Cara
There's one error in testAlreadyTracing that appears on both Python 2
File "/home/cara/code/peak-rules/DecoratorTools/test_decorators.py",
line 116, in testAlreadyTracing
'decorate_assignment', 'enclosing_frame', '<lambda>',
'failUnlessEqual',
AssertionError: Lists differ: ['tes[66 chars]>', 'assertEqual',
'_getAssertEqualityFunc', '[363 chars]ual'] != ['tes[66 chars]>',
'failUnlessEqual', 'decorate_assignment', [171 chars]ual']
Yeah, as of 2.7 it looks like part of unittest was refactored, and
that test was based on the call stack in pre-2.7. I've already seen
it in 2.7 and consider it a shallow failure; if it fails the same way
on 3.x then it's probably nothing to worry about.
Post by Cara
And then there's a large collection of errors in BytecodeAssembler on
Python 2 I haven't assessed,
Huh? I just ran "python27 setup.py test" on a fresh checkout of
BytecodeAssembler and it comes back clean.
Post by Cara
plus it segfaults (no surprise there) on
Python 3.
You'll probably need to comment out some tests to find out where it breaks.
Post by Cara
http://pastebin.com/UhCfyHJf .
Interesting. So, looks like SymbolTypes and Extremes are good, and
most of DecoratorTools' failures are expected or shallow, and that
many of AddOns' failures are just the direct effect of DecoratorTools'
expected failures. The unsortable types thing is a shallow failure of
sorts (no pun intended): dir() doesn't work right with non-string keys
and the test needs to do the verification it's doing in some other
way.

I'm actually very encouraged by this, though, since all the
DecoratorTools failures except the unittest call stack thing are due
to the metaclass issue. So if I write a workaround for that,
DecoratorTools should work, and then AddOns ought to work, and maybe
PEAK-Rules will work, right up to the point where it needs
BytecodeAssembler, anyway. ;-)

So... I've checked in some changes to DecoratorTools, and I have here
a proposed patch to make the class stuff work on Python 3. Add the
following to the end of decorators.py, and let me know if it works:

try:
old_build_class = __build_class__
except NameError:
pass
else:
def apply_decorators(cls, advice):
if metaclass_is_decorator(advice):
cls = advice.callback(
apply_decorators(cls, advice.previousMetaclass)
)
return cls

def py3_build_class(func, name, *bases, **kw):
cls = old_build_class(func, name, *bases, **kw)
advice = cls.__dict__.get('__metaclass__', None)
cls = apply_decorators(cls, advice)
if '__metaclass__' in cls.__dict__
try:
del cls.__metaclass__
except TypeError:
pass
return cls

__builtins__.__build_class__ = py3_build_class


This is basically a monkeypatch to post-process class decorators on
Python 3, by detecting DecoratorTools' metaclass-decorator protocol
and only applying the decoration part, not the metaclass part. I
would be very interested in seeing what test failures are left after
you add this, and the code I just checked in to fix the
unittest-related failure. If this patch above works, then we should
also see a lot fewer failures for AddOns as well.
PJ Eby
2015-04-04 00:56:47 UTC
Permalink
Post by PJ Eby
This is basically a monkeypatch to post-process class decorators on
Python 3, by detecting DecoratorTools' metaclass-decorator protocol
and only applying the decoration part, not the metaclass part. I
would be very interested in seeing what test failures are left after
you add this, and the code I just checked in to fix the
unittest-related failure. If this patch above works, then we should
also see a lot fewer failures for AddOns as well.
Update: the SVN versions of DecoratorTools and AddOns now run with
clean tests on Python 3.1 and 3.2; I haven't tried anything more
recent yet.

I'm playing around with BytecodeAssembler, and have gotten it down to
only a couple hundred lines of error output on the tests; no crashes
yet on 3.1 or 3.2. FYI, the way I changed the call signature for
creating code objects was to add a zero as the *second* argument to
code(); if you added the extra argument someplace else it might be
what's causing your core dump.

The remaining failures are either shallow (the representation of error
type names in doctest) or expected (tuple-unpacking arguments not
supported in Python 3, or the disappearance of the DUP_TOPX opcode).

Anyway, I've also checked in the BytecodeAssembler work I've done so
far -- it *should* work well enough for PEAK-Rules, but only testing
will tell.
Cara
2015-04-04 05:29:43 UTC
Permalink
Post by PJ Eby
PEAK-Rules' decorators for methods defined in classes add in the
current class as a restriction on applicability of the method; to do
this, they need the class object, but that object can only be obtained
*after* the class is defined. They do this by *invisbly* decorating
the class, so they can be notified when the class is created. This is
why the whole PEP business was needed: the mechanism used for this
invisible class decoration in Python 2, went away in Python 3.
I see what's going on now. Thanks.
Post by PJ Eby
Yeah, DecoratorTools needs some significant work to port to Python 3,
in order for the class-decorating and metaclass-related features to
work, and PEAK-Rules actually does use some of them, directly or via
AddOns. I'm not sure how many of the test failures actually represent
sticking points for PEAK-Rules, though.
<patch snipped>
This is basically a monkeypatch to post-process class decorators on
Python 3, by detecting DecoratorTools' metaclass-decorator protocol
and only applying the decoration part, not the metaclass part. I
would be very interested in seeing what test failures are left after
you add this, and the code I just checked in to fix the
unittest-related failure. If this patch above works, then we should
also see a lot fewer failures for AddOns as well.
I applied a slightly-modified version of this patch (based on the one
you'd checked into the repository) to decorators.py. AddOns now passes
on 2.7 and has only shallow failures on 3.4 (unorderable types in dir()
and <function Demo2.dummy ...> instead of <function dummy ...>).
DecoratorTools passes on 2 (except for the error caused by unittest
changing) and has only two substantive failures on 3.

ERROR: testMixedMetas (test_decorators.ClassDecoratorTests)
----------------------------------------------------------------------
Traceback (most recent call last):
File "~/code/peak-rules/DecoratorTools/test_decorators.py", line 236,
in testMixedMetas
class C(B1,B2, with_metaclass(M3)):
File "~/code/peak-rules/DecoratorTools/peak/util/decorators.py", line
762, in py3_build_class
cls = old_build_class(func, name, *bases, **kw)
TypeError: metaclass conflict: the metaclass of a derived class must be
a (non-strict) subclass of the metaclasses of all its bases

This could easily be some interaction of future.with_metaclass, or
something else could be going on.

ERROR: testSingleExplicitMeta (test_decorators.ClassDecoratorTests)
----------------------------------------------------------------------
Traceback (most recent call last):
File "~/code/peak-rules/DecoratorTools/test_decorators.py", line 211,
in testSingleExplicitMeta
class C(M, with_metaclass(M)):
File "~/code/peak-rules/DecoratorTools/peak/util/decorators.py", line
765, in py3_build_class
if '__metaclass__' in cls.__dict__:
AttributeError: 'list' object has no attribute '__dict__'

This also occurs in testOrder. Repeated calls to decorators seem to be
nesting a list around each call. I'm not sure why, though I'm assuming
it's related to pong() geting called multiple times.
Post by PJ Eby
Post by Cara
And then there's a large collection of errors in BytecodeAssembler
on
Post by Cara
Python 2 I haven't assessed,
Huh? I just ran "python27 setup.py test" on a fresh checkout of
BytecodeAssembler and it comes back clean.
I went back and checked. It turns out that when I run the doctests
(with the usual option flags) directly on Python 2.7, after fixing a
couple of shallow problems, there are no errors. When I spot-checked a
few examples in the interpreter, they also ran fine. When I run the
doctests with `setup.py test`, I get a cascade of errors. I don't know
why there's a difference. Could it be setuptools? I'm using setuptools
7.0 freshly installed from PyPi.
Post by PJ Eby
I'm playing around with BytecodeAssembler, and have gotten it down to
only a couple hundred lines of error output on the tests; no crashes
yet on 3.1 or 3.2. FYI, the way I changed the call signature for
creating code objects was to add a zero as the *second* argument to
code(); if you added the extra argument someplace else it might be
what's causing your core dump.
I'd changed the second argument to 0, yes. The segfaults could easily
be that I'm running on 3.4 and you're trying 3.1 and 3.2. As far as I
know, there were no bytecode changes between 3.2 and 3.4, but there were
changes made to the interpreter. FWIW, 2/3 compatible code-bases often
only aim to support 3.3+ because in 3.3 the u'' notation for explicit
Unicode strings was brought back. I changed the ord() call on Python 3
in assembler.py to a no-op because indexing a bytestring returns an
Post by PJ Eby
Post by Cara
f = eval(c.code()) # doctest:+SKIP
f
<function f at ...>
Post by PJ Eby
Post by Cara
c.return_( # doctest:+SKIP
... Function(Return(Function(Return(Local('a')))),
... 'f', ['a', 'b'], 'c', 'd', [99, 66])
... )
Post by PJ Eby
Post by Cara
dis(c.code())
0 0 LOAD_CONST 1 (99)
3 LOAD_CONST 2 (66)
6 LOAD_CONST 3 (<... f ..., file
"<string>", line -1>)
9 MAKE_FUNCTION 2
12 RETURN_VALUE

After skipping those doctests, running the doctests directly on Python 3
now produces the following log: http://pastebin.com/aR9P1JZb . All of
the errors there (not counting the segfaults) look shallow to me, along
the lines of what you're seeing. Running the doctests on Python 3 using
`setup.py tests` also works now, and I still have no idea why.

With the dependencies surprisingly close to working, I'm now seeing a
lot more errors in PEAK-Rules. I simplified the implications rules for
class types as you discussed. (I started programming in Python long
after old-style classes were deprecated, so the logic wasn't transparent
to me.) To get rid of another bug, I commented out l.965 in core.py:

when(rules_for, type(After.sorted))(lambda f: rules_for(f.__func__))

My interpretation of this line is that it was stripping the function out
of unbound methods, but it's entirely possible I'm wrong. It did give
me a more useful log, but unfortunately, it's still huge because there
are still quite a few tests throwing infinite-recursion errors, so I
can't post it. The principal cycle seems to be between these three
lines in core.py:

l.62: def implies(s1,s2):
l.596: if implies(key, sig):
l.736: if not implies(t1,t2):

The first test where that comes up is testKwArgHandling. Calling cls =
old_build_class(func, name, *bases, **kw) in decorators.py is raising
"TypeError: nonempty __slots__ not supported for subtype of 'int'" in
many places. There's also a syntax error on l.140 of imports.py: "raise
exc[0],exc[1],exc[2]".

Cara
PJ Eby
2015-04-04 06:32:34 UTC
Permalink
At this point, it might be a good idea to use the svn versions of all
the dependencies, as I've done extensive work to get them working
properly. BytecodeAssembler is currently working except for various
expected failures up to Python 3.2, and I've also fixed the tests such
that a lot of the spurious errors your log shows are gone. I've also
updated the svn version of PEAK-Rules for a lot of files, and in my
working copy I have it working except for predicate dispatching on 3.1
and 3.2. There's still a lot to clean up and check in, aside from the
fact that lots of stuff is broken on 3.x.

I do get segfaults in PEAK-Rules' tests, though not in
BytecodeAssembler's, so that's probably a 3.3 or 3.4 thing. I'm worn
out for this evening, so I'll take a look at it again tomorrow. Many
of the problems you're having with PEAK-Rules I have already fixed in
my working copy, but not checked in yet.
Post by Cara
Post by PJ Eby
PEAK-Rules' decorators for methods defined in classes add in the
current class as a restriction on applicability of the method; to do
this, they need the class object, but that object can only be obtained
*after* the class is defined. They do this by *invisbly* decorating
the class, so they can be notified when the class is created. This is
why the whole PEP business was needed: the mechanism used for this
invisible class decoration in Python 2, went away in Python 3.
I see what's going on now. Thanks.
Post by PJ Eby
Yeah, DecoratorTools needs some significant work to port to Python 3,
in order for the class-decorating and metaclass-related features to
work, and PEAK-Rules actually does use some of them, directly or via
AddOns. I'm not sure how many of the test failures actually represent
sticking points for PEAK-Rules, though.
<patch snipped>
This is basically a monkeypatch to post-process class decorators on
Python 3, by detecting DecoratorTools' metaclass-decorator protocol
and only applying the decoration part, not the metaclass part. I
would be very interested in seeing what test failures are left after
you add this, and the code I just checked in to fix the
unittest-related failure. If this patch above works, then we should
also see a lot fewer failures for AddOns as well.
I applied a slightly-modified version of this patch (based on the one
you'd checked into the repository) to decorators.py. AddOns now passes
on 2.7 and has only shallow failures on 3.4 (unorderable types in dir()
and <function Demo2.dummy ...> instead of <function dummy ...>).
DecoratorTools passes on 2 (except for the error caused by unittest
changing) and has only two substantive failures on 3.
ERROR: testMixedMetas (test_decorators.ClassDecoratorTests)
----------------------------------------------------------------------
File "~/code/peak-rules/DecoratorTools/test_decorators.py", line 236,
in testMixedMetas
File "~/code/peak-rules/DecoratorTools/peak/util/decorators.py", line
762, in py3_build_class
cls = old_build_class(func, name, *bases, **kw)
TypeError: metaclass conflict: the metaclass of a derived class must be
a (non-strict) subclass of the metaclasses of all its bases
This could easily be some interaction of future.with_metaclass, or
something else could be going on.
ERROR: testSingleExplicitMeta (test_decorators.ClassDecoratorTests)
----------------------------------------------------------------------
File "~/code/peak-rules/DecoratorTools/test_decorators.py", line 211,
in testSingleExplicitMeta
File "~/code/peak-rules/DecoratorTools/peak/util/decorators.py", line
765, in py3_build_class
AttributeError: 'list' object has no attribute '__dict__'
This also occurs in testOrder. Repeated calls to decorators seem to be
nesting a list around each call. I'm not sure why, though I'm assuming
it's related to pong() geting called multiple times.
Post by PJ Eby
Post by Cara
And then there's a large collection of errors in BytecodeAssembler
on
Post by Cara
Python 2 I haven't assessed,
Huh? I just ran "python27 setup.py test" on a fresh checkout of
BytecodeAssembler and it comes back clean.
I went back and checked. It turns out that when I run the doctests
(with the usual option flags) directly on Python 2.7, after fixing a
couple of shallow problems, there are no errors. When I spot-checked a
few examples in the interpreter, they also ran fine. When I run the
doctests with `setup.py test`, I get a cascade of errors. I don't know
why there's a difference. Could it be setuptools? I'm using setuptools
7.0 freshly installed from PyPi.
Post by PJ Eby
I'm playing around with BytecodeAssembler, and have gotten it down to
only a couple hundred lines of error output on the tests; no crashes
yet on 3.1 or 3.2. FYI, the way I changed the call signature for
creating code objects was to add a zero as the *second* argument to
code(); if you added the extra argument someplace else it might be
what's causing your core dump.
I'd changed the second argument to 0, yes. The segfaults could easily
be that I'm running on 3.4 and you're trying 3.1 and 3.2. As far as I
know, there were no bytecode changes between 3.2 and 3.4, but there were
changes made to the interpreter. FWIW, 2/3 compatible code-bases often
only aim to support 3.3+ because in 3.3 the u'' notation for explicit
Unicode strings was brought back. I changed the ord() call on Python 3
in assembler.py to a no-op because indexing a bytestring returns an
Post by PJ Eby
Post by Cara
f = eval(c.code()) # doctest:+SKIP
f
<function f at ...>
Post by PJ Eby
Post by Cara
c.return_( # doctest:+SKIP
... Function(Return(Function(Return(Local('a')))),
... 'f', ['a', 'b'], 'c', 'd', [99, 66])
... )
Post by PJ Eby
Post by Cara
dis(c.code())
0 0 LOAD_CONST 1 (99)
3 LOAD_CONST 2 (66)
6 LOAD_CONST 3 (<... f ..., file
"<string>", line -1>)
9 MAKE_FUNCTION 2
12 RETURN_VALUE
After skipping those doctests, running the doctests directly on Python 3
now produces the following log: http://pastebin.com/aR9P1JZb . All of
the errors there (not counting the segfaults) look shallow to me, along
the lines of what you're seeing. Running the doctests on Python 3 using
`setup.py tests` also works now, and I still have no idea why.
With the dependencies surprisingly close to working, I'm now seeing a
lot more errors in PEAK-Rules. I simplified the implications rules for
class types as you discussed. (I started programming in Python long
after old-style classes were deprecated, so the logic wasn't transparent
when(rules_for, type(After.sorted))(lambda f: rules_for(f.__func__))
My interpretation of this line is that it was stripping the function out
of unbound methods, but it's entirely possible I'm wrong. It did give
me a more useful log, but unfortunately, it's still huge because there
are still quite a few tests throwing infinite-recursion errors, so I
can't post it. The principal cycle seems to be between these three
The first test where that comes up is testKwArgHandling. Calling cls =
old_build_class(func, name, *bases, **kw) in decorators.py is raising
"TypeError: nonempty __slots__ not supported for subtype of 'int'" in
many places. There's also a syntax error on l.140 of imports.py: "raise
exc[0],exc[1],exc[2]".
Cara
PJ Eby
2015-04-05 00:30:56 UTC
Permalink
Okay, I'm done: the version of PEAK-Rules that's in SVN now runs its
tests with fewer than 1000 lines of error output on Python 3.1-3.4,
with no segfaults. BytecodeAssembler's tests still segfault under
3.3+, though I know what the problem is and how to fix it; I've just
been focused on getting PEAK-Rules to work on 3.x at all.

The segfault I fixed was due to a change in Python 3 in how exception
blocks are processed: there's now a POP_EXCEPT that has to be added to
exception handlers, and there was a change in stack levels. The
unfixed problem is that in 3.3+, MAKE_FUNCTION and MAKE_CLOSURE now
take an extra value on the stack, containing the function's "qualified
name".

PEAK-Rules' 40 non-doctest tests all pass on 3.1 and 3.2, with one
failure on 3.3 and 3.4. Of the 8 doctest files, 1 is running clean
(AST-Builder), and the rest have varying amounts of failures -- mostly
shallow, being caused by repr() changes, loss of features relative to
Python 2, or etc. (A small number of them may represent actual
problems, however.)

If you'd like to try any of this, be aware that you need to have a
current *svn checkout* of ALL the packages used: AddOns,
BytecodeAssembler, DecoratorTools, Extremes, Importing, PEAK-Rules,
and SymbolType. You'll then need to use `setup.py develop` to install
them locally, in the correct order. Some of this won't work right if
you're using a setuptools version that's not compatible with your
local svn checkout format... or one of the newfangled setuptools
versions that don't support Subversion at all, or get cranky about the
new PEP-mandated version numbering schemes. So, consider all this
highly experimental at the moment, for only the most motivated
persons. ;-)
Cara
2015-04-09 13:50:25 UTC
Permalink
I haven't had much chance to look at this this week, but I checked out
and installed the current versions in SVN. Except for the same
segfaults in BytecodeAssembler's tests, most of the major bugs I saw are
gone. There are some real bugs still in PEAK-Rules, some of which are
shallow but may be concealing more serious bugs (the peak.rules.debug
import in test_rules.py is broken), some of which are shallow and easily
fixable (__repr__ differences), and some of which look like real bugs.
I could post the log if it would be helpful, but I assume you're seeing
the same thing.

Cara
PJ Eby
2015-04-09 16:15:21 UTC
Permalink
Yes. Slicing is broken, as is syntax pattern matching. I'm not
seeing any breakage on peak.rules.debug's import, though. As of this
morning, Python 3.1 has 735 lines of failure output from `setup.py
test`, in about 30-something individual doctest failures, almost half
of which are pure repr issues, where the values shown as not matching
are actually equal. Most of the remaining ones are either
SyntaxErrors caused by unsupported-on-3.x syntax, slicing problems, or
cascading errors from the two preceding things. I only see two errors
that look like they need further investigation: the MRO problem in
README.txt, and the 'NoneType is not callable' in Predicates.txt.

I'm thinking that I need to change the pattern-matching syntax to
something like `[[var]]` instead of backquotes, though for backwards
compatibility I'll still support backquotes. But then the tests and
things can use [[]] syntax to work across 2.x and 3.x.

(Btw, I just checked in some more test cleanup stuff, to clear away
several more false positive test failures on 3.x)
Post by Cara
I haven't had much chance to look at this this week, but I checked out
and installed the current versions in SVN. Except for the same
segfaults in BytecodeAssembler's tests, most of the major bugs I saw are
gone. There are some real bugs still in PEAK-Rules, some of which are
shallow but may be concealing more serious bugs (the peak.rules.debug
import in test_rules.py is broken), some of which are shallow and easily
fixable (__repr__ differences), and some of which look like real bugs.
I could post the log if it would be helpful, but I assume you're seeing
the same thing.
Cara
PJ Eby
2015-04-09 17:55:23 UTC
Permalink
Update: I've reviewed all remaining PEAK-Rules failures on 3.1, 3.2
and 3.4, and what's left at this point is just a missing feature:
method argument binding is broken, due to dependence on named tuple
args. Everything else is shallow or cascading errors, now that I've
updated BytecodeAssembler to emulate the SLICE_X opcodes from Python
2.x. (Note that 3.3+ changes dictionary and function reprs and
certain dissasembly bits, which adds a couple hundred lines more
failure output compared to 3.1/3.2, but AFAICT these are all shallow.)

Also, I've changed syntax binding variables to the form ~~x instead of
`x` -- the latter syntax still works on 2.x, but of course is not
available on 3.x.

If you find anything in PEAK-Rules that's not working on 3.x that
*doesn't* depend on tuple argument syntax, let me know.
Post by PJ Eby
Yes. Slicing is broken, as is syntax pattern matching. I'm not
seeing any breakage on peak.rules.debug's import, though. As of this
morning, Python 3.1 has 735 lines of failure output from `setup.py
test`, in about 30-something individual doctest failures, almost half
of which are pure repr issues, where the values shown as not matching
are actually equal. Most of the remaining ones are either
SyntaxErrors caused by unsupported-on-3.x syntax, slicing problems, or
cascading errors from the two preceding things. I only see two errors
that look like they need further investigation: the MRO problem in
README.txt, and the 'NoneType is not callable' in Predicates.txt.
I'm thinking that I need to change the pattern-matching syntax to
something like `[[var]]` instead of backquotes, though for backwards
compatibility I'll still support backquotes. But then the tests and
things can use [[]] syntax to work across 2.x and 3.x.
(Btw, I just checked in some more test cleanup stuff, to clear away
several more false positive test failures on 3.x)
Post by Cara
I haven't had much chance to look at this this week, but I checked out
and installed the current versions in SVN. Except for the same
segfaults in BytecodeAssembler's tests, most of the major bugs I saw are
gone. There are some real bugs still in PEAK-Rules, some of which are
shallow but may be concealing more serious bugs (the peak.rules.debug
import in test_rules.py is broken), some of which are shallow and easily
fixable (__repr__ differences), and some of which look like real bugs.
I could post the log if it would be helpful, but I assume you're seeing
the same thing.
Cara
PJ Eby
2015-04-09 21:43:47 UTC
Permalink
A further update: all shallow and cascading failures in 3.x are fixed,
and the remaining broken feature has been fixed with another syntax
workaround. At this point, PEAK-Rules should have clean test runs on
both Python 2.x and 3.x ,when it and its dependencies are the latest
from SVN. (Note that I made some BytecodeAssembler changes today, and
you need those, too!)

Please let me know if you're seeing any test failures or experiencing
any breakage in 3.x code using PEAK-Rules.

If you want to move your code that uses PEAK-Rules to 3.x, and you are
using the syntax-matching rules feature or the let-binding arguments
feature, you'll need to tweak your code to use the new 2.x/3.x
cross-compatible syntax for these features.

Syntax rules with backquoted names (e.g. "type(`x`) is `y`") are now
replaced with double-tilded names ("type(~~x) is ~~y"). And methods
with binding-tuple arguments must be expanded from e.g.:

@when(something, "let(x=1, y=2) and somethingElse(foo)")
def aMethod((x,y), foo):
...

to:

@when(something, "let(x=1, y=2) and somethingElse(foo)")
def aMethod(__args__, foo):
(x,y) = __args__
...

(This isn't a general repacement for named-tuple arguments, just for
ones used with PEAK-Rules' let-binding feature. The special argument
*must* be named __args__ and it *must* be unpacked to the desired
named arguments as the first code inside the function body.
Otherwise, an exception will be raised.)

Both backquoted names and let-bindings are fairly obscure features of
PEAK-Rules, but now it's possible to port code using them to 3.x. The
old ways of spelling these features remain so that old code doesn't
break, and the new ways work under both 2.x and 3.x so you can begin
switching your 2.x code even if you're not porting to 3.x yet.
Post by PJ Eby
Update: I've reviewed all remaining PEAK-Rules failures on 3.1, 3.2
method argument binding is broken, due to dependence on named tuple
args. Everything else is shallow or cascading errors, now that I've
updated BytecodeAssembler to emulate the SLICE_X opcodes from Python
2.x. (Note that 3.3+ changes dictionary and function reprs and
certain dissasembly bits, which adds a couple hundred lines more
failure output compared to 3.1/3.2, but AFAICT these are all shallow.)
Also, I've changed syntax binding variables to the form ~~x instead of
`x` -- the latter syntax still works on 2.x, but of course is not
available on 3.x.
If you find anything in PEAK-Rules that's not working on 3.x that
*doesn't* depend on tuple argument syntax, let me know.
Post by PJ Eby
Yes. Slicing is broken, as is syntax pattern matching. I'm not
seeing any breakage on peak.rules.debug's import, though. As of this
morning, Python 3.1 has 735 lines of failure output from `setup.py
test`, in about 30-something individual doctest failures, almost half
of which are pure repr issues, where the values shown as not matching
are actually equal. Most of the remaining ones are either
SyntaxErrors caused by unsupported-on-3.x syntax, slicing problems, or
cascading errors from the two preceding things. I only see two errors
that look like they need further investigation: the MRO problem in
README.txt, and the 'NoneType is not callable' in Predicates.txt.
I'm thinking that I need to change the pattern-matching syntax to
something like `[[var]]` instead of backquotes, though for backwards
compatibility I'll still support backquotes. But then the tests and
things can use [[]] syntax to work across 2.x and 3.x.
(Btw, I just checked in some more test cleanup stuff, to clear away
several more false positive test failures on 3.x)
Post by Cara
I haven't had much chance to look at this this week, but I checked out
and installed the current versions in SVN. Except for the same
segfaults in BytecodeAssembler's tests, most of the major bugs I saw are
gone. There are some real bugs still in PEAK-Rules, some of which are
shallow but may be concealing more serious bugs (the peak.rules.debug
import in test_rules.py is broken), some of which are shallow and easily
fixable (__repr__ differences), and some of which look like real bugs.
I could post the log if it would be helpful, but I assume you're seeing
the same thing.
Cara
Cara
2015-04-13 16:38:33 UTC
Permalink
Most of the tests on my system now seem to be passing. In Python 3,
PEAK-Rules is clean except for a couple of deprecation warnings. There
are some shallow failures in AddOns and BytecodeAssembler's doctests
still segfault.

http://pastebin.com/2K3Qzb0b

On Python 2 everything is clean except that there are a handful of
failures for PEAK-Rules. I think they're all shallow except for a
failure to import ord from assembler.py.

http://pastebin.com/ScizUKkV

A quick look suggests that because `new` exists in Python 2, ord never
gets set in assembler.py.

try:
from new import code as NEW_CODE, function
except ImportError:
from types import FunctionType as function
NEW_CODE = lambda ac, *args: CodeType(ac, 0, *args)
long = ord = int

Probably you want to enclose the import in the doctest in another try:
except: block. I don't know why you aren't seeing this bug.

Cara
PJ Eby
2015-04-13 19:28:27 UTC
Permalink
Oops, the Python 2 errors are because I forgot to check in some code.
;-) (Specifically a similar export in BytecodeAssembler.) The
'anonymous' function thing is because I have a local change to
DecoratorTools that needs a test before I can check it in. Fixing the
segfault is waiting on me retooling my developer environment a bit so
I can more easily test against all Python versions; I hope to work on
that sometime this week.

In the meantime, if any of the actual functionality of PEAK-Rules
appears broken, let me know. (Btw, you can get *much* shorter output
from the tests if you use 'setup.py -q test'; it will show only a line
of dots and any actual failures, rather than a detailed accounting of
what is being run.)
Post by Cara
Most of the tests on my system now seem to be passing. In Python 3,
PEAK-Rules is clean except for a couple of deprecation warnings. There
are some shallow failures in AddOns and BytecodeAssembler's doctests
still segfault.
http://pastebin.com/2K3Qzb0b
On Python 2 everything is clean except that there are a handful of
failures for PEAK-Rules. I think they're all shallow except for a
failure to import ord from assembler.py.
http://pastebin.com/ScizUKkV
A quick look suggests that because `new` exists in Python 2, ord never
gets set in assembler.py.
from new import code as NEW_CODE, function
from types import FunctionType as function
NEW_CODE = lambda ac, *args: CodeType(ac, 0, *args)
long = ord = int
except: block. I don't know why you aren't seeing this bug.
Cara
_______________________________________________
PEAK mailing list
http://www.eby-sarna.com/mailman/listinfo/peak
Loading...