py3k concerns. An example

M

Martin v. Löwis

Again, to me, this is a non-issue because I've been able to create a
cross-version compatible single codebase for pyparsing. But it was a
bit dicey there for a while, and I think other module developers/
maintainers may not be so lucky.

I'm more optimistic. I tried it for Django, and while the port is not
complete, it goes really well and supports "basic" operations (i.e.
the Django tutorial).

Based on your experience, and other reports, I think there is a fair
chance that you can support a wide range of versions (2.x and 3.x)
from a single code base for most projects.
- create (if possible) single cross-version compatible code
- forego support of 3.0 users
- discontinue pre-2.6 support for future versions of their module
- maintain dual codebase

One needs to consider the drawbacks in each case; for the single
codebase approach, the drawback probably is that readability
suffers, and the need for testing increases (but it does always
if you support multiple targets). It also requires expertise to
create such cross-version code in the first place, but that's
"just" a learning issue (i.e. you have to keep the rules in mind
that you want to follow).

Regards,
Martin
 
A

Aaron Watters

end point applications (I consider maintaining 2 branches to be in the
"not working" category), but it does NOT WORK for people who maintain
modules for other people to use, because those people may be on a
range of Python versions that extend beyond 2.6-3.0.  So if I upgrade
my module to 2.6, those running on earlier versions can no longer use
it.  At some point in the future, I'll probably be able to say "no
more support for pre-2.6", but it is a bit early to start saying that
now.

In my view using a conversion tool on an ongoing basis is
not an option. It just adds a dependancy. What happens when
the conversion tool is upgraded in a non-backwards-compatible
way? Or do we have assurance that it won't be ;)?

Will changes to the converter
mean that the users of my
converted libraries have to start
using my tools in a different way? Even if it breaks some
users in a very subtle way it's not acceptible.
I have no interest in adding additional dependancies,
with an additional degree of freedom to break.

This is all made worse because it's binary -- with
upgrades to C or C# you usually had the option of cross
linking between old style components and new style
components (and at least with C these could usually
be made to work) and you could port the older stuff
with care. With py 3.0 and python 2.6 *everything*
either works with the interpreter or none of it does.
(Don't ask my users to install two interpreters:
they'll just give up and use something else.)

So if I want to support both I have to do everything
twice in the expected case and in the best case test
everything twice, at the same time, if I want to
support both versions and keep features in sync.
This is of course assuming that all the supporting
libraries do the same thing. If they don't and
one of the libraries doesn't support 2.* and another
doesn't support 3.*... I guess I'm just screwed.

I still think it's a shame, and I think it's
different in kind from python 1.x->2.x. 2.x
broke very little as I recall. Most 1.x code
just worked in 2.x and most of the rest required
very minor change. I think this is not the case
for 2.x->3.x.

-- Aaron (Scummy) Watters, hoping to shut up now.

ps: I didn't notice that % was vanishing later (3.3).
that's a bit better (whew ;) ).

pps: I have to note that it would be nice if the
ad-hominem (sp?) invective would drop out of
these threads -- it doesn't add a lot, I think.

===

http://www.xfeedme.com/nucular/pydistro.py/go?FREETEXT=garbage+left+over
 
T

Terry Reedy

The reason that successive versions of 2.x broke so little is that starting
at about 2.2, all breakages (starting with int division change) were put
off until until 3.0 instead of being implemented as decided upon (with
warning, deprecation, and then removal). Now the debt comes due.

The new policy of mass breakage was a result of complaint about the old
policy of gradual breakage. Of course, the new policy will get complaints
both from those who preferred the old policy and those who want Python
frozen with nothing ever removed for improvements. No change, gradual
change, and jump change all have problems.

In a year, we will have a better idea of which was better.
 
M

Martin v. Löwis

In my view using a conversion tool on an ongoing basis is
not an option. It just adds a dependancy. What happens when
the conversion tool is upgraded in a non-backwards-compatible
way? Or do we have assurance that it won't be ;)?

The latter: if you include a copy of the converter with your
package, it won't change unless you change it. If you rely
on the copy of the converter that ships with Python 3.0, you
have the assurance that it won't change in a
non-backwards-compatible manner in all of 3.0.y.

Of course, the copies include in later 3.x releases may change, but
you'll have to test for the later 3.x releases, anyway, as
they may show incompatible changes themselves.
Will changes to the converter
mean that the users of my
converted libraries have to start
using my tools in a different way?

No. If the 2to3 converter is changed to support additional
source patterns to convert, it either won't affect your
code (if you don't use the pattern), or it may convert some
of your code that it didn't previously - then that conversion
may or may not be correct. So as a consequence, your library
may stop working; then you'll have to adjust either your
library, or go back to an older version of the converter.

In no case, however, will the users of the library need to
adjust their code to changing 2to3 output. 2to3 won't change
the library API.
I have no interest in adding additional dependancies,
with an additional degree of freedom to break.

Then remove the freedom by fixing a specific 2to3 version
(e.g. by including it).
So if I want to support both I have to do everything
twice in the expected case and in the best case test
everything twice, at the same time, if I want to
support both versions and keep features in sync.

This I don't understand. Why do you think you have to
do everything twice?
I still think it's a shame [...]
pps: I have to note that it would be nice if the
ad-hominem (sp?) invective would drop out of
these threads -- it doesn't add a lot, I think.

shame
1 a. a painful emotion caused by consciousness of guilt,
shortcoming, or impropriety
2 a condition of humiliating disgrace or disrepute

So who do you think should feel guilt? Or should
be disgraced or disreputed?

Regards,
Martin
 
G

Gabriel Genellina

Gabriel -

(Thanks for chiming in on this sub-thread, I really enjoy reading your
posts.)

(And I enjoy using your parser! Not that I have to parse text so often,
but when it comes, the "pythonicity" of pyparsing is a great thing!)
My point is that the recommended strategy MAY work for those who write
end point applications (I consider maintaining 2 branches to be in the
"not working" category), but it does NOT WORK for people who maintain
modules for other people to use, because those people may be on a
range of Python versions that extend beyond 2.6-3.0. So if I upgrade
my module to 2.6, those running on earlier versions can no longer use
it. At some point in the future, I'll probably be able to say "no
more support for pre-2.6", but it is a bit early to start saying that
now.

Likewise, I don't want to say "no support for 3.0" - people DO want to
try 3.0 out, and I WANT them to want and be able to use my module too.

Given the recommended strategy, and ruling out dual codebase, whom do
I tell that they can't use the next version of my module?

Ok, code that is "2.6 compatible" doesn't mean that it only runs on 2.6...
I'm *trying* to write code that is "2to3 friendly" but anyway compatible
with older Python versions, and it should not require 2.6 to run. That
means not using "with" as a variable name, for example. (And on the other
side, also refrain from using some new 2.6 features like class decorators
and binary literals)
I hope the final version of the 2to3 tool will be a little more robust -
or at least, that one will always be able to write code in a way that it
can handle (and I *dont* want to maintain a 2.x and 3.x branches of any
code either)
Based on my limited experience I'd say that this approach *could* work,
that is, write the code base for 2.x (x >= 3, in my case) and
automatically convert to 3.0. That last stage may fail, but -I hope!- not
so often in the future. As always, YMMV...
Also note that I *don't* write code for other developers (thanks God!),
just final users (with Python 2.3/4/5)
Again, to me, this is a non-issue because I've been able to create a
cross-version compatible single codebase for pyparsing. But it was a
bit dicey there for a while, and I think other module developers/
maintainers may not be so lucky.

That's a bit tricky at least. How did you manage to avoid problems with
(string/unicode) and (bytes/string) in 3.0?
So, I feel that the recommended strategy was devised with a narrow
group of developers in mind, and leaves module developers/maintainers,
who wish to target as broad a set of users as possible, faced with
choosing one of these strategies:
- create (if possible) single cross-version compatible code
- forego support of 3.0 users
- discontinue pre-2.6 support for future versions of their module
- maintain dual codebase

I hope the first alternative will be actually viable, perhaps with help
from tools like 2to3...
 
D

Donn Cave

I still think it's a shame [...]
pps: I have to note that it would be nice if the
ad-hominem (sp?) invective would drop out of
these threads -- it doesn't add a lot, I think.

shame
1 a. a painful emotion caused by consciousness of guilt,
shortcoming, or impropriety
2 a condition of humiliating disgrace or disrepute

- [in sing.] a regrettable or unfortunate situation or action: `it is a
shame that they are not better known'

If English isn't your 1st language, you deserve a lot of credit for your
mastery of it, but you need a better dictionary.

Donn Cave, (e-mail address removed)
 
A

Aaron Watters

shame
1 a. a painful emotion caused by consciousness of guilt,
     shortcoming, or impropriety
2 a condition of humiliating disgrace or disrepute

Sigh. This is stupid (in the usual usage), but
I must reply because I can't control myself. I meant
usage 5:

"something regrettable, unfortunate, or outrageous:
it's a shame that he wasn't told."
-- http://www.yourdictionary.com/shame

I think outrageous is appropriate here because
I think it's outrageous to change the basic
usage for things like dictionary.keys() when
it would be so easy to leave the old definition
and add a new method like dictionary.keySet().
This would save me personally a great deal of
painful tedium, I suspect (especially considering
that I've implemented a lot of "dictionary-like"
objects -- so I'll have to change the way their
"keys" method works -- or something -- I haven't
figured it out yet...).

I know that the designers of Python are motivated
by a desire to attain a Platonic ideal of
aesthetic perfection primarily with a weaker desire
to make lives easy for people writing libraries
and tools somewhere further down the list,
but from my perspective it's a shame^H^H^H^H^H
regretable and unfortunate that the aesthetics
so often trumps other considerations.

In C# and java, for example, this sort of issue
has never been a problem
in my experience: stuff I wrote many versions ago
still works just fine with no changes (but please
note that I don't write gui stuff, which is less
stable -- I'm speaking of algorithmic and system
libraries).
-- Aaron Watters

===
btw: usage (5) for "shame" in the python source:
http://www.xfeedme.com/nucular/pydistro.py/go?FocusId=463&FREETEXT=shame
 
M

Martin v. Löwis

This would save me personally a great deal of
painful tedium, I suspect (especially considering
that I've implemented a lot of "dictionary-like"
objects -- so I'll have to change the way their
"keys" method works -- or something -- I haven't
figured it out yet...). [...]
In C# and java, for example, this sort of issue
has never been a problem
in my experience: stuff I wrote many versions ago
still works just fine with no changes (but please
note that I don't write gui stuff, which is less
stable -- I'm speaking of algorithmic and system
libraries).

I don't see the connection. Why do you think your
..keys() implementation breaks just because dict.keys
has a different semantics now?

An existing application of an existing dict-like
object will continue to work just fine in Python 3,
right?

I can't find the change to dictionaries outrageous.

Regards,
Martin
 
A

Aaron Watters

An existing application of an existing dict-like
object will continue to work just fine in Python 3,
right?

Unless I mix my psuedodicts with standard dicts
in the same list, for example, or pass them to
functions intended to accept any dict-like object,
including the especially important case of standard
dicts.

Who knows? Maybe I'm wrong about this being a much of
problem. 20+ years experience warns me strongly
to be very afraid, however. It would be great if I
didn't have to think about it.

Can anyone recommend a good book on Ruby :)?
-- Aaron Watters

===
http://www.xfeedme.com/nucular/pydistro.py/go?FREETEXT=unnecessary+breakage
 
M

Martin v. Löwis

Unless I mix my psuedodicts with standard dicts
in the same list, for example, or pass them to
functions intended to accept any dict-like object,
including the especially important case of standard
dicts.

Who knows? Maybe I'm wrong about this being a much of
problem.

I think so. I expect that in the typical application, you either
won't notice the difference in behavior at all, or you get an
exception the first time, in which case you can easily adjust
the code to support both cases. This expectation is supported
by experience both from adjusting the Python standard library
itself, and from converting Django to Python 3.

In my experience (from the same applications), by far the most
significant change in Python 3 is the change to the meaning of
string literals, and the disposal of the 2.x str type.

Regards,
Martin
 
P

Paul McGuire

I'm more optimistic. I tried it for Django, and while the port is not
complete, it goes really well and supports "basic" operations (i.e.
the Django tutorial).

Based on your experience, and other reports, I think there is a fair
chance that you can support a wide range of versions (2.x and 3.x)
from a single code base for most projects.


One needs to consider the drawbacks in each case; for the single
codebase approach, the drawback probably is that readability
suffers, and the need for testing increases (but it does always
if you support multiple targets). It also requires expertise to
create such cross-version code in the first place, but that's
"just" a learning issue (i.e. you have to keep the rules in mind
that you want to follow).

Regards,
Martin

Martin --

Well, my concerns about 3.0 continue to be founded. Up until now I
have been just reading "What's New" docs, and relying on input from
others as to what changes I will have to make. Yesterday I downloaded
and installed 3.0a5, and it is clear that there is *no* way to have a
single code base for any but the most trivial module.

The biggest sticking point is the incompatibility of "except" syntax.
Apparently the promise of syntax compatibility in the 3.0a4 docs was
an overstatement. Syntax can't be conditionalized out with "if
version >= 3:" type code, so I must have separate Python 2.x and
Python 3.x codebases, as will anyone whose modules include exception
handlers.

I also tripped over the conversion from "<iterator>.next()" to
"next(<iterator>)". Fortunately, this only occurs in my test cases,
so my runtime module will not be affected by extra conditional
testing, just to pick the right code form for the particular Python
version that is running.

Conversion of print from statement to function is definitely more
painful than I thought it would be. Again, I am fortunate that this
largely affects only my test code, with only minimal impact on my
runtime module.

I continue to struggle with some of the refactoring done in references
to func.func_code, im_self, etc. changing to __code__, __self__, and
so on. There is a bit of code in Pyparsing that normalizes user
callbacks to a standard call using 3 arguments, and I have to
compensate for functions that have self args, or are callables. I see
that there is some movement to "get rid of bound methods," but I don't
fully understand how this will be done, nor how I will adjust my code
to compensate.

In fact, I will probably set this effort aside for now, so as to avoid
converting/conditionalizing code to alpha versions of Python, and
having to change them again for later alphas or the final release.

By the way Martin, your work on 2to3 was especially helpful in this
effort - thank you!

In summary, I am adjusting my plans for future support of Python
versions in pyparsing. As of a pyparsing release some time after
August, I will only support Python 3.0 versions with any new features
or bugfixes, and the pyparsing version that is compatible with Python
2.x will be frozen.

-- Paul
 
M

Martin v. Löwis

Well, my concerns about 3.0 continue to be founded. Up until now I
have been just reading "What's New" docs, and relying on input from
others as to what changes I will have to make. Yesterday I downloaded
and installed 3.0a5, and it is clear that there is *no* way to have a
single code base for any but the most trivial module.

I think there is a way, if you can use 2to3.
The biggest sticking point is the incompatibility of "except" syntax.
Apparently the promise of syntax compatibility in the 3.0a4 docs was
an overstatement. Syntax can't be conditionalized out with "if
version >= 3:" type code, so I must have separate Python 2.x and
Python 3.x codebases, as will anyone whose modules include exception
handlers.

No, you don't need to maintain two code bases. Just maintain the 2.x
one, and generate the 3.x code every time you need it updated.

2to3 deals with the change to the except clauses just fine.
I also tripped over the conversion from "<iterator>.next()" to
"next(<iterator>)".

2to3 should also fix that one. Alternatively, you can add your own
next implementation to 2.x.
Conversion of print from statement to function is definitely more
painful than I thought it would be. Again, I am fortunate that this
largely affects only my test code, with only minimal impact on my
runtime module.

Again, 2to3 fixes these just fine.
I continue to struggle with some of the refactoring done in references
to func.func_code, im_self, etc. changing to __code__, __self__, and
so on.

There are also 2to3 fixers for these, although they might be incomplete.
By the way Martin, your work on 2to3 was especially helpful in this
effort - thank you!

Thanks - but this is really Collin Winter's work (with various
contributions of others, of course).
In summary, I am adjusting my plans for future support of Python
versions in pyparsing. As of a pyparsing release some time after
August, I will only support Python 3.0 versions with any new features
or bugfixes, and the pyparsing version that is compatible with Python
2.x will be frozen.

I don't want to interfere with your project plans, but I don't think
there is a factual need for such a process. Instead, you could continue
to write 2.x code, and produce 3.x code either at release or at install
time.

Regards,
Martin
 
H

Hrvoje Niksic

Paul McGuire said:
I see that there is some movement to "get rid of bound methods," but
I don't fully understand how this will be done, nor how I will
adjust my code to compensate.

Isn't it supposed to get rid of *un*bound methods? That is,
Class.method will simply return the function object used to define
'method', rather than a specialized "unbound method" object.
object.method will continue to return bound method objects, which are
required for method calls to work.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,053
Latest member
BrodieSola

Latest Threads

Top