Skip to content

Commit 08b7bce

Browse files
committed
update from Atlas
1 parent 9db73c7 commit 08b7bce

File tree

12 files changed

+801
-21
lines changed

12 files changed

+801
-21
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
concurrency/flags/img/
2+
13
# Byte-compiled / optimized / DLL files
24
__pycache__/
35
*.py[cod]

attributes/exists_truthy.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import timeit
2+
3+
def exists_and_truthy_hasattr(obj, attr_name):
4+
if hasattr(obj, attr_name):
5+
return bool(getattr(obj, attr_name))
6+
else:
7+
return False
8+
9+
def exists_and_truthy_getattr(obj, attr_name):
10+
return bool(getattr(obj, attr_name, False))
11+
12+
def exists_and_truthy_tryget(obj, attr_name):
13+
try:
14+
return bool(getattr(obj, attr_name))
15+
except AttributeError:
16+
return False
17+
18+
19+
class Gizmo:
20+
def __init__(self):
21+
self.gadget = True
22+
23+
gizmo = Gizmo()
24+
25+
test_keys = 'hasattr', 'getattr', 'tryget'
26+
27+
def average(timings):
28+
sample = timings[1:-1]
29+
return sum(sample) / len(sample)
30+
31+
def do_tests():
32+
for test_key in test_keys:
33+
func_name = 'exists_and_truthy_' + test_key
34+
test = func_name + '(gizmo, "gadget")'
35+
setup = 'from __main__ import gizmo, ' + func_name
36+
elapsed = average(timeit.repeat(test, repeat=5, setup=setup))
37+
print(test_key.rjust(7), format(elapsed, '0.5f'))
38+
39+
if __name__ == '__main__':
40+
do_tests()
41+
del gizmo.gadget
42+
do_tests()
43+

attributes/hasattr.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import timeit
2+
3+
test_hasattr = """
4+
if hasattr(gizmo, 'gadget'):
5+
feature = gizmo.gadget
6+
else:
7+
feature = None
8+
"""
9+
10+
test_getattr = """
11+
feature = getattr(gizmo, 'gadget', None)
12+
"""
13+
14+
test_tryget = """
15+
try:
16+
feature = getattr(gizmo, 'gadget')
17+
except AttributeError:
18+
feature = None
19+
"""
20+
21+
22+
class Gizmo:
23+
def __init__(self):
24+
self.gadget = True
25+
26+
gizmo = Gizmo()
27+
28+
test_keys = 'hasattr', 'getattr', 'tryget'
29+
30+
31+
def test():
32+
for test_key in test_keys:
33+
test_name = 'test_' + test_key
34+
test = globals()[test_name]
35+
setup = 'from __main__ import gizmo'
36+
t_present = min(timeit.repeat(test, setup=setup))
37+
del gizmo.gadget
38+
t_absent = min(timeit.repeat(test, setup=setup))
39+
gizmo.gadget = True
40+
print('{:7} {:.3f} {:.3f}'.format(test_key, t_present, t_absent))
41+
42+
if __name__ == '__main__':
43+
test()
44+

concurrency/flags/countryflags.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@
1616
# Vaurien
1717
VAURIEN_URL = 'http://localhost:8000/ciaflags/{gec}.gif'
1818

19-
BASE_URL = VAURIEN_URL
19+
SOURCE_URLS = {
20+
'CIA' : CIA_URL,
21+
'NGINX' : NGINX_URL,
22+
'VAURIEN' : VAURIEN_URL,
23+
}
2024

2125
DEST_PATH_NAME = 'img/{cc}.gif'
2226

@@ -34,8 +38,9 @@ def _load():
3438
cc2gec[iso_cc] = gec
3539

3640

37-
def flag_url(iso_cc):
38-
return BASE_URL.format(gec=cc2gec[iso_cc].lower())
41+
def flag_url(iso_cc, source='CIA'):
42+
base_url = SOURCE_URLS[source.upper()]
43+
return base_url.format(gec=cc2gec[iso_cc].lower())
3944

4045
def iso_file_name(iso_cc):
4146
return DEST_PATH_NAME.format(cc=iso_cc.lower())

concurrency/flags/getsequential.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,16 @@
55

66
times = {}
77

8-
def fetch(iso_cc):
9-
resp = requests.get(cf.flag_url(iso_cc))
8+
def fetch(iso_cc, source):
9+
resp = requests.get(cf.flag_url(iso_cc, source))
1010
if resp.status_code != 200:
1111
resp.raise_for_status()
1212
file_name = cf.iso_file_name(iso_cc)
1313
with open(file_name, 'wb') as img:
1414
written = img.write(resp.content)
1515
return written, file_name
1616

17-
def main():
17+
def main(source):
1818
pending = sorted(cf.cc2name)
1919
to_download = len(pending)
2020
downloaded = 0
@@ -23,7 +23,7 @@ def main():
2323
print('get:', iso_cc)
2424
try:
2525
times[iso_cc] = [time.time() - t0]
26-
octets, file_name = fetch(iso_cc)
26+
octets, file_name = fetch(iso_cc, source)
2727
times[iso_cc].append(time.time() - t0)
2828
downloaded += 1
2929
print('\t--> {}: {:5d} bytes'.format(file_name, octets))
@@ -36,7 +36,14 @@ def main():
3636
print('{}\t{:.6g}\t{:.6g}'.format(iso_cc, start, end))
3737

3838
if __name__ == '__main__':
39-
main()
39+
import argparse
40+
41+
source_names = ', '.join(sorted(cf.SOURCE_URLS))
42+
parser = argparse.ArgumentParser(description='Download flag images.')
43+
parser.add_argument('source', help='one of: ' + source_names)
44+
45+
args = parser.parse_args()
46+
main(args.source)
4047

4148
"""
4249
From cia.gov:
@@ -53,4 +60,4 @@ def main():
5360
real 1m40.519s
5461
user 0m1.103s
5562
sys 0m0.243s
56-
"""
63+
"""

concurrency/flags/getthreadpool.py

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@
1111

1212
times = {}
1313

14-
def main(num_threads):
14+
def main(source, num_threads):
1515
pool = futures.ThreadPoolExecutor(num_threads)
1616
pending = {}
1717
t0 = time.time()
1818
# submit all jobs
1919
for iso_cc in sorted(cf.cc2name):
2020
print('get:', iso_cc)
2121
times[iso_cc] = [time.time() - t0]
22-
job = pool.submit(fetch, iso_cc)
22+
job = pool.submit(fetch, iso_cc, source)
2323
pending[job] = iso_cc
2424
to_download = len(pending)
2525
downloaded = 0
@@ -39,18 +39,23 @@ def main(num_threads):
3939
print('{}\t{:.6g}\t{:.6g}'.format(iso_cc, start, end))
4040

4141
if __name__ == '__main__':
42-
if len(sys.argv) == 2:
43-
num_threads = int(sys.argv[1])
44-
else:
45-
num_threads = DEFAULT_NUM_THREADS
46-
main(num_threads)
42+
import argparse
43+
44+
source_names = ', '.join(sorted(cf.SOURCE_URLS))
45+
parser = argparse.ArgumentParser(description='Download flag images.')
46+
parser.add_argument('source', help='one of: ' + source_names)
47+
parser.add_argument('-t', '--threads', type=int, default=DEFAULT_NUM_THREADS,
48+
help='number of threads (default: %s)' % DEFAULT_NUM_THREADS)
49+
50+
args = parser.parse_args()
51+
main(args.source, args.threads)
4752

4853
"""
49-
From localhost nginx:
50-
real 0m1.163s
51-
user 0m1.001s
52-
sys 0m0.289s
54+
From CIA, 1 thread:
55+
real 2m0.832s
56+
user 0m4.685s
57+
sys 0m0.366s
5358
5459
5560
56-
"""
61+
"""

concurrency/flags/img.zip

2.2 MB
Binary file not shown.

metaprog/spreadsheet.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
"""
2+
Spreadsheet example adapted from Raymond Hettinger's `recipe`__
3+
4+
__ http://code.activestate.com/recipes/355045-spreadsheet/
5+
6+
Demonstration::
7+
8+
>>> from math import sin, pi
9+
>>> ss = Spreadsheet(sin=sin, pi=pi, abs=abs)
10+
>>> ss['a1'] = '-5'
11+
>>> ss['a2'] = 'a1*6'
12+
>>> ss['a3'] = 'a2*7'
13+
>>> ss['a3']
14+
-210
15+
>>> ss['b1'] = 'sin(pi/4)'
16+
>>> ss['b1'] # doctest:+ELLIPSIS
17+
0.707106781186...
18+
>>> ss.getformula('b1')
19+
'sin(pi/4)'
20+
>>> ss['c1'] = 'abs(a2)'
21+
>>> ss['c1']
22+
30
23+
>>> ss['c2'] = 'len(a2)'
24+
>>> ss['c2']
25+
Traceback (most recent call last):
26+
...
27+
NameError: name 'len' is not defined
28+
>>> ss['d1'] = '3*'
29+
>>> ss['d1']
30+
Traceback (most recent call last):
31+
...
32+
SyntaxError: unexpected EOF while parsing
33+
"""
34+
35+
36+
class Spreadsheet:
37+
38+
def __init__(self, **tools):
39+
self._cells = {}
40+
self._tools = {'__builtins__' : {}}
41+
self._tools.update(tools)
42+
43+
def __setitem__(self, key, formula):
44+
self._cells[key] = formula
45+
46+
def getformula(self, key):
47+
return self._cells[key]
48+
49+
def __getitem__(self, key):
50+
return eval(self._cells[key], self._tools, self)

metaprog/spreadsheet2.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
"""
2+
Spreadsheet example adapted from Raymond Hettinger's `recipe`__
3+
4+
__ http://code.activestate.com/recipes/355045-spreadsheet/
5+
6+
Demonstration::
7+
8+
>>> from math import sin, pi
9+
>>> ss = Spreadsheet(sin=sin, pi=pi, abs=abs)
10+
>>> ss['a1'] = '-5'
11+
>>> ss['a2'] = 'a1*6'
12+
>>> ss['a3'] = 'a2*7'
13+
>>> ss['a3']
14+
-210
15+
>>> ss['b1'] = 'sin(pi/4)'
16+
>>> ss['b1'] # doctest:+ELLIPSIS
17+
0.707106781186...
18+
>>> ss.getformula('b1')
19+
'sin(pi/4)'
20+
>>> ss['c1'] = 'abs(a2)'
21+
>>> ss['c1']
22+
30
23+
>>> ss['c2'] = 'len(a2)'
24+
>>> ss['c2']
25+
Traceback (most recent call last):
26+
...
27+
NameError: name 'len' is not defined
28+
>>> ss['d1'] = '3*'
29+
Traceback (most recent call last):
30+
...
31+
SyntaxError: unexpected EOF while parsing ['d1'] = '3*'
32+
"""
33+
34+
35+
class Spreadsheet:
36+
37+
def __init__(self, **tools):
38+
self._cells = {}
39+
self._tools = {'__builtins__' : {}}
40+
self._tools.update(tools)
41+
42+
def __setitem__(self, key, formula):
43+
try:
44+
compile(formula, '<__setitem__>', 'eval')
45+
except SyntaxError as exc:
46+
msg = '{} [{!r}] = {!r}'.format(exc.msg, key, formula)
47+
raise SyntaxError(msg)
48+
self._cells[key] = formula
49+
50+
def getformula(self, key):
51+
return self._cells[key]
52+
53+
def __getitem__(self, key):
54+
return eval(self._cells[key], self._tools, self)

0 commit comments

Comments
 (0)