1
1
"""Utilities for second set of flag examples.
2
2
"""
3
3
4
- import os
5
- import time
6
- import sys
7
- import string
8
4
import argparse
5
+ import string
6
+ import sys
7
+ import time
9
8
from collections import namedtuple , Counter
10
9
from enum import Enum
11
-
10
+ from pathlib import Path
12
11
13
12
Result = namedtuple ('Result' , 'status data' )
14
13
28
27
}
29
28
DEFAULT_SERVER = 'LOCAL'
30
29
31
- DEST_DIR = 'downloaded/'
32
- COUNTRY_CODES_FILE = 'country_codes.txt'
30
+ DEST_DIR = Path ( 'downloaded' )
31
+ COUNTRY_CODES_FILE = Path ( 'country_codes.txt' )
33
32
34
33
35
34
def save_flag (img : bytes , filename : str ) -> None :
36
- path = os .path .join (DEST_DIR , filename )
37
- with open (path , 'wb' ) as fp :
38
- fp .write (img )
35
+ (DEST_DIR / filename ).write_bytes (img )
39
36
40
37
41
38
def initial_report (cc_list : list [str ],
@@ -44,77 +41,79 @@ def initial_report(cc_list: list[str],
44
41
if len (cc_list ) <= 10 :
45
42
cc_msg = ', ' .join (cc_list )
46
43
else :
47
- cc_msg = 'from {} to {}' .format (cc_list [0 ], cc_list [- 1 ])
48
- print ('{} site: {}' .format (server_label , SERVERS [server_label ]))
49
- msg = 'Searching for {} flag{}: {}'
44
+ cc_msg = f'from { cc_list [0 ]} to { cc_list [- 1 ]} '
45
+ print (f'{ server_label } site: { SERVERS [server_label ]} ' )
50
46
plural = 's' if len (cc_list ) != 1 else ''
51
- print (msg . format ( len (cc_list ), plural , cc_msg ) )
47
+ print (f'Searching for { len (cc_list )} flag { plural } : { cc_msg } ' )
52
48
plural = 's' if actual_req != 1 else ''
53
- msg = '{} concurrent connection{} will be used.'
54
- print (msg .format (actual_req , plural ))
49
+ print (f'{ actual_req } concurrent connection{ plural } will be used.' )
55
50
56
51
57
52
def final_report (cc_list : list [str ],
58
53
counter : Counter [HTTPStatus ],
59
54
start_time : float ) -> None :
60
- elapsed = time .time () - start_time
55
+ elapsed = time .perf_counter () - start_time
61
56
print ('-' * 20 )
62
- msg = '{} flag{} downloaded.'
63
57
plural = 's' if counter [HTTPStatus .ok ] != 1 else ''
64
- print (msg . format ( counter [HTTPStatus .ok ], plural ) )
58
+ print (f' { counter [HTTPStatus .ok ]} flag { plural } downloaded.' )
65
59
if counter [HTTPStatus .not_found ]:
66
- print (counter [HTTPStatus .not_found ], ' not found.' )
60
+ print (f' { counter [HTTPStatus .not_found ]} not found.' )
67
61
if counter [HTTPStatus .error ]:
68
62
plural = 's' if counter [HTTPStatus .error ] != 1 else ''
69
- print ('{} error{}.' . format ( counter [HTTPStatus .error ], plural ) )
70
- print ('Elapsed time: {:.2f}s' . format ( elapsed ) )
63
+ print (f' { counter [HTTPStatus .error ]} error { plural } ' )
64
+ print (f 'Elapsed time: { elapsed :.2f} s' )
71
65
72
66
73
67
def expand_cc_args (every_cc : bool ,
74
68
all_cc : bool ,
75
69
cc_args : list [str ],
76
70
limit : int ) -> list [str ]:
77
71
codes : set [str ] = set ()
78
- A_Z = string .ascii_uppercase
72
+ A_Z = set ( string .ascii_uppercase )
79
73
if every_cc :
80
- codes .update (a + b for a in A_Z for b in A_Z )
74
+ codes .update (f' { a } { b } ' for a in A_Z for b in A_Z )
81
75
elif all_cc :
82
- with open (COUNTRY_CODES_FILE ) as fp :
83
- text = fp .read ()
76
+ text = COUNTRY_CODES_FILE .read_text ()
84
77
codes .update (text .split ())
85
78
else :
86
79
for cc in (c .upper () for c in cc_args ):
87
80
if len (cc ) == 1 and cc in A_Z :
88
- codes .update (cc + c for c in A_Z )
81
+ codes .update (cc + c for c in A_Z )
89
82
elif len (cc ) == 2 and all (c in A_Z for c in cc ):
90
83
codes .add (cc )
91
84
else :
92
- msg = ' each CC argument must be A to Z or AA to ZZ. '
93
- raise ValueError ( '*** Usage error: ' + msg )
85
+ raise ValueError ( '*** Usage error: each CC argument '
86
+ 'must be A to Z or AA to ZZ.' )
94
87
return sorted (codes )[:limit ]
95
88
96
89
97
90
def process_args (default_concur_req ):
98
91
server_options = ', ' .join (sorted (SERVERS ))
99
92
parser = argparse .ArgumentParser (
100
93
description = 'Download flags for country codes. '
101
- 'Default: top 20 countries by population.' )
102
- parser .add_argument ('cc' , metavar = 'CC' , nargs = '*' ,
94
+ 'Default: top 20 countries by population.' )
95
+ parser .add_argument (
96
+ 'cc' , metavar = 'CC' , nargs = '*' ,
103
97
help = 'country code or 1st letter (eg. B for BA...BZ)' )
104
- parser .add_argument ('-a' , '--all' , action = 'store_true' ,
98
+ parser .add_argument (
99
+ '-a' , '--all' , action = 'store_true' ,
105
100
help = 'get all available flags (AD to ZW)' )
106
- parser .add_argument ('-e' , '--every' , action = 'store_true' ,
101
+ parser .add_argument (
102
+ '-e' , '--every' , action = 'store_true' ,
107
103
help = 'get flags for every possible code (AA...ZZ)' )
108
- parser .add_argument ('-l' , '--limit' , metavar = 'N' , type = int ,
109
- help = 'limit to N first codes' , default = sys .maxsize )
110
- parser .add_argument ('-m' , '--max_req' , metavar = 'CONCURRENT' , type = int ,
104
+ parser .add_argument (
105
+ '-l' , '--limit' , metavar = 'N' , type = int , help = 'limit to N first codes' ,
106
+ default = sys .maxsize )
107
+ parser .add_argument (
108
+ '-m' , '--max_req' , metavar = 'CONCURRENT' , type = int ,
111
109
default = default_concur_req ,
112
110
help = f'maximum concurrent requests (default={ default_concur_req } )' )
113
- parser .add_argument ('-s' , '--server' , metavar = 'LABEL' ,
114
- default = DEFAULT_SERVER ,
115
- help = ('Server to hit; one of ' +
116
- f'{ server_options } (default={ DEFAULT_SERVER } )' ))
117
- parser .add_argument ('-v' , '--verbose' , action = 'store_true' ,
111
+ parser .add_argument (
112
+ '-s' , '--server' , metavar = 'LABEL' , default = DEFAULT_SERVER ,
113
+ help = f'Server to hit; one of { server_options } '
114
+ f'(default={ DEFAULT_SERVER } )' )
115
+ parser .add_argument (
116
+ '-v' , '--verbose' , action = 'store_true' ,
118
117
help = 'output detailed progress info' )
119
118
args = parser .parse_args ()
120
119
if args .max_req < 1 :
@@ -127,8 +126,8 @@ def process_args(default_concur_req):
127
126
sys .exit (1 )
128
127
args .server = args .server .upper ()
129
128
if args .server not in SERVERS :
130
- print ('*** Usage error: --server LABEL must be one of' ,
131
- server_options )
129
+ print (f '*** Usage error: --server LABEL '
130
+ f'must be one of { server_options } ' )
132
131
parser .print_usage ()
133
132
sys .exit (1 )
134
133
try :
@@ -148,8 +147,9 @@ def main(download_many, default_concur_req, max_concur_req):
148
147
actual_req = min (args .max_req , max_concur_req , len (cc_list ))
149
148
initial_report (cc_list , actual_req , args .server )
150
149
base_url = SERVERS [args .server ]
151
- t0 = time .time ()
150
+ t0 = time .perf_counter ()
152
151
counter = download_many (cc_list , base_url , args .verbose , actual_req )
153
- assert sum (counter .values ()) == len (cc_list ), \
152
+ assert sum (counter .values ()) == len (cc_list ), (
154
153
'some downloads are unaccounted for'
154
+ )
155
155
final_report (cc_list , counter , t0 )
0 commit comments