I'm British and I have never personally pronounced it "istoric", and to my knowledge I have never heard anyone pronounce it like that either. Is it a regional thing? I can only recall it being pronounced like that in US TV shows with comedy fake English accents.
"An hour" on the other hand makes more sense, as that is truly a soft H.
"An historic" is not only still acceptable in the USA, but it also (IMO) sounds better. The leading "H" is not a strong-sounding consonant, and is often dropped in both American and British English.
The 'h' is stressed in 'history', not in 'historic'. Try pronouncing 'historic' with a stress on the first syllable, it sounds wrong. Since it's softer in historic it's more natural (to me anyway) to use 'an'.
(Also, I'm french so I barely pronounce h's to begin with - so in my speech the stressed 'h' in history is kinda soft, and the unstressed h in historic is barely there.)
I've been doing this for ten years. Why wouldn't you use 2to3? In my experience, 2to3 is all you need 95% of the time. It is really that good.
The only times it doesn't work is with python that is bad to an unusual degree. For example, if you make a variable named "list", overriding the built-in list type. 2to3 freaks right out. The other type of "bad" python is stuff that abuses the "open kimono" nature of the language and heavily monkeypatches python internals. Or things that depend on version specific binary data, like pickle files.
First, I'd recommend python-future rather than 2to3, it has additional fixers and replaces some with better versions.
Second, those only do the fairly straightforward changes, fixers are simple AST transformations they don't do complex type analysis or anything, you should use them as a starting point but don't expect the work to be over by then: the 2->3 transitions has a number of API and semantics changes which these tools can't handle, text model changes are the biggest one[0] but they're not the only one by far.
If the project is non-trivial, having a good test coverage is absolutely crucial.
Basically, 2to3 handles the first 90% of the work which are mostly drudgery and syntactic fixes, you're still on the hook for the second 90% which is more subtle.
Source: finalising the conversion of a ~200k SLOC codebase to cross-version compatibility.
[0] not just the strict separation of text and bytes, but APIs being set to one or the other so you have places where you want to ensure bytes, others where you want to ensure text and yet others where you need "native strings", some APIs (csv) are also incompatibly altered.
Lots of people mention strings, but for a concreteish example: you have some code which reads bytes from the network, say "cookie", and uses that as a key into a dict. Later you try to access the stored value with headers["cookie"].
This works in python 2. It silently fails in python 3 because b"cookie" and "cookie" are different keys. Not really related to whether the original code supported Unicode or not.
2to3 gets all the good low hanging fruit syntatic fixes I've found, but it really comes down to the str/bytes divergence and how mucked up the mixing was in the py2 code. His comment here is the clinch...
"pdbparse is among the worst offendants I’ve seen since, as any parsing library, it will happily handle and transform bytes-like data as string."
This has not been accurate at all in my experience. It really came down to whether the code had supported non-ASCII text before — if there's a huge amount of bytes/str conflation, it's a mess but if it followed good Python 2 practice it's been very close to convert and run.
I agree, although different people's experience may differ simply because they were or were not using certain language features often.
What bites me all the time is the division operator. The 2to3 code will run, but produce incorrect results. String / byte handling is an obvious other one.
This lines up with my experience. Strangely I had someone submit a bunch of slightly passive-aggressive "Py3 support" pull requests to a couple of my repos which were basically the result of running 2to3 on the code. They hadn't even bothered to run the unit tests (which obviously failed spectacularly). It did however prompt me to get Py3 support working properly which was actually a good thing.
> Strangely I had someone submit a bunch of slightly passive-aggressive "Py3 support" pull requests
Is there a more polite way to go about this? I submitted some "Py3 support"-style pull requests to a repo out of the blue a while back. In that case it was just a few minor changes to some fairly small scripts and I did those by hand, preserving Py2 compatibility. But I did wonder at the time whether it wasn't a bit jarring for the owner to see a stranger pop up with a bunch of pull requests like that.
This is the usual process for submitting a large change to a project:
1. Check the issue tracker or mailing list for an existing discussion about Python 3 support. If there is one, read the discussion. If there isn't one, start the discussion. Mention that you're willing to make the changes if there is interest. Remember that supporting both Python 2 and Python 3 places a burden on all future contributors.
2. Keep the changes minimal and easy to review.
3. Review the changes yourself before sending a patch/pull request.
4. Run the test suite.
5. Test your changes in all versions of Python the software supports.
Forgetting #1 is usually the cause of tension when people submit large patches. The person who submits a patch wants to see their patch included. The authors of the project want to make sure it aligns with the goals of their project and doesn't break their software.
You can't make something truly polyglot across all of 2.X and all of 3.X. However much of py3 syntax is supported by py2. As far as I know, 2to3 doesn't produce py3-only syntax. I diff the original and the converted code, merging the non-compatible parts into a version check.
> You can't make something truly polyglot across all of 2.X and all of 3.X.
There's little reason to though, generally you want 2.7 and >=3.x (the simplest is 3.5, 3.4 is fairly easy, 3.3 is possible but starts being more annoying)
> As far as I know, 2to3 doesn't produce py3-only syntax.
It does: print function, metaclass kwarg. It will also generate syntactically valid but P2-incompatible code (with_traceback calls) as well as possibly semantically break P2 code (rename __nonzero__ to __bool__, basestring and unicode to str, stdlib changes, raw_input to input, …)
Print() is valid in Python2. It will print a tuple under some conditions, but that is still syntactically valid and a graceful degradation. (Print is for humans to read. As long as a human can understand it, good enough. Going for full identical behavior costs extra :-) Valid-but-incompatible is fine for polyglot stuff. Merge the files and put in a version test around those parts.
I was experimenting with them a little while ago, along with MyPy [1] but I immediately ran into an issue where the type system couldn't describe the type I was using, so I had to let it go (reluctantly.)
Same. Mypy was very limited at the beginning, and have been much more improved since. I give it a try regularly. It is indeed way better now, although I'm still structural typing and taking duck typing in consideration.
I really like the suggestion about focusing on PR for PR, that is pull request public relations. PR diplomacy, very sound advice.
+1 for articulating this bit of funny business in the Python Windows ecosystem...
"Moreover on Windows the building process was historically so bad that you usually end up downloading binaries from some random guy on the Internet."
I once spent a week porting some python2 researchware into python3. It was only at the end of that week that I discovered that it was the actual logic of the researchware that was broken, and not the way I was porting it. I now distrust all FOSS except for widely used and tested ones. You would think that a graduate student would debug (or at least fix to the point of being interpretable) the work that they spent months on before publishing it as finished and adding it to pip.
And yes, 2to3 fixes 90% of porting problems. But in my experience, it was especially bad at handling, of all things, import statements. Definitely not a silver bullet.
I'm not conflating them, but clearly software can be both researchware and open source. I'm not going to start distrusting tensorflow or scikit-learn, but I'm going to be wary before I invest time in a promising niche software package, regardless of whether it was actually from academia or not.
You have a remarkably rosy view of grad students and their relationship to software. All it has to do is produce output (I hesitate to say work) one time, on one computer, under some conditions that may never be documented, let alone reproduced. This is doubly true if the code just a step in the analysis chain and not the actual subject of the research.
In this case, the software itself was the focus of the research. And this grad student still works at a very prestigious university for CS.
I've worked in academia (as a research assistant) before so I'm familiar with shitty grad student software. But going to the effort to document and present on the software without making sure it even worked? That seemed excessively stupid to me.
That's dismaying -- not at all surprising, unfortunately, but I understand your frustration. The upside-down incentives in the academic world are such that even somebody who ought to know better fails to produce useable software because there's no payoff. Actually, it's worse than that -- producing software other people can use means you might be giving a leg up to the competition, so there's an incetive to produce software that appears to work but is in fact useless.
You would think that a graduate student would debug (or at least fix to the point of being interpretable) the work that they spent months on before publishing it as finished and adding it to pip.
HA ha ha ha ha. No. Not even a little.
There are a bunch of reasons for this, but the big ones are:
1. Scientists aren't developers (some of us are exceptions, but we prove the rule).
2. The objective function of a grad student is "publish and graduate" not "write good code and use it forever".
In almost every Python-related project I work on, we're developing in an exciting new language called "Python 2-compatible Python 3 subset". Twice as must testing, twice as much fun!
Yes, this is exactly the issue. Porting to Python 3 was never an issue itself, but keep your code compatible with Python 2 (while introduce 3) is a nightmare :P
I've been working on one project that needs to work in every Python verson from 2.4 to 3.3. There are some pretty fun gymnastics getting some syntax to work.
Why wouldn't we build a vehicle that can drive on streets, on rails, can fly, swim and dig through the earth? It would be a marvellous construction. And awful engineering.
I'm not blaming the person who builds the machine in the end, but the person that sets up the specification – they are doing a bad job.
If it's a large project, you can't necessarily move everything to Python 3 all at once. You can't break Python 2 compatibility until everything works in Python 3.
Partly that, and partly dependencies. For example in one project we use VTK for visualization. The Python VTK wrapper until recently only supported Python 2. So the rest of the project is Python2/3 compatible, but to run the visualization we have to run the Python 2 version.
VTK itself recently does support Python 3, but it's not in Debian/Ubuntu yet. And we'd have to upgrade our code to VTK 7. (Now 8, I believe, seems we've skipped a version.) So... lots of inertia all around, basically.
The result is that in the meantime (meantime being like, 2 years), we compile Python 2 and Python 3 versions of everything.
Not to mention that it's hard to justify breaking user's code that we aren't in control of just to tell them to fix their print statements -- though obviously we'll get there eventually.
Swift is 3 years old. Most people who use it will be on the latest version Swift 4 within a few months. Apple won’t let developers stay behind.
While it was unrealistic for Python to be that aggressive given its larger community, not forcing the issue created a lot of unnecessary work for the community. A benevolent dictator should have moved developers along faster. Having the language fragmented for this long is extremely unproductive.
I don't think Apple could even get away with this if Swift were more than 3 years old. I suspect the relationship between migration pain and age is exponential.
In part it's age. In part, Apple get away with it because they forewarned developers. Swift explicitly intended a "move fast and break things" approach to syntax, naming etc.
I like it, "development tough love", ha. I think looking back it becomes clearer in hindsight that it really did consume a lot of community energy. I'm vaguely sensing maybe some kind of community development bystander effect where fixing and upgrading is someone else's problem has kept the divide around longer than it needed to be.
> They added Python 3 features to Python 2 over the years to encourage adoption of Python 3 as the standard. It worked.
Did it really? My impression was the opposite: the fact that so much of Python 3 became available in Python 2 made people feel like there was no point in moving to Python 3.
It worked both ways. Some new features were ported back, some could be ported, but explicitly weren't to encourage migration. On the other side, things like the "u" prefix got re-added to python 3 for compatibility.
Isn't Swift compiled? I'm not sure it's relevant to the specific problems faced here, unless a library written and compiled in earlier versions of Swift won't be usable in a Swift 4 project.
Ah, I see. I assume you could compile to a C compatible library, but they you would have to deal with marshaling costs where the types mismatch, correct?
They should have created an annotation or something saying "this file uses the python3 dialect", made python3 run all python2 code unmodified (the only way to not require both being on $PATH), and halted python2 releases except critical security bugs.
Because python3 and python2 are incompatible dialects, you have to say which one you want, and there's no reliable way to use just "python" and no useful reason to have it on $PATH. Any code needs to declare all its dependencies, including either python3 or python2. If I didn't want any specific dependencies, I'd be targeting POSIX and writing in Bourne shell.
If you mean OS distros then this is not a concern. Unless your python needs are very small then you shouldnt use the OS distro for your python apps you should be running them in independent virtual environment with independent versions and packages
Aren't there more 2.7 users than 3.x users? I am certain this is true in the scientific community. But I also thought it was true for the general. So telling the majority of your user base "to go fuck themselves" is, generally, not considered a good idea.
GP comment seems like a troll. There is no formula as simple as "always use 3 and don't bother with 2". Not all python2 modules have been ported to python3 and python2 modules are unlikely to be future-supported as long as python3.
Django's next version will be the first that doesn't support Python 2 anymore (because that Django version will be supported longer than Python 2), I hope that that will start the mass updating at my employer's.
Oh dear God why do you hate my eyes. Tiny sans-serif gray body text is of the Devil and should be grounds for irate and overbearing truculent curmudgeons to whine about on online forums.
Maybe this is an unpopular opinion coming from someone new to Python (2 years) but the way this versioning was done is definitely a pain point. Working with new code and looking up docs to achieve X, working with existing code and trying to apply the same solution. God it's annoying.
Having said that, I know the decisions were not made lightly, and were backed by logical analysis. If nothing else, it's a good case study for the evolution of future languages (looking at you golang 2.0).
How about a type checked python variant ala typescript that compiles to python2 or python3?
Do: introduce and require the compile step for awhile, flesh out the language and build it up, get by-in and an ecosystem while also leveraging compatibility with python2/3 ecosystems -- then eventually release a python4 that runs this new typed python language directly!
Have you tried the typing [0] module? I now use it for every project I'm working on and I find the experience working with it similar to the experience I have working with TypeScript. At least if you use a good IDE that can handle the type annotations.
> Usually, a dev writing a Python 2.7 library will not discriminate between bytes-like buffers and ASCII strings (since the language doesn’t either) which means to have to code review everything str operations and ask yourself if there is a bytes operation implied or is it really a string one.
And...that's exactly why you want static typing. Code review to catch stuff like this is poorly and primitively doing a job a computer can do for you perfectly. Dynamic typing is fine for small projects but when you're wanting to port over all Python 2 code that's ever been written to Python 3 types would have made the task much less daunting.
You're thinking strong typing, not static typing. With stronger types, there would be a difference between a bytes string and unicode string, and the programmer would have to explicitly choose between them. With dynamic typing, this difference can still exists, and it is still obvious from the code. The only difference is that it isn't checked by the compiler at compile time.
Look at c. It has static typing, but fairly weak types. Strings are represented as a series of bytes (char *). The exact same work would be required to port c code to semantic c++.
Whatever terminology you want to use, I mean at compile time you would get an error because the types are wrong for that specific example. Python is generally referred to as strongly dynamically typed, that's why I only wrote "static".
In this case, a new type was introduced...bytes didn't exist. So I don't know that static typing would have helped much, at least for dealing with existing code. You still have to decide what migrates from type1 to type2.
The "bytes" that was put into 2.6 was just an alias to str as hinting for the 2to3 utility.
If Python had static typing though, wouldn't that have introduced a compile time error instead of a runtime error? At the least it would alert you to all the places you had to make the decision instead of waiting for a runtime crash.
Introducing a new type to a statically typed language still requires that decision point. The compiler can't know what was string and now should be byte. So there wouldn't be errors, other than maybe for types you're passing into 3rd party libraries that changed themselves from 2 to 3. Yes, it would help after that decision.
And as mentioned, the byte "backported (sort of)" to 2.x acts and works differently than the byte in 3.x. So there actually 3 types in play, plus bytearray too.
Yeah, I'm not saying static typing would make the decision for you but it would let you know every line in your code where the decision had to be made instead of having to rely on runtime crashes or debugging weird behaviour. The latter is really horrible as well as it's hard to pinpoint where the problem originates from and you sometimes have to delve into the innards of libraries you're using to understand what's going on.
I just think it's a good example of how strong static typing makes refactoring large projects significantly easier compared to strong dynamic typing. Getting everyone to move from Python 2 to 3 is basically a massive refactoring task.
Statically-typed Python 2 would not have solved this, since the problem was a single type permitting both string-like and bytes-like operations. A static type checker would simply say "yup, that type supports that".
The solution -- introducing a new type which explicitly is not to be used in string-like fashion and does not expose the same interface as 'str' -- was implemented in Python 3, and does not require static typing.
Also, I've been involved in porting very large codebases and have never felt a need for static typing to assist. The "dynamic typing is only for tiny puny baby child's toy programs" meme does not reveal your sagacity; it reveals your ignorance.
> Statically-typed Python 2 would not have solved this, since the problem was a single type permitting both string-like and bytes-like operations. A static type checker would simply say "yup, that type supports that".
You'd have to change type definitions then...if you define the type to allow those operations then obviously a static type checker isn't going to help. From the article they have this Python 2 -> 3 example which seems like static typing would catch:
self.streams = zip(sizes, page_lists)
and
# zip return a generator on Py3
self.streams = list(zip(sizes, page_lists))
> Also, I've been involved in porting very large codebases and have never felt a need for static typing to assist. The "dynamic typing is only for tiny puny baby child's toy programs" meme does not reveal your sagacity; it reveals your ignorance.
Why would you not want assistance from the computer to automatically check things for you given the choice? Why would you not want ways to automatically refactor your code? Those are good reasons, not memes or ignorance... Basic refactorings like changing an ID field between being a number and a string type are just horrible with languages that have dynamic types and implicit conversions for example.
Yes, but they're usually unsound. If you rename a field in thousands of lines of JavaScript code for example, you've no guarantee it's still going to work because of JavaScript's dynamic nature. I'm not saying refactoring dynamically typed code it impossible, it just makes life harder and I don't understand why you'd want that if you had a choice.
Because everything has a cost, and the cost of static typing, as it stands right now, is far higher than any hypothetical you can propose about more difficult refactoring or unsuitability for "large" codebases.
What is the "far higher" cost of static typing?
In F# you don't even need to specify the types, they are (almost) all inferred.
And you can be sure that you won't ever multiply feet with meters and crash some space probe on Mars for example.
I think that the cost of the lost space probe is far higher than whatever advantage you find in dynamic typing.
From my point of view I can see no advantage whatsoever, only disadvantages.
I'm also curious about this "cost of static typing" that is always brought up. What is the cost really? Typing and reading 5 extra characters per function argument?! It's not like every single line of your algorithm inner loop code will be littered with types, there you still keep it clean and skimmable with inferred types. You only make the interfaces type safe, this prevents function misuse, simplifies refactoring and makes the architecture graspable.
The cost is up-front having to think carefully about types when you're not yet done exploring the problem space. Types, if you're going to use them, should be decided on after you've completed that step.
This is why if you're going to do it, a dynamically-typed language that allows adding hints/annotations later on is an ideal choice.
And this is not a purely hypothetical objection: once you put types in a program, you're constraining the future of what you can do unless/until you go back and change them. Those constraints are a very real and, in my experience, very high cost.
You say I'm being hypothetical but I back up what I'm saying with examples when you don't.
What high cost do you mean? The extra time you spend writing type annotations and getting your program to compile is time you save puzzling through runtime errors. Python, JavaScript and even PHP all have ways to get static checking from the use of types. Why would you not want to take advantage of this and rely on less reliable dynamic checks instead?
I never ported something from 2 to 3, but whenever I read about it I wonder, wouldn't the new typing [0] module be enough to cope with this? It let's you annotate types like 'str', 'bytes', 'bytearray', etc. My IDE shows me right away, whenever I have the types wrong and with all the annotations visible I find it pretty easy to reason about types.
Sounds like it would help but it sounds like the same 2 to 3 issue that everyone has to start migrating to it.
> My IDE shows me right away, whenever I have the types wrong and with all the annotations visible I find it pretty easy to reason about types.
Do you find it makes you more productive? Honestly not trying to troll but my feeling is people that defend strong dynamic typing just haven't used strong statically type languages enough because the benefits are painfully obvious to me when you switch between them.
> it sounds like the same 2 to 3 issue that everyone has to start migrating to it.
If you don't like to have it in your code base, then you could use it for the migration phase and remove it afterwards, or just leave it in the parts of the project, where it was helpful. It's totally optional, meaning, you can use it just on some parts of your code without affecting the rest.
> Do you find it makes you more productive?
It makes me a lot more productive. Especially when I touch code that I haven't seen in a while. I use it everywhere. Actually my IDE highlights items that I forgot to annotate.
> Honestly not trying to troll but my feeling is people that defend strong dynamic typing just haven't used strong statically type languages enough because the benefits are painfully obvious to me when you switch between them.
I'm not defending strong dynamic typing. I just think that the typing module makes Python a better language. I use the typing module for the same reason I switched from JavaScript to TypeScript and the experience I have working in both, Python+typing and TypeScript, is very similar, even though TypeScript is strong statically typed.
> I'm not defending strong dynamic typing. I just think that the typing module makes Python a better language. I use the typing module for the same reason I switched from JavaScript to TypeScript and the experience I have working in both, Python+typing and TypeScript, is very similar, even though TypeScript is strong statically typed.
I think you've misread me, I had the exact same experience with both languages and agree with you.
Well, this isn't exactly how I expected my PDB parsing library to end up on HN ;)
The bytes/string changeover is probably the biggest pain point for RE tools written in Python2. Indeed, despite lucasg's excellent work porting things over, there was still at least one byte/string issue that needed to be fixed:
Edit: Also, I have one small correction – pdbparse is actually 10 years old, not 5! I started writing it my first year out of college, which also explains (in part) why the code is a bit crap. As evidence I offer the first article I wrote on the PDB format:
125 comments
[ 6.0 ms ] story [ 184 ms ] threadhttps://en.oxforddictionaries.com/usage/a-historic-event-or-...
Which we do (in Britain and the rest of the English speaking world outside North America), so "an historic" it is.
e.g. from BBC:
http://www.bbc.co.uk/programmes/p055vr37
"An hour" on the other hand makes more sense, as that is truly a soft H.
https://github.com/jwilk/anorack
$ ./anorack test_file
$ out:1: an historic -> a historic /hIst'0rIk/
Interesting. What if...
$ ...hacks phonetics.py to use "en-us" voice...
$ ./anorack test_file
$ out:1: an historic -> a historic /hIst'0rIk/
Hum... same result. What about:
$ ...hacks phonetics.py to use "en-wm" voice...
$ ./anorack test_file
$
Ah, finally someone gets it right :)
(just having a bit of fun, this is a cool work!)
Edit: formatting...
No need to feel ignorant; it's a nonstandard, eSpeak-specific notation.
History: /ˈhist(ə)rē/
Historic: /hiˈstôrik/
The 'h' is stressed in 'history', not in 'historic'. Try pronouncing 'historic' with a stress on the first syllable, it sounds wrong. Since it's softer in historic it's more natural (to me anyway) to use 'an'.
(Also, I'm french so I barely pronounce h's to begin with - so in my speech the stressed 'h' in history is kinda soft, and the unstressed h in historic is barely there.)
(edited)
The only times it doesn't work is with python that is bad to an unusual degree. For example, if you make a variable named "list", overriding the built-in list type. 2to3 freaks right out. The other type of "bad" python is stuff that abuses the "open kimono" nature of the language and heavily monkeypatches python internals. Or things that depend on version specific binary data, like pickle files.
This is absolutely not the case in my experience.
2to3 tends to produce something that appears to work at first glance, but it actually doesn't.
Second, those only do the fairly straightforward changes, fixers are simple AST transformations they don't do complex type analysis or anything, you should use them as a starting point but don't expect the work to be over by then: the 2->3 transitions has a number of API and semantics changes which these tools can't handle, text model changes are the biggest one[0] but they're not the only one by far.
If the project is non-trivial, having a good test coverage is absolutely crucial.
Basically, 2to3 handles the first 90% of the work which are mostly drudgery and syntactic fixes, you're still on the hook for the second 90% which is more subtle.
Source: finalising the conversion of a ~200k SLOC codebase to cross-version compatibility.
[0] not just the strict separation of text and bytes, but APIs being set to one or the other so you have places where you want to ensure bytes, others where you want to ensure text and yet others where you need "native strings", some APIs (csv) are also incompatibly altered.
This works in python 2. It silently fails in python 3 because b"cookie" and "cookie" are different keys. Not really related to whether the original code supported Unicode or not.
What bites me all the time is the division operator. The 2to3 code will run, but produce incorrect results. String / byte handling is an obvious other one.
Is there a more polite way to go about this? I submitted some "Py3 support"-style pull requests to a repo out of the blue a while back. In that case it was just a few minor changes to some fairly small scripts and I did those by hand, preserving Py2 compatibility. But I did wonder at the time whether it wasn't a bit jarring for the owner to see a stranger pop up with a bunch of pull requests like that.
This is the usual process for submitting a large change to a project:
1. Check the issue tracker or mailing list for an existing discussion about Python 3 support. If there is one, read the discussion. If there isn't one, start the discussion. Mention that you're willing to make the changes if there is interest. Remember that supporting both Python 2 and Python 3 places a burden on all future contributors.
2. Keep the changes minimal and easy to review.
3. Review the changes yourself before sending a patch/pull request.
4. Run the test suite.
5. Test your changes in all versions of Python the software supports.
Forgetting #1 is usually the cause of tension when people submit large patches. The person who submits a patch wants to see their patch included. The authors of the project want to make sure it aligns with the goals of their project and doesn't break their software.
There's little reason to though, generally you want 2.7 and >=3.x (the simplest is 3.5, 3.4 is fairly easy, 3.3 is possible but starts being more annoying)
> As far as I know, 2to3 doesn't produce py3-only syntax.
It does: print function, metaclass kwarg. It will also generate syntactically valid but P2-incompatible code (with_traceback calls) as well as possibly semantically break P2 code (rename __nonzero__ to __bool__, basestring and unicode to str, stdlib changes, raw_input to input, …)
print("a", end=" ") is not, neither is class Foo(metaclass=Bar)
[1] http://python-future.org
I haven't seen them used anywhere, but that's an okay solution I guess.
NB : by the way, love your blog :p
[1] http://mypy-lang.org/
> NB : by the way, love your blog :p
Thanks :)
Also, that doesn't help those of us stuck on Python 3.4, the last version that supports Windows XP (don't ask).
But some other projects are so hardcore about CLA enforcement, they won't even accept one-letter typo-fixes without CLA signed.
+1 for articulating this bit of funny business in the Python Windows ecosystem... "Moreover on Windows the building process was historically so bad that you usually end up downloading binaries from some random guy on the Internet."
And yes, 2to3 fixes 90% of porting problems. But in my experience, it was especially bad at handling, of all things, import statements. Definitely not a silver bullet.
I've worked in academia (as a research assistant) before so I'm familiar with shitty grad student software. But going to the effort to document and present on the software without making sure it even worked? That seemed excessively stupid to me.
> document and present on the software without making sure it even worked? That seemed excessively stupid to me
It sounds like that individual is responding rationally to the incentive structure he's embedded in, and succeeding as a result.
HA ha ha ha ha. No. Not even a little.
There are a bunch of reasons for this, but the big ones are: 1. Scientists aren't developers (some of us are exceptions, but we prove the rule). 2. The objective function of a grad student is "publish and graduate" not "write good code and use it forever".
I'm not blaming the person who builds the machine in the end, but the person that sets up the specification – they are doing a bad job.
All the projects I've worked on moved to Python 3 and never looked back.
VTK itself recently does support Python 3, but it's not in Debian/Ubuntu yet. And we'd have to upgrade our code to VTK 7. (Now 8, I believe, seems we've skipped a version.) So... lots of inertia all around, basically.
The result is that in the meantime (meantime being like, 2 years), we compile Python 2 and Python 3 versions of everything.
Not to mention that it's hard to justify breaking user's code that we aren't in control of just to tell them to fix their print statements -- though obviously we'll get there eventually.
When all dependencies were there, we made the switch.
While it was unrealistic for Python to be that aggressive given its larger community, not forcing the issue created a lot of unnecessary work for the community. A benevolent dictator should have moved developers along faster. Having the language fragmented for this long is extremely unproductive.
There was no backwards compatibility with Python 2 and it had relatively little adoption.
They added Python 3 features to Python 2 over the years to encourage adoption of Python 3 as the standard. It worked.
Now we just need Apple to ship Mac OS with Python 3 instead of 2 as the default and that'll push adoption for developers.
Did it really? My impression was the opposite: the fact that so much of Python 3 became available in Python 2 made people feel like there was no point in moving to Python 3.
On macOS 10.12.5, released 2017-05-15:
That's a release from 2015-05-23. Latest is 2.7.13 released 2016-12-17.And no system python3. Only through Homebrew/Macports.
Do you think that means they don't care about Python? Perhaps it's not a strategic language for them?
No one said they the provide a full Unix system or keep everything else up to date. Apple has a very narrow focus on what's important to them.
Django's next version will be the first that doesn't support Python 2 anymore (because that Django version will be supported longer than Python 2), I hope that that will start the mass updating at my employer's.
Can't comment on the site itself, so: PEP 484 - Type hints ( https://www.python.org/dev/peps/pep-0484/#suggested-syntax-f... ) does suggest Python 2.7-compatible type hints, and PyCharm, and probably other IDEs, do support them (e.g., https://www.jetbrains.com/help/pycharm/type-hinting-in-pycha... ).
Having said that, I know the decisions were not made lightly, and were backed by logical analysis. If nothing else, it's a good case study for the evolution of future languages (looking at you golang 2.0).
Do: introduce and require the compile step for awhile, flesh out the language and build it up, get by-in and an ecosystem while also leveraging compatibility with python2/3 ecosystems -- then eventually release a python4 that runs this new typed python language directly!
Bring us the beauty!
[0] https://docs.python.org/3/library/typing.html
And...that's exactly why you want static typing. Code review to catch stuff like this is poorly and primitively doing a job a computer can do for you perfectly. Dynamic typing is fine for small projects but when you're wanting to port over all Python 2 code that's ever been written to Python 3 types would have made the task much less daunting.
Look at c. It has static typing, but fairly weak types. Strings are represented as a series of bytes (char *). The exact same work would be required to port c code to semantic c++.
The "bytes" that was put into 2.6 was just an alias to str as hinting for the 2to3 utility.
And as mentioned, the byte "backported (sort of)" to 2.x acts and works differently than the byte in 3.x. So there actually 3 types in play, plus bytearray too.
I just think it's a good example of how strong static typing makes refactoring large projects significantly easier compared to strong dynamic typing. Getting everyone to move from Python 2 to 3 is basically a massive refactoring task.
The solution -- introducing a new type which explicitly is not to be used in string-like fashion and does not expose the same interface as 'str' -- was implemented in Python 3, and does not require static typing.
Also, I've been involved in porting very large codebases and have never felt a need for static typing to assist. The "dynamic typing is only for tiny puny baby child's toy programs" meme does not reveal your sagacity; it reveals your ignorance.
You'd have to change type definitions then...if you define the type to allow those operations then obviously a static type checker isn't going to help. From the article they have this Python 2 -> 3 example which seems like static typing would catch:
and > Also, I've been involved in porting very large codebases and have never felt a need for static typing to assist. The "dynamic typing is only for tiny puny baby child's toy programs" meme does not reveal your sagacity; it reveals your ignorance.Why would you not want assistance from the computer to automatically check things for you given the choice? Why would you not want ways to automatically refactor your code? Those are good reasons, not memes or ignorance... Basic refactorings like changing an ID field between being a number and a string type are just horrible with languages that have dynamic types and implicit conversions for example.
This is why if you're going to do it, a dynamically-typed language that allows adding hints/annotations later on is an ideal choice.
And this is not a purely hypothetical objection: once you put types in a program, you're constraining the future of what you can do unless/until you go back and change them. Those constraints are a very real and, in my experience, very high cost.
What high cost do you mean? The extra time you spend writing type annotations and getting your program to compile is time you save puzzling through runtime errors. Python, JavaScript and even PHP all have ways to get static checking from the use of types. Why would you not want to take advantage of this and rely on less reliable dynamic checks instead?
[0] https://docs.python.org/3/library/typing.html
> My IDE shows me right away, whenever I have the types wrong and with all the annotations visible I find it pretty easy to reason about types.
Do you find it makes you more productive? Honestly not trying to troll but my feeling is people that defend strong dynamic typing just haven't used strong statically type languages enough because the benefits are painfully obvious to me when you switch between them.
If you don't like to have it in your code base, then you could use it for the migration phase and remove it afterwards, or just leave it in the parts of the project, where it was helpful. It's totally optional, meaning, you can use it just on some parts of your code without affecting the rest.
> Do you find it makes you more productive?
It makes me a lot more productive. Especially when I touch code that I haven't seen in a while. I use it everywhere. Actually my IDE highlights items that I forgot to annotate.
> Honestly not trying to troll but my feeling is people that defend strong dynamic typing just haven't used strong statically type languages enough because the benefits are painfully obvious to me when you switch between them.
I'm not defending strong dynamic typing. I just think that the typing module makes Python a better language. I use the typing module for the same reason I switched from JavaScript to TypeScript and the experience I have working in both, Python+typing and TypeScript, is very similar, even though TypeScript is strong statically typed.
I think you've misread me, I had the exact same experience with both languages and agree with you.
The bytes/string changeover is probably the biggest pain point for RE tools written in Python2. Indeed, despite lucasg's excellent work porting things over, there was still at least one byte/string issue that needed to be fixed:
https://github.com/moyix/pdbparse/issues/39
Edit: Also, I have one small correction – pdbparse is actually 10 years old, not 5! I started writing it my first year out of college, which also explains (in part) why the code is a bit crap. As evidence I offer the first article I wrote on the PDB format:
http://moyix.blogspot.com/2007/08/pdb-stream-decomposition.h...