sync from Atlas

This commit is contained in:
Luciano Ramalho 2021-08-25 14:46:57 -03:00
parent b429f217d3
commit dd535abcf7
16 changed files with 51 additions and 62 deletions

View File

@ -1,9 +1,11 @@
# tag::COLUMNIZE[]
from collections.abc import Sequence
def columnize(sequence: Sequence[str], num_columns: int = 0) -> list[tuple[str, ...]]:
def columnize(
sequence: Sequence[str], num_columns: int = 0
) -> list[tuple[str, ...]]:
if num_columns == 0:
num_columns = round(len(sequence) ** .5)
num_columns = round(len(sequence) ** 0.5)
num_rows, reminder = divmod(len(sequence), num_columns)
num_rows += bool(reminder)
return [tuple(sequence[i::num_rows]) for i in range(num_rows)]
@ -11,10 +13,11 @@ def columnize(sequence: Sequence[str], num_columns: int = 0) -> list[tuple[str,
def demo() -> None:
nato = ('Alfa Bravo Charlie Delta Echo Foxtrot Golf Hotel India'
' Juliett Kilo Lima Mike November Oscar Papa Quebec Romeo'
' Sierra Tango Uniform Victor Whiskey X-ray Yankee Zulu'
).split()
nato = (
'Alfa Bravo Charlie Delta Echo Foxtrot Golf Hotel India'
' Juliett Kilo Lima Mike November Oscar Papa Quebec Romeo'
' Sierra Tango Uniform Victor Whiskey X-ray Yankee Zulu'
).split()
for row in columnize(nato, 4):
for word in row:

View File

@ -3,7 +3,7 @@ from typing import cast
def find_first_str(a: list[object]) -> str:
index = next(i for i, x in enumerate(a) if isinstance(x, str))
# We only get here if there's at least one string in a
# We only get here if there's at least one string
return cast(str, a[index])
# end::CAST[]

View File

@ -1,6 +1,3 @@
#!/usr/bin/env python3
# tag::ABS_DEMO[]
import math
from typing import NamedTuple, SupportsAbs
@ -31,4 +28,3 @@ assert is_unit(v3)
assert is_unit(v4)
print('OK')
# end::ABS_DEMO[]

View File

@ -1,5 +1,6 @@
# tag::MYMAX_TYPES[]
from typing import Protocol, Any, TypeVar, overload, Callable, Iterable, Union
from collections.abc import Callable, Iterable
from typing import Protocol, Any, TypeVar, overload, Union
class SupportsLessThan(Protocol):
def __lt__(self, other: Any) -> bool: ...

View File

@ -1,6 +1,6 @@
import json
# tag::BOOKDICT[]
from typing import TypedDict
import json
class BookDict(TypedDict):
isbn: str
@ -10,14 +10,14 @@ class BookDict(TypedDict):
# end::BOOKDICT[]
# tag::TOXML[]
AUTHOR_EL = '<AUTHOR>{}</AUTHOR>'
AUTHOR_ELEMENT = '<AUTHOR>{}</AUTHOR>'
def to_xml(book: BookDict) -> str: # <1>
elements: list[str] = [] # <2>
for key, value in book.items():
if isinstance(value, list): # <3>
elements.extend(
AUTHOR_EL.format(n) for n in value) # <4>
AUTHOR_ELEMENT.format(n) for n in value) # <4>
else:
tag = key.upper()
elements.append(f'<{tag}>{value}</{tag}>')

View File

@ -10,13 +10,13 @@ class BookDict(TypedDict):
# end::BOOKDICT[]
# tag::TOXML[]
AUTHOR_EL = '<AUTHOR>{}</AUTHOR>'
AUTHOR_ELEMENT = '<AUTHOR>{}</AUTHOR>'
def to_xml(book: BookDict) -> str: # <1>
elements: List[str] = [] # <2>
for key, value in book.items():
if isinstance(value, list): # <3>
elements.extend(AUTHOR_EL.format(n)
elements.extend(AUTHOR_ELEMENT.format(n)
for n in value)
else:
tag = key.upper()

View File

@ -46,7 +46,7 @@ Tests for __iadd__:
>>> globe += 1 # <6>
Traceback (most recent call last):
...
TypeError: right operand in += must be 'AddableBingoCage' or an iterable
TypeError: right operand in += must be 'Tombola' or an iterable
# end::ADDABLE_BINGO_IADD_DEMO[]
@ -72,9 +72,9 @@ class AddableBingoCage(BingoCage): # <1>
try:
other_iterable = iter(other) # <4>
except TypeError: # <5>
self_cls = type(self).__name__
msg = "right operand in += must be {!r} or an iterable"
raise TypeError(msg.format(self_cls))
msg = ('right operand in += must be '
"'Tombola' or an iterable")
raise TypeError(msg)
self.load(other_iterable) # <6>
return self # <7>

View File

@ -19,7 +19,7 @@ Arithmetic progression class
>>> from decimal import Decimal
>>> ap = ArithmeticProgression(0, Decimal('.1'), .3)
>>> list(ap)
[Decimal('0.0'), Decimal('0.1'), Decimal('0.2')]
[Decimal('0'), Decimal('0.1'), Decimal('0.2')]
# end::ARITPROG_CLASS_DEMO[]
"""

View File

@ -14,7 +14,7 @@ Arithmetic progression generator function::
>>> from decimal import Decimal
>>> ap = aritprog_gen(0, Decimal('.1'), .3)
>>> list(ap)
[Decimal('0.0'), Decimal('0.1'), Decimal('0.2')]
[Decimal('0'), Decimal('0.1'), Decimal('0.2')]
"""

View File

@ -1,26 +1,27 @@
# tag::COLUMNIZE[]
from typing import Sequence, Tuple, Iterator
from collections.abc import Sequence, Iterator
def columnize(sequence: Sequence[str], num_columns: int = 0) -> Iterator[Tuple[str, ...]]:
def columnize(
sequence: Sequence[str], num_columns: int = 0
) -> Iterator[tuple[str, ...]]: # <1>
if num_columns == 0:
num_columns = round(len(sequence) ** .5)
num_columns = round(len(sequence) ** 0.5)
num_rows, reminder = divmod(len(sequence), num_columns)
num_rows += bool(reminder)
return (tuple(sequence[i::num_rows]) for i in range(num_rows))
return (tuple(sequence[i::num_rows]) for i in range(num_rows)) # <2>
# end::COLUMNIZE[]
def demo() -> None:
nato = ('Alfa Bravo Charlie Delta Echo Foxtrot Golf Hotel India'
' Juliett Kilo Lima Mike November Oscar Papa Quebec Romeo'
' Sierra Tango Uniform Victor Whiskey X-ray Yankee Zulu'
).split()
nato = (
'Alfa Bravo Charlie Delta Echo Foxtrot Golf Hotel India'
' Juliett Kilo Lima Mike November Oscar Papa Quebec Romeo'
' Sierra Tango Uniform Victor Whiskey X-ray Yankee Zulu'
).split()
for row in columnize(nato, 4):
for word in row:
print(f'{word:15}', end='')
print()
if __name__ == '__main__':
demo()

View File

@ -0,0 +1,13 @@
from collections.abc import Iterator
from keyword import kwlist
from typing import TYPE_CHECKING
short_kw = (k for k in kwlist if len(k) < 5) # <1>
if TYPE_CHECKING:
reveal_type(short_kw) # <2>
long_kw: Iterator[str] = (k for k in kwlist if len(k) >= 4) # <3>
if TYPE_CHECKING: # <4>
reveal_type(long_kw)

View File

@ -9,7 +9,7 @@ def sub_tree(cls):
def display(cls):
for cls_name, level in tree(cls):
for cls_name, level in tree(cls): # <3>
indent = ' ' * 4 * level
print(f'{indent}{cls_name}')

View File

@ -1243,7 +1243,7 @@
"time_start": "2014-07-21 13:30:00",
"time_stop": "2014-07-21 17:00:00",
"venue_serial": 1451,
"description": "Metaprograming in Python is fun and profitable thanks to its rich Data Model \u2013 APIs that let you handle functions, modules and even classes as objects that you can create, inspect and modify at runtime. The Data Model also enables your own objects to support infix operators, become iterable and emulate collections. This workshop shows how, through a diverse selection of examples and exercises.",
"description": "Metaprogramming in Python is fun and profitable thanks to its rich Data Model \u2013 APIs that let you handle functions, modules and even classes as objects that you can create, inspect and modify at runtime. The Data Model also enables your own objects to support infix operators, become iterable and emulate collections. This workshop shows how, through a diverse selection of examples and exercises.",
"website_url": "http://oscon.com/oscon2014/public/schedule/detail/34107",
"speakers": [150170],
"categories": [

View File

@ -1,25 +0,0 @@
#!/usr/bin/env python3
import shelve
from schedule_v2 import DB_NAME, CONFERENCE, load_db
from schedule_v2 import DbRecord, Event
with shelve.open(DB_NAME) as db:
if CONFERENCE not in db:
load_db(db)
DbRecord.set_db(db)
event = DbRecord.fetch('event.33950')
print(event)
print(event.venue)
print(event.venue.name)
for spkr in event.speakers:
print(f'{spkr.serial}:', spkr.name)
print(repr(Event.venue))
event2 = DbRecord.fetch('event.33451')
print(event2)
print(event2.fetch)
print(event2.venue)

View File

@ -56,4 +56,4 @@ def test_event_speakers():
def test_event_no_speakers():
event = schedule.Record.fetch('event.36848')
assert event.speakers == []
assert event.speakers == []

View File

@ -1,4 +1,4 @@
# pseudo-code for object construction
# pseudocode for object construction
def make(the_class, some_arg):
new_object = the_class.__new__(some_arg)
if isinstance(new_object, the_class):