Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 21 additions & 8 deletions Doc/library/turtle.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@
**Source code:** :source:`Lib/turtle.py`

.. testsetup:: default
:skipif: _tkinter is None

from turtle import *
turtle = Turtle()

.. testcleanup::
:skipif: _tkinter is None

import os
os.remove("my_drawing.ps")
Expand Down Expand Up @@ -510,6 +512,7 @@ Turtle motion
turtle is headed. Do not change the turtle's heading.

.. doctest::
:skipif: _tkinter is None
:hide:

>>> turtle.goto(0, 0)
Expand Down Expand Up @@ -852,6 +855,7 @@ Turtle motion
last *n* stamps.

.. doctest::
:skipif: _tkinter is None

>>> for i in range(8):
... unused_stamp_id = turtle.stamp()
Expand Down Expand Up @@ -1409,8 +1413,11 @@ More drawing control
font. If *move* is true, the pen is moved to the bottom-right corner of the
text. By default, *move* is ``False``.

>>> turtle.write("Home = ", True, align="center")
>>> turtle.write((0,0), True)
.. doctest::
:skipif: _tkinter is None

>>> turtle.write("Home = ", True, align="center")
>>> turtle.write((0,0), True)


Turtle state
Expand Down Expand Up @@ -1447,12 +1454,15 @@ Visibility

Return ``True`` if the Turtle is shown, ``False`` if it's hidden.

>>> turtle.hideturtle()
>>> turtle.isvisible()
False
>>> turtle.showturtle()
>>> turtle.isvisible()
True
.. doctest::
:skipif: _tkinter is None

>>> turtle.hideturtle()
>>> turtle.isvisible()
False
>>> turtle.showturtle()
>>> turtle.isvisible()
True


Appearance
Expand Down Expand Up @@ -1983,6 +1993,9 @@ Window control
method, one can make visible those parts of a drawing which were outside the
canvas before.

.. doctest::
:skipif: _tkinter is None

>>> screen.screensize()
(400, 300)
>>> screen.screensize(2000,1500)
Expand Down
17 changes: 9 additions & 8 deletions Lib/netrc.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,12 @@ def _read_char(self):
def get_token(self):
if self.pushback:
return self.pushback.pop(0)
token = ""
token = None
fiter = iter(self._read_char, "")
for ch in fiter:
if ch in self.whitespace:
continue
token = ""
if ch == '"':
for ch in fiter:
if ch == '"':
Expand Down Expand Up @@ -96,9 +97,9 @@ def _parse(self, file, fp, default_netrc):
# Look for a machine, default, or macdef top-level keyword
saved_lineno = lexer.lineno
tt = lexer.get_token()
if not tt:
if tt is None:
break
elif tt[0] == '#':
elif tt.startswith('#'):
if lexer.lineno == saved_lineno and len(tt) == 1:
lexer.instream.readline()
continue
Expand Down Expand Up @@ -135,20 +136,20 @@ def _parse(self, file, fp, default_netrc):
while 1:
prev_lineno = lexer.lineno
tt = lexer.get_token()
if tt.startswith('#'):
if tt is not None and tt.startswith('#'):
if lexer.lineno == prev_lineno:
lexer.instream.readline()
continue
if tt in {'', 'machine', 'default', 'macdef'}:
if tt in {None, 'machine', 'default', 'macdef'}:
self.hosts[entryname] = (login, account, password)
lexer.push_token(tt)
break
elif tt == 'login' or tt == 'user':
login = lexer.get_token()
login = lexer.get_token() or ''
elif tt == 'account':
account = lexer.get_token()
account = lexer.get_token() or ''
elif tt == 'password':
password = lexer.get_token()
password = lexer.get_token() or ''
else:
raise NetrcParseError("bad follower token %r" % tt,
file, lexer.lineno)
Expand Down
15 changes: 15 additions & 0 deletions Lib/test/test_netrc.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ def test_optional_tokens(self):
"machine host.domain.com login",
"machine host.domain.com account",
"machine host.domain.com password",
"machine host.domain.com login \"\"",
"machine host.domain.com account \"\"",
"machine host.domain.com password \"\"",
"machine host.domain.com login \"\" account",
"machine host.domain.com login \"\" password",
"machine host.domain.com account \"\" password"
Expand All @@ -74,6 +77,9 @@ def test_optional_tokens(self):
"default login",
"default account",
"default password",
"default login \"\"",
"default account \"\"",
"default password \"\"",
"default login \"\" account",
"default login \"\" password",
"default account \"\" password"
Expand All @@ -82,6 +88,15 @@ def test_optional_tokens(self):
nrc = self.make_nrc(item)
self.assertEqual(nrc.hosts['default'], ('', '', ''))

def test_empty_quoted_token_is_not_eof(self):
data = (
'"" invalid',
'machine host.domain.com "" invalid',
)
for item in data:
with self.subTest(item=item):
self.assertRaises(netrc.NetrcParseError, self.make_nrc, item)

def test_invalid_tokens(self):
data = (
"invalid host.domain.com",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix :mod:`netrc` to distinguish empty quoted tokens from end-of-file, so
malformed files no longer cause the remaining content to be silently ignored.
Loading