Re: The Case Against Python 3

2016-12-01 Thread Ned Batchelder
On Thursday, December 1, 2016 at 9:03:46 AM UTC-5, Paul  Moore wrote:
> While I agree that f-strings are more dangerous than people will immediately 
> realise (the mere fact that we call them f-*strings* when they definitely 
> aren't strings is an example of that), the problem here is clearly (IMO) with 
> the sloppy checking in gettext.


Can you elaborate on the dangers as you see them?

--Ned.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: The Case Against Python 3

2016-12-01 Thread Paul Moore
On Tuesday, 29 November 2016 01:01:01 UTC, Chris Angelico  wrote:
> So what is it that's trying to read something and is calling an
> f-string a mere string?

gettext.c2py:

"""Gets a C expression as used in PO files for plural forms and returns a
Python lambda function that implements an equivalent expression.
"""
# Security check, allow only the "n" identifier
import token, tokenize
tokens = tokenize.generate_tokens(io.StringIO(plural).readline)
try:
danger = [x for x in tokens if x[0] == token.NAME and x[1] != 'n']
except tokenize.TokenError:
raise ValueError('plural forms expression error, maybe unbalanced 
parenthesis')
else:
if danger:
raise ValueError('plural forms expression could be dangerous')

So the only things that count as DANGER are NAME tokens that aren't "n". That 
seems pretty permissive...

While I agree that f-strings are more dangerous than people will immediately 
realise (the mere fact that we call them f-*strings* when they definitely 
aren't strings is an example of that), the problem here is clearly (IMO) with 
the sloppy checking in gettext.

Paul
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: The Case Against Python 3

2016-11-28 Thread Chris Angelico
On Tue, Nov 29, 2016 at 10:54 AM, Steve D'Aprano
 wrote:
> Now you're just being silly, this isn't "anything", it is a specific design
> decision: something which looks like, and is treated by the tokeniser, as a
> string but is actually a hidden call to eval.
>

This, I think, is the crux. A "hidden eval" is a fundamentally bad
thing. Python 2's input() function is bad for this reason - not
because eval is necessarily evil (there are times when that's the
exact behaviour you want), but because the simple "get text from the
keyboard" function shouldn't conceal an eval of user text.

The solution, IMO, is to treat f-strings as expressions and NOT as
strings. They are no more strings than function calls are:

"###".join(os.system("sh"))

Everything that tokenizes Python code needs to be aware of the
different string prefixes already (eg a raw string literal doesn't end
at the same point as other string literals do), and this should be no
different. The stdlib ast.parse (really a wrapper around compile)
already gets this right:

>>> ast.dump(ast.parse('lambda x,y: f"{x} + {y} = {x+y}"'))
"Module(body=[Expr(value=Lambda(args=arguments(args=[arg(arg='x',
annotation=None), arg(arg='y', annotation=None)], vararg=None,
kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]),
body=JoinedStr(values=[FormattedValue(value=Name(id='x', ctx=Load()),
conversion=-1, format_spec=None), Str(s=' + '),
FormattedValue(value=Name(id='y', ctx=Load()), conversion=-1,
format_spec=None), Str(s=' = '),
FormattedValue(value=BinOp(left=Name(id='x', ctx=Load()), op=Add(),
right=Name(id='y', ctx=Load())), conversion=-1,
format_spec=None)])))])"

So what is it that's trying to read something and is calling an
f-string a mere string?

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: The Case Against Python 3

2016-11-28 Thread Steve D'Aprano
On Tue, 29 Nov 2016 09:35 am, Gregory Ewing wrote:

> Steve D'Aprano wrote:
>> I daresay you are right that a sufficiently clever adversary may have
>> found an exploit. But there's no sign that anyone actually did find an
>> exploit, until f-strings made exploiting this trivial.
> 
> The person who wrote the bug report found at least one
> way of exploiting it that doesn't require f-strings.

Oops, of course you are right. The bug report says:

My first discovery was that nothing prevents an input plural 
string that resembles a function call:

   gettext.c2py("n()")(lambda: os.system("sh"))

This is of course a low risk bug, since it requires control
of both the plural function string and the argument.

http://bugs.python.org/issue28563


And later on:

Instead of passing a string to eval, we can build a string
from characters in the docstrings available in the context
of the gettext module:
[...]
This will successfully spawn a shell in Python 2.7.11.

Which I had forgotten about. (And by the way: the exploit could have been
avoided by refusing any string which contains an underscore. If you can't
avoid vulnerable code, at least make attackers work hard to exploit it.)

The point I was making was this comment:

Bonus: With the new string interpolation in Python 3.7, 
exploiting gettext.c2py becomes trivial:

   gettext.c2py('f"{os.system(\'sh\')}"')(0)

The tokenizer will recognize the entire format-string as 
JUST A STRING [emphasis added]

f-strings are *not* "just a string", as this shows -- they're actually
equivalent to a call to eval. And *that* is my point: we've picked a syntax
which looks like a static literal string for something which is not only a
function call but equivalent to the second most powerful (and hence
dangerous) built-in function call available in the language.

Normally I think Guido's instinct for syntax and language features is pretty
good, but here I think he's made a blunder. The original proposal on the
Python-Ideas mailing list was for syntax to automatically perform *only*
name lookups so that 

f"{x}"

was syntactic sugar for

"{x}".format(x=x)


and from that simple request it has grown in scope to the point that we can
now write:

f"{os.system('sh')}"

as syntactic sugar for:

str(eval("os.system('sh')"))

Yay for progress!



> I agree that f-strings are not to blame here.

I've already said that. Certainly the *vulnerability* comes from the use of
eval by gettext.c2py, but the TRIVIAL *exploit* comes from f-strings.


> If we really 
> want to avoid breaking anyone's ill-conceived attempts at
> sandboxing eval, we'd better not add anything more to the
> language, ever, because nobody can foresee all the possible
> consequences.

Now you're just being silly, this isn't "anything", it is a specific design
decision: something which looks like, and is treated by the tokeniser, as a
string but is actually a hidden call to eval.

And in fact I did foresee the consequences. I never predicted this *exact*
vulnerability, of course, but I did say that disguising a call to eval
inside something which looks like a string would lead to trouble. I was
poo-pooed for that idea, so please excuse me if I gloat a little when the
first "trouble" is discovered before the feature is even available in a
production release.

I don't say this as if it were an amazing feat of prediction. I'm astonished
that apparently others can't, or won't, see it. Its like when people store
weed killer or some other poison in a soft-drink bottle, complete with the
label still on, and then are surprised when someone gets poisoned.

http://www.dailymail.co.uk/news/article-1337101/Father-Phillip-Ward-dies-accidentally-drinking-weedkiller-Lucozade-bottle.html

(Not the first, or last, case of accidental poisoning from herbicide or
pesticide stored inappropriately.)



-- 
Steve
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: The Case Against Python 3

2016-11-28 Thread Paul Rubin
Gregory Ewing  writes:
> I agree that f-strings are not to blame here. If we really want to
> avoid breaking anyone's ill-conceived attempts at sandboxing eval,
> we'd better not add anything more to the language, ever, because
> nobody can foresee all the possible consequences.

I'm surprised eval was used like that.  It seems ill-advised.  Something
similar happened with pickles some time back.  Oh my, now I'm reminded
at how old we've all gotten:

"Using eval this way is like storing a vat of cyanide in your
child's bedroom.  Sure, maybe if you check the seals and locks on
the vat carefully enough, you can convince yourself that your child
won't be able to get to the cyanide.  But wouldn't you feel safer
just not having the vat there at all?  That's basic
safety-consciousness.  Security consciousness works the same way.
Try to keep dangerous ingredients and attackers as far away from
each other as possible."  ( http://bugs.python.org/msg6972 )
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: The Case Against Python 3

2016-11-28 Thread Gregory Ewing

Steve D'Aprano wrote:

I daresay you are right that a sufficiently clever adversary may have found
an exploit. But there's no sign that anyone actually did find an exploit,
until f-strings made exploiting this trivial.


The person who wrote the bug report found at least one
way of exploiting it that doesn't require f-strings.

I agree that f-strings are not to blame here. If we really
want to avoid breaking anyone's ill-conceived attempts at
sandboxing eval, we'd better not add anything more to the
language, ever, because nobody can foresee all the possible
consequences.

--
Greg
--
https://mail.python.org/mailman/listinfo/python-list


Re: The Case Against Python 3

2016-11-26 Thread Nathan Ernst
You're right. Didn't look closely enough at it in my phone. Still don't
think i'd recommend this in a general solution, though. You effectively
have to white-list code snippets. Not very useful.

On Nov 26, 2016 7:51 PM, "Michael Torrie"  wrote:

> On 11/26/2016 06:26 PM, Nathan Ernst wrote:
> > Sure, what if the input used a double quote instead of single, cursory
> > glance looks like it might vulnerable.
>
> Either a single quote or a double quote would not pass the sanitizer. Or
> am I misunderstanding you?
> --
> https://mail.python.org/mailman/listinfo/python-list
>
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: The Case Against Python 3

2016-11-26 Thread Michael Torrie
On 11/26/2016 06:26 PM, Nathan Ernst wrote:
> Sure, what if the input used a double quote instead of single, cursory
> glance looks like it might vulnerable.

Either a single quote or a double quote would not pass the sanitizer. Or
am I misunderstanding you?
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: The Case Against Python 3

2016-11-26 Thread Nathan Ernst
Sure, what if the input used a double quote instead of single, cursory
glance looks like it might vulnerable.

(Not trying to be argumentative here)

On Nov 26, 2016 7:21 PM, "Steve D'Aprano" 
wrote:

> On Sun, 27 Nov 2016 11:25 am, Chris Angelico wrote:
>
> > On Sun, Nov 27, 2016 at 11:13 AM, Steve D'Aprano
> >  wrote:
> >> So-called f-strings haven't even hit the  already been implicated in a
> >> code-injection vulnerability:
> >>
> >> http://bugs.python.org/issue28563
> >>
> >> I feel kind of vindicated here, because when so-called f-strings were
> >> first proposed I asked about the security implication of another way of
> >> evaluating arbitrary expressions, and I was told that there were no
> >> security implications. Technically that might be true in the sense that
> >> f-strings don't do anything that wasn't already possible, but as the
> >> above bug shows, they can make exploiting code injection trivially easy
> >> in cases where they were previously diabolically hard.
> >
> > Given that the exploit exists in 2.7, I would say f-strings didn't
> > create this, eval did.
>
> I never said that f-strings caused the vulnerability. I choose my words
> carefully. As I said when I mentioned this issue three weeks ago, the
> underlying cause of the vulnerability is the use of eval on an untrusted
> string. But the existence of a theoretical vulnerability is not the same as
> an exploit, let alone an easy exploit.
>
>
> > The problem is that you absolutely CANNOT
> > "sanitize" something before giving it to eval.
>
> Be careful about making absolute claims. I challenge you to break this use
> of eval:
>
> def calculate(phrase):
> try:
> phrase = sanitize(phrase)
> except ValueError:
> return
> return eval(phrase, {'x': 20})
>
>
> def sanitize(phrase):
> phrase = phrase.replace(' ', '')
> if phrase in ('x+1', '2*x'):
> return phrase
> raise ValueError('unsafe phrase')
>
>
> For a more practical example, namedtuple uses exec to dynamically build the
> class. Can you find a code injection attack in namedtuple? I doubt it. Not
> all uses of exec or eval lead to a code injection vulnerability.
>
>
> > An f-string slips past the sanitizer, but so do other things.
>
> I daresay you are right that a sufficiently clever adversary may have found
> an exploit. But there's no sign that anyone actually did find an exploit,
> until f-strings made exploiting this trivial.
>
>
>
>
>
> --
> Steve
> “Cheer up,” they said, “things could be worse.” So I cheered up, and sure
> enough, things got worse.
>
> --
> https://mail.python.org/mailman/listinfo/python-list
>
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: The Case Against Python 3

2016-11-26 Thread Steve D'Aprano
On Sun, 27 Nov 2016 11:25 am, Chris Angelico wrote:

> On Sun, Nov 27, 2016 at 11:13 AM, Steve D'Aprano
>  wrote:
>> So-called f-strings haven't even hit the  already been implicated in a
>> code-injection vulnerability:
>>
>> http://bugs.python.org/issue28563
>>
>> I feel kind of vindicated here, because when so-called f-strings were
>> first proposed I asked about the security implication of another way of
>> evaluating arbitrary expressions, and I was told that there were no
>> security implications. Technically that might be true in the sense that
>> f-strings don't do anything that wasn't already possible, but as the
>> above bug shows, they can make exploiting code injection trivially easy
>> in cases where they were previously diabolically hard.
> 
> Given that the exploit exists in 2.7, I would say f-strings didn't
> create this, eval did. 

I never said that f-strings caused the vulnerability. I choose my words
carefully. As I said when I mentioned this issue three weeks ago, the
underlying cause of the vulnerability is the use of eval on an untrusted
string. But the existence of a theoretical vulnerability is not the same as
an exploit, let alone an easy exploit.


> The problem is that you absolutely CANNOT 
> "sanitize" something before giving it to eval.

Be careful about making absolute claims. I challenge you to break this use
of eval:

def calculate(phrase):
try:
phrase = sanitize(phrase)
except ValueError:
return
return eval(phrase, {'x': 20})


def sanitize(phrase):
phrase = phrase.replace(' ', '')
if phrase in ('x+1', '2*x'):
return phrase
raise ValueError('unsafe phrase')


For a more practical example, namedtuple uses exec to dynamically build the
class. Can you find a code injection attack in namedtuple? I doubt it. Not
all uses of exec or eval lead to a code injection vulnerability.


> An f-string slips past the sanitizer, but so do other things.

I daresay you are right that a sufficiently clever adversary may have found
an exploit. But there's no sign that anyone actually did find an exploit,
until f-strings made exploiting this trivial.





-- 
Steve
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: The Case Against Python 3

2016-11-26 Thread Chris Angelico
On Sun, Nov 27, 2016 at 11:13 AM, Steve D'Aprano
 wrote:
> So-called f-strings haven't even hit the  already been implicated in a
> code-injection vulnerability:
>
> http://bugs.python.org/issue28563
>
> I feel kind of vindicated here, because when so-called f-strings were first
> proposed I asked about the security implication of another way of
> evaluating arbitrary expressions, and I was told that there were no
> security implications. Technically that might be true in the sense that
> f-strings don't do anything that wasn't already possible, but as the above
> bug shows, they can make exploiting code injection trivially easy in cases
> where they were previously diabolically hard.

Given that the exploit exists in 2.7, I would say f-strings didn't
create this, eval did. The problem is that you absolutely CANNOT
"sanitize" something before giving it to eval. An f-string slips past
the sanitizer, but so do other things.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: The Case Against Python 3

2016-11-26 Thread Steve D'Aprano
On Sat, 26 Nov 2016 07:01 pm, Ian Kelly wrote:

> When I read that Python 3.6 would include f-strings, I turned to the
> coworker sitting next to me and said, "Oh my god, Python is adding yet
> another new syntax for string formatting." It's getting to be a joke.

f-strings are not merely string formatting. They are a new syntax for
evaluating arbitrary Python expressions, which then gets inserted into a
string.

In some ways, they're like the old Python 2 backtick syntax:

py> `1 + len(str(5**4))`
'4'


except that you can automagically concatenate strings to the evaluated
expressions.

So-called f-strings haven't even hit the  already been implicated in a
code-injection vulnerability:

http://bugs.python.org/issue28563

I feel kind of vindicated here, because when so-called f-strings were first
proposed I asked about the security implication of another way of
evaluating arbitrary expressions, and I was told that there were no
security implications. Technically that might be true in the sense that
f-strings don't do anything that wasn't already possible, but as the above
bug shows, they can make exploiting code injection trivially easy in cases
where they were previously diabolically hard.

Yay for progress.


-- 
Steve
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: The Case Against Python 3

2016-11-26 Thread Tim Chase
On 2016-11-26 01:01, Ian Kelly wrote:
> When I read that Python 3.6 would include f-strings, I turned to the
> coworker sitting next to me and said, "Oh my god, Python is adding
> yet another new syntax for string formatting." It's getting to be a
> joke.

Pretty soon Python will have one string-formatting syntax for every
Python web framework. ;-)

-tkc


-- 
https://mail.python.org/mailman/listinfo/python-list


Re: The Case Against Python 3

2016-11-26 Thread Ian Kelly
On Fri, Nov 25, 2016 at 1:29 AM, Mark Summerfield  wrote:
> The article has a section called:
>
> "Too Many Formatting Options"
>
> He's right! The % formatting was kept to help port old code, the new 
> .format() which is far more versatile is a bit verbose, so finally they've 
> settled on f-strings. So, you do need to know that all three exist (e.g., for 
> maintaining code), but you can easily choose the style that you prefer and 
> just use that.

Largely tangential, but don't you mean "all four"? PEP-292 template
strings are also still around, though I don't recall that I've ever
seen them used in the wild.

When I read that Python 3.6 would include f-strings, I turned to the
coworker sitting next to me and said, "Oh my god, Python is adding yet
another new syntax for string formatting." It's getting to be a joke.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: The Case Against Python 3

2016-11-25 Thread Gregory Ewing

Chris Angelico wrote:

but brace-formatting lets you reorder the parameters, so it has
flexibility that can be important for i18n.


Actually, Python's version of %-formatting lets you reorder
the parameters as well. The brace syntax for this is easier
to read and write, though, so probably better for i18n files.

--
Greg
--
https://mail.python.org/mailman/listinfo/python-list


Re: The Case Against Python 3

2016-11-25 Thread Chris Warrick
On 25 November 2016 at 12:11, Fabien  wrote:
> I'd be interested to read what the community thinks about the fact that his
> book (learn the hard way) is extremely influential among beginners, and what
> tools do we have to avoid that beginners stumble across such opinions in
> their very first steps with python...

His book is slowly on the way out. #python on freenode and /r/python
stopped recommending the book. Other places should follow suit, and
actively discourage an outdated (easy_install, distribute, nosetests,
python 2) book written by an asshole and a xenophobe.

-- 
Chris Warrick 
PGP: 5EAAEA16
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: The Case Against Python 3

2016-11-25 Thread Fabien

On 11/25/2016 09:29 AM, Mark Summerfield wrote:

On Thursday, November 24, 2016 at 7:35:03 PM UTC, bream...@gmail.com wrote:

> It's all here https://learnpythonthehardway.org/book/nopython3.html

I think the article is full of factual errors and is at best misleading

> and at worst downright dishonest in its criticisms of Python 3.

> (snipped answers)

Thanks for your answers, which concur well with the post that Mark 
Lawrence linked earlier 
(https://eev.ee/blog/2016/11/23/a-rebuttal-for-python-3/ ).


I'd be interested to read what the community thinks about the fact that 
his book (learn the hard way) is extremely influential among beginners, 
and what tools do we have to avoid that beginners stumble across such 
opinions in their very first steps with python...


--
https://mail.python.org/mailman/listinfo/python-list


Re: The Case Against Python 3

2016-11-25 Thread Chris Angelico
On Fri, Nov 25, 2016 at 7:29 PM, Mark Summerfield  wrote:
> The article has a section called:
>
> "Statically Typed Strings"
>
> The title is wrong of course because Python uses dynamic typing. But his 
> chief complaint seems to be that you can't mix strings and bytes in Python 3. 
> That's a deliberate design choice that several Python core developers have 
> explained. Essentially they are saying that you can't concatenate a bunch of 
> raw bytes with a string in the same way that you can't add a set to a list -- 
> and this makes perfect sense because raw bytes could be just bytes, or they 
> could be a representation of text in which case by specifying the encoding 
> (i.e., converting them to a string) the concatenation can take place. And 
> this is in keeping with Python's core philosphy of being explicit.
>

It's worse than that. Look at his comparison of Py3 and Py2. I've
shortened them some to highlight the part I'm looking at:

x = bytes("hello", 'utf-8')
y = "hello"
def addstring(a, b):
return a + b

addstring(x, y)
# TypeError

==

def addstring(a, b):
return a + b
x = "hello"
y = bytes("hello")
addstring(x, y)
# 'hellohello'

==

He clearly does not understand the difference between bytes and text,
as has been proven earlier, but this demonstrates that he doesn't even
understand the difference between Python's data types. The first
example is trying to add a bytestring to a Unicode string; the second
is actually adding two byte strings. He could have given a demo of how
Python 2 lets you join str and unicode, but it would have spoiled his
Py2 code by putting u'hellohello' into his output, and making Py3
actually look better. Can't have that.

Then he says:
> If they're going to require beginners to struggle with the difference between 
> bytes and Unicode the least they could do is tell people what variables are 
> bytes and what variables are strings.
>

The trouble is, by the time you're adding bytes and text, you're not
looking at variables any more. You're looking at objects. I don't
think he's properly understood Python's object model.

Here, have some FUD:
> Strings are also most frequently received from an external source, such as a 
> network socket, file, or similar input. This means that Python 3's statically 
> typed strings and lack of static type safety will cause Python 3 applications 
> to crash more often and have more security problems when compared with Python 
> 2.
>

What security problems? Any evidence of that?

On the face of it, without any actual specific examples, which of
these would you expect to be more security-problem-prone: mixing data
types, or throwing exceptions? In a web application, an exception can
be caught at a high level, logged, and handled by kicking a 500 back
to the client. In other applications, there may be an equivalent, or
you just terminate the server (client gets disconnected) and start up
again. At worst, this means that someone can exploit the whole "crash
and restart" thing as a way to DOS you. Here, let me walk you through
some different numeric types, and you tell me which ones are equal and
which aren't - and the security implications of that:

1) 1e2 == 100 ?
2) 1e2 == "100" ?
3) "1e2" == 100 ?
4) "1e2" == "100" ?

#1 makes perfect sense. Python says, yes, this is the case. (Not all
languages will; 1e2 is a floating-point literal, 100 is an integer,
and it's conceivable to keep them separate.)

#2 is acceptable to languages with "sloppy comparison" and "strict
comparison" operators, like ECMAScript/JavaScript. The number 100 is
(non-strictly) equal to the string "100".

#3 depends on whether sloppy comparisons are done by converting to
string or converting to number. ECMAScript treats them as equal, but
I'm just as happy with that being false (actually, probably slightly
happier).

#4 makes no sense to any sane programmer [1], which must be why PHP
chose to have that one be true.

Security implications of two different hexadecimal strings comparing
equal that can't have any bearing on passwords now, can it...

Is b"hello" == u"hello" ever a security consideration? If it is, my
money is on the exception being the *more* secure option.

Straight-up false:
> The point being that character encoding detection and negotiation is a solved 
> problem.

Nope, nope it isn't. One of my hobbies is collecting movie subtitles
in various languages [2]. They generally come to me in eight-bit
encodings with no declaration. Using only internal evidence, chardet
has about a 66% hit rate at a pass mark of "readable enough that I can
figure out the language", and a much lower hit rate at "actually the
correct encoding". With better heuristics (maybe a set of rules
specifically aimed at reading subtitle files), that could probably get
as far as 100% readable and 75% correct, but it is *never* going to be
perfect, because *the input is ambiguous*.

If other languages appear to have gotten this right, it's 

Re: The Case Against Python 3

2016-11-25 Thread Mark Summerfield
On Thursday, November 24, 2016 at 7:35:03 PM UTC, bream...@gmail.com wrote:
> It's all here https://learnpythonthehardway.org/book/nopython3.html although 
> I strongly suggest that people have large piles of sedatives to hand before 
> reading the article.  Does me a favour though, i've been looking for another 
> member of my dream team for some time.
> 
> Kindest regards.
> 
> Mark Lawrence.

I think the article is full of factual errors and is at best misleading and at 
worst downright dishonest in its criticisms of Python 3. (My only serious 
complaint about Python is that it doesn't support a key-ordered dict.) Anyway, 
here are my initial responses to some of the articles "points".

The article claims:

"There is a high probability that Python 3 is such a failure it will kill 
Python."

This is despite the fact that there are more Python programmers than ever 
before, that there is more investment in Python programming, tools, and 
libraries than ever before, and that more and more new projects start out as 
Python 3 only.

The article says:

"Also, it's been over a decade, maybe even multiple decades, and Python 3 
still isn't above about 30% in adoption."

Python 3.0 was released in 2008, so it hasn't been a single decade. According 
to an analysis of PyPI downloads, Python 2-only packages have steadily declined 
in the past 5 years with Python 3-only packages steadily rising and about to 
overtake, and with a steady rise in packages that support both:
https://blogs.msdn.microsoft.com/pythonengineering/2016/03/08/python-3-is-winning/
The Python 3 Readiness web site:
http://py3readiness.org/
shows that today, 341 out of 360 of Python's most popular packages are Python 3 
compatible.

The article says:

"The fact that you can't run Python 2 and Python 3 at the same time"

This is untrue. Most Linux distributions not only ship with Python 2 and Python 
3, but often end up with both installed. Modern versions of Fedora and Ubuntu 
depend on Python 3, but allow Python 2 to be installed side-by-side to support 
older software. On Windows it is easy to install both Python 2 and Python 3 and 
the py.exe that comes with Python 3 will detect which Python version is 
required and use it, if it is installed.

The article says:

"Every time you attempt to deal with characters in your programs you'll 
have to understand the difference between byte sequences and Unicode strings."

If you are doing low-level networking or other low-level programming dealing 
with raw bytes this is true. But for application programming you just put your 
strings in quotes and they work fine. And if you're in a non-English 
environment, you still just put your strings in quotes and they still work 
fine. But in Python 2, for non-English environments you need to add an encoding 
comment at the top of each file and you may have to use Unicode escapes.

Working with strings in Python 3 is easier than in Python 2 since you always 
know they are Unicode whereas in Python 2 they can be in any 8-bit encoding 
depending on the encoding comment, the environment, or where they came from.

And working with raw bytes is easier in Python 3 because of the bytes and 
bytearray objects which are optimized for use with bytes rather than Python 2's 
jack of all trades str type.

The article has a section called:

"Core Libraries Not Updated"

All of Python's core libraries were updated for Python 3, and further updating 
is an ongoing process. In general, if you have a library that can work with 
bytes or strings, the library will accept either and return the same type. So, 
for example, if you use the regex library, re, and give it a bytes object, any 
matches will be bytes objects, but if you give it string, any matches will be 
strings.

The article has a section called:

"Python 3 Is Not Turing Complete"

This would be laughable if it wasn't being said straight. He claims that 
"Currently you cannot run Python 2 inside the Python 3 virtual machine." and 
that this 'proves' that Python 3 isn't Turing complete.

It is true that you can't run Python 2 code in a Python 3 interpreter (unless 
you use six), but that says nothing about whether Python 3 is Turing complete 
or not. Turing completeness depends on whether a language supports certain 
computational features, such as branching and unbounded looping, and Python 3 
(and Python 2) have all the necessary features.

What he doesn't seem to understand is that Python 3 (or any other Turing 
complete language), can be used to _write an interepreter_ for any other 
language. So, a Python 2 interpreter could be written in Python 3, but no one 
has done so because there's no point when it is far easier to port Python 2 to 
Python 3, especially since Python 2 support will cease in a few years time.

The article has a section called:

"Purposefully Crippled 2to3 Translator"

This section is incredibly insulting to the Python developers. The reason that 
2to3 is imperfect is