11"""Utilities for second set of flag examples.
22"""
33
4- import os
5- import time
6- import sys
7- import string
84import argparse
5+ import string
6+ import sys
7+ import time
98from collections import namedtuple , Counter
109from enum import Enum
11-
10+ from pathlib import Path
1211
1312Result = namedtuple ('Result' , 'status data' )
1413
2827}
2928DEFAULT_SERVER = 'LOCAL'
3029
31- DEST_DIR = 'downloaded/'
32- COUNTRY_CODES_FILE = 'country_codes.txt'
30+ DEST_DIR = Path ( 'downloaded' )
31+ COUNTRY_CODES_FILE = Path ( 'country_codes.txt' )
3332
3433
3534def 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 )
3936
4037
4138def initial_report (cc_list : list [str ],
@@ -44,77 +41,79 @@ def initial_report(cc_list: list[str],
4441 if len (cc_list ) <= 10 :
4542 cc_msg = ', ' .join (cc_list )
4643 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 ]} ' )
5046 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 } ' )
5248 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.' )
5550
5651
5752def final_report (cc_list : list [str ],
5853 counter : Counter [HTTPStatus ],
5954 start_time : float ) -> None :
60- elapsed = time .time () - start_time
55+ elapsed = time .perf_counter () - start_time
6156 print ('-' * 20 )
62- msg = '{} flag{} downloaded.'
6357 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.' )
6559 if counter [HTTPStatus .not_found ]:
66- print (counter [HTTPStatus .not_found ], ' not found.' )
60+ print (f' { counter [HTTPStatus .not_found ]} not found.' )
6761 if counter [HTTPStatus .error ]:
6862 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' )
7165
7266
7367def expand_cc_args (every_cc : bool ,
7468 all_cc : bool ,
7569 cc_args : list [str ],
7670 limit : int ) -> list [str ]:
7771 codes : set [str ] = set ()
78- A_Z = string .ascii_uppercase
72+ A_Z = set ( string .ascii_uppercase )
7973 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 )
8175 elif all_cc :
82- with open (COUNTRY_CODES_FILE ) as fp :
83- text = fp .read ()
76+ text = COUNTRY_CODES_FILE .read_text ()
8477 codes .update (text .split ())
8578 else :
8679 for cc in (c .upper () for c in cc_args ):
8780 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 )
8982 elif len (cc ) == 2 and all (c in A_Z for c in cc ):
9083 codes .add (cc )
9184 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.' )
9487 return sorted (codes )[:limit ]
9588
9689
9790def process_args (default_concur_req ):
9891 server_options = ', ' .join (sorted (SERVERS ))
9992 parser = argparse .ArgumentParser (
10093 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 = '*' ,
10397 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' ,
105100 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' ,
107103 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 ,
111109 default = default_concur_req ,
112110 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' ,
118117 help = 'output detailed progress info' )
119118 args = parser .parse_args ()
120119 if args .max_req < 1 :
@@ -127,8 +126,8 @@ def process_args(default_concur_req):
127126 sys .exit (1 )
128127 args .server = args .server .upper ()
129128 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 } ' )
132131 parser .print_usage ()
133132 sys .exit (1 )
134133 try :
@@ -148,8 +147,9 @@ def main(download_many, default_concur_req, max_concur_req):
148147 actual_req = min (args .max_req , max_concur_req , len (cc_list ))
149148 initial_report (cc_list , actual_req , args .server )
150149 base_url = SERVERS [args .server ]
151- t0 = time .time ()
150+ t0 = time .perf_counter ()
152151 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 ), (
154153 'some downloads are unaccounted for'
154+ )
155155 final_report (cc_list , counter , t0 )
0 commit comments