sync to Atlas repo
This commit is contained in:
parent
2f495627fb
commit
b38e6fc5f2
@ -1,8 +1,13 @@
|
||||
"""StrKeyDict always converts non-string keys to `str`
|
||||
|
||||
Test for initializer: keys are converted to `str`.
|
||||
|
||||
>>> d = StrKeyDict([(2, 'two'), ('4', 'four')])
|
||||
>>> sorted(d.keys())
|
||||
['2', '4']
|
||||
|
||||
Tests for item retrieval using `d[key]` notation::
|
||||
|
||||
>>> d = StrKeyDict([('2', 'two'), ('4', 'four')])
|
||||
>>> d['2']
|
||||
'two'
|
||||
>>> d[4]
|
||||
@ -12,6 +17,15 @@ Tests for item retrieval using `d[key]` notation::
|
||||
...
|
||||
KeyError: '1'
|
||||
|
||||
Tests for item retrieval using `d.get(key)` notation::
|
||||
|
||||
>>> d.get('2')
|
||||
'two'
|
||||
>>> d.get(4)
|
||||
'four'
|
||||
>>> d.get(1, 'N/A')
|
||||
'N/A'
|
||||
|
||||
Tests for the `in` operator::
|
||||
|
||||
>>> 2 in d
|
||||
|
@ -14,6 +14,16 @@ Tests for item retrieval using `d[key]` notation::
|
||||
...
|
||||
KeyError: '1'
|
||||
|
||||
Tests for item retrieval using `d.get(key)` notation::
|
||||
|
||||
>>> d.get('2')
|
||||
'two'
|
||||
>>> d.get(4)
|
||||
'four'
|
||||
>>> d.get(1, 'N/A')
|
||||
'N/A'
|
||||
|
||||
|
||||
Tests for the `in` operator::
|
||||
|
||||
>>> 2 in d
|
||||
@ -24,8 +34,8 @@ Tests for the `in` operator::
|
||||
# END STRKEYDICT0_TESTS
|
||||
"""
|
||||
|
||||
# BEGIN STRKEYDICT0
|
||||
|
||||
# BEGIN STRKEYDICT0
|
||||
class StrKeyDict0(dict): # <1>
|
||||
|
||||
def __missing__(self, key):
|
||||
@ -33,7 +43,13 @@ class StrKeyDict0(dict): # <1>
|
||||
raise KeyError(key)
|
||||
return self[str(key)] # <3>
|
||||
|
||||
def __contains__(self, key):
|
||||
return key in self.keys() or str(key) in self.keys() # <4>
|
||||
def get(self, key, default=None):
|
||||
try:
|
||||
return self[key] # <4>
|
||||
except KeyError:
|
||||
return default # <5>
|
||||
|
||||
# END STRKEYDICT0
|
||||
def __contains__(self, key):
|
||||
return key in self.keys() or str(key) in self.keys() # <6>
|
||||
|
||||
# END STRKEYDICT0
|
||||
|
@ -1,17 +1,12 @@
|
||||
from abc import ABC, abstractmethod
|
||||
import abc
|
||||
|
||||
class Tombola(abc.ABC): # <1>
|
||||
|
||||
class Tombola(ABC): # <1>
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self, iterable): # <2>
|
||||
"""New instance is loaded from an iterable."""
|
||||
|
||||
@abstractmethod
|
||||
def load(self, iterable):
|
||||
@abc.abstractmethod
|
||||
def load(self, iterable): # <2>
|
||||
"""Add items from an iterable."""
|
||||
|
||||
@abstractmethod
|
||||
@abc.abstractmethod
|
||||
def pick(self): # <3>
|
||||
"""Remove item at random, returning it.
|
||||
|
||||
|
@ -1,33 +1,36 @@
|
||||
import sys
|
||||
import importlib
|
||||
# BEGIN TOMBOLA_RUNNER
|
||||
import doctest
|
||||
|
||||
from tombola import Tombola
|
||||
|
||||
# modules to test
|
||||
import bingo, lotto, tombolist, drum # <1>
|
||||
|
||||
TEST_FILE = 'tombola_tests.rst'
|
||||
MODULE_NAMES = 'bingo lotto tombolist drum'.split()
|
||||
TEST_MSG = '{0:16} {1.attempted:2} tests, {1.failed:2} failed - {2}'
|
||||
|
||||
|
||||
def main(argv):
|
||||
verbose = '-v' in argv
|
||||
real_subclasses = Tombola.__subclasses__() # <2>
|
||||
virtual_subclasses = list(Tombola._abc_registry) # <3>
|
||||
|
||||
for cls in real_subclasses + virtual_subclasses: # <4>
|
||||
test(cls, verbose)
|
||||
|
||||
|
||||
def test(cls, verbose=False):
|
||||
|
||||
res = doctest.testfile(TEST_FILE,
|
||||
globs={'TombolaUnderTest': cls},
|
||||
verbose=verbose,
|
||||
optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)
|
||||
res = doctest.testfile(
|
||||
TEST_FILE,
|
||||
globs={'ConcreteTombola': cls}, # <5>
|
||||
verbose=verbose,
|
||||
optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)
|
||||
tag = 'FAIL' if res.failed else 'OK'
|
||||
print(TEST_MSG.format(cls.__name__, res, tag))
|
||||
print(TEST_MSG.format(cls.__name__, res, tag)) # <6>
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
for name in MODULE_NAMES: # import modules to test, by name
|
||||
importlib.import_module(name)
|
||||
|
||||
verbose = '-v' in sys.argv
|
||||
|
||||
real_subclasses = Tombola.__subclasses__()
|
||||
virtual_subclasses = list(Tombola._abc_registry)
|
||||
|
||||
for cls in real_subclasses + virtual_subclasses:
|
||||
test(cls, verbose)
|
||||
import sys
|
||||
main(sys.argv)
|
||||
# END TOMBOLA_RUNNER
|
||||
|
@ -8,7 +8,7 @@ Every concrete subclass of Tombola should pass these tests.
|
||||
Create and load instance from iterable::
|
||||
|
||||
>>> balls = list(range(3))
|
||||
>>> globe = TombolaUnderTest(balls)
|
||||
>>> globe = ConcreteTombola(balls)
|
||||
>>> globe.loaded()
|
||||
True
|
||||
|
||||
@ -42,7 +42,7 @@ Reload::
|
||||
Check that `LookupError` (or a subclass) is the exception
|
||||
thrown when the device is empty::
|
||||
|
||||
>>> globe = TombolaUnderTest([])
|
||||
>>> globe = ConcreteTombola([])
|
||||
>>> try:
|
||||
... globe.pick()
|
||||
... except LookupError as exc:
|
||||
@ -53,7 +53,7 @@ thrown when the device is empty::
|
||||
Load and pick 100 balls to verify that they are all come out::
|
||||
|
||||
>>> balls = list(range(100))
|
||||
>>> globe = TombolaUnderTest(balls)
|
||||
>>> globe = ConcreteTombola(balls)
|
||||
>>> picks = []
|
||||
>>> while globe.loaded():
|
||||
... picks.append(globe.pick())
|
||||
@ -75,3 +75,6 @@ even if the implementation is OK. The probability of the 100
|
||||
balls coming out, by chance, in the order they were loaded is
|
||||
1/100!, or approximately 1.07e-158. It's much easier to win the
|
||||
Lotto or to become a billionaire working as a programmer.
|
||||
|
||||
THE END
|
||||
|
||||
|
@ -16,6 +16,4 @@ class TomboList(list): # <2>
|
||||
|
||||
def loaded(self): return bool(self) # <6>
|
||||
|
||||
"""
|
||||
Tombola.register(TomboList) # <- Python 3.2 or earlier
|
||||
"""
|
||||
# Tombola.register(TomboList) # <- Python 3.2 or earlier
|
||||
|
@ -12,10 +12,10 @@ class Sentence:
|
||||
|
||||
def __init__(self, text):
|
||||
self.text = text
|
||||
self.words = RE_WORD.findall(text) #<1>
|
||||
self.words = RE_WORD.findall(text) # <1>
|
||||
|
||||
def __getitem__(self, index):
|
||||
return self.words[index] #<2>
|
||||
return self.words[index] # <2>
|
||||
|
||||
def __repr__(self):
|
||||
return 'Sentence(%s)' % reprlib.repr(self.text) #<3>
|
||||
return 'Sentence(%s)' % reprlib.repr(self.text) # <3>
|
||||
|
Loading…
Reference in New Issue
Block a user