99from datetime import datetime
1010from io import BytesIO
1111import ssl
12+ from typing import List , Optional , Tuple , Union
1213from urllib .parse import quote
1314from urllib .request import urlopen , Request
1415from urllib .error import HTTPError , URLError
@@ -50,7 +51,7 @@ class CacheNotExist(Exception):
5051 pass
5152
5253
53- def get_language_code (language ) :
54+ def get_language_code (language : str ) -> str :
5455 language = language .split ('.' )[0 ]
5556 if language in ['pt_PT' , 'pt_BR' , 'zh_TW' ]:
5657 return language
@@ -59,7 +60,7 @@ def get_language_code(language):
5960 return language .split ('_' )[0 ]
6061
6162
62- def get_default_language ():
63+ def get_default_language () -> str :
6364 default_lang = get_language_code (
6465 os .environ .get (
6566 'LANG' ,
@@ -73,22 +74,22 @@ def get_default_language():
7374 return default_lang
7475
7576
76- def get_cache_dir ():
77+ def get_cache_dir () -> str :
7778 if not os .environ .get ('XDG_CACHE_HOME' , False ):
7879 if not os .environ .get ('HOME' , False ):
7980 return os .path .join (os .path .expanduser ("~" ), ".cache" , "tldr" )
8081 return os .path .join (os .environ .get ('HOME' ), '.cache' , 'tldr' )
8182 return os .path .join (os .environ .get ('XDG_CACHE_HOME' ), 'tldr' )
8283
8384
84- def get_cache_file_path (command , platform , language ) :
85+ def get_cache_file_path (command : str , platform : str , language : str ) -> str :
8586 pages_dir = "pages"
8687 if language and language != 'en' :
8788 pages_dir += "." + language
8889 return os .path .join (get_cache_dir (), pages_dir , platform , command ) + ".md"
8990
9091
91- def load_page_from_cache (command , platform , language ) :
92+ def load_page_from_cache (command : str , platform : str , language : str ) -> Optional [ str ] :
9293 try :
9394 with open (get_cache_file_path (
9495 command ,
@@ -101,7 +102,12 @@ def load_page_from_cache(command, platform, language):
101102 pass
102103
103104
104- def store_page_to_cache (page , command , platform , language ):
105+ def store_page_to_cache (
106+ page : str ,
107+ command : str ,
108+ platform : str ,
109+ language : str
110+ ) -> Optional [str ]:
105111 try :
106112 cache_file_path = get_cache_file_path (command , platform , language )
107113 os .makedirs (os .path .dirname (cache_file_path ), exist_ok = True )
@@ -111,7 +117,7 @@ def store_page_to_cache(page, command, platform, language):
111117 pass
112118
113119
114- def have_recent_cache (command , platform , language ) :
120+ def have_recent_cache (command : str , platform : str , language : str ) -> bool :
115121 try :
116122 cache_file_path = get_cache_file_path (command , platform , language )
117123 last_modified = datetime .fromtimestamp (os .path .getmtime (cache_file_path ))
@@ -121,7 +127,7 @@ def have_recent_cache(command, platform, language):
121127 return False
122128
123129
124- def get_page_url (command , platform , remote , language ) :
130+ def get_page_url (command : str , platform : str , remote : str , language : str ) -> str :
125131 if remote is None :
126132 remote = PAGES_SOURCE_LOCATION
127133
@@ -133,7 +139,13 @@ def get_page_url(command, platform, remote, language):
133139 return remote + language + "/" + platform + "/" + quote (command ) + ".md"
134140
135141
136- def get_page_for_platform (command , platform , remote , language , only_use_cache = False ):
142+ def get_page_for_platform (
143+ command : str ,
144+ platform : str ,
145+ remote : str ,
146+ language : str ,
147+ only_use_cache : bool = False
148+ ) -> str :
137149 data_downloaded = False
138150 if USE_CACHE and have_recent_cache (command , platform , language ):
139151 data = load_page_from_cache (command , platform , language )
@@ -159,7 +171,12 @@ def get_page_for_platform(command, platform, remote, language, only_use_cache=Fa
159171 return data .splitlines ()
160172
161173
162- def update_page_for_platform (command , platform , remote , language ):
174+ def update_page_for_platform (
175+ command : str ,
176+ platform : str ,
177+ remote : str ,
178+ language : str
179+ ) -> None :
163180 page_url = get_page_url (platform , command , remote , language )
164181 data = urlopen (
165182 Request (page_url , headers = REQUEST_HEADERS ),
@@ -168,22 +185,22 @@ def update_page_for_platform(command, platform, remote, language):
168185 store_page_to_cache (data , command , platform , language )
169186
170187
171- def get_platform ():
188+ def get_platform () -> str :
172189 for key in OS_DIRECTORIES :
173190 if sys .platform .startswith (key ):
174191 return OS_DIRECTORIES [key ]
175192 return 'linux'
176193
177194
178- def get_platform_list ():
195+ def get_platform_list () -> List [ str ] :
179196 platforms = ['common' ] + list (OS_DIRECTORIES .values ())
180197 current_platform = get_platform ()
181198 platforms .remove (current_platform )
182199 platforms .insert (0 , current_platform )
183200 return platforms
184201
185202
186- def get_language_list ():
203+ def get_language_list () -> List [ str ] :
187204 tldr_language = get_language_code (os .environ .get ('TLDR_LANGUAGE' , '' ))
188205 languages = os .environ .get ('LANGUAGE' , '' ).split (':' )
189206 languages = list (map (
@@ -209,7 +226,12 @@ def get_language_list():
209226 return languages
210227
211228
212- def get_page (command , remote = None , platforms = None , languages = None ):
229+ def get_page (
230+ command : str ,
231+ remote : Optional [str ] = None ,
232+ platforms : Optional [List [str ]] = None ,
233+ languages : Optional [List [str ]] = None
234+ ) -> Union [str , bool ]:
213235 if platforms is None :
214236 platforms = get_platform_list ()
215237 if languages is None :
@@ -275,7 +297,7 @@ def get_page(command, remote=None, platforms=None, languages=None):
275297PARAM_REGEX = re .compile (r'(?:{{)(?P<param>.+?)(?:}})' )
276298
277299
278- def get_commands (platforms = None ):
300+ def get_commands (platforms : Optional [ List [ str ]] = None ) -> List [ str ] :
279301 if platforms is None :
280302 platforms = get_platform_list ()
281303
@@ -289,7 +311,7 @@ def get_commands(platforms=None):
289311 return commands
290312
291313
292- def colors_of (key ) :
314+ def colors_of (key : str ) -> Tuple [ str , str , List [ str ]] :
293315 env_key = 'TLDR_COLOR_%s' % key .upper ()
294316 values = os .environ .get (env_key , DEFAULT_COLORS [key ]).strip ().split ()
295317 color = None
@@ -305,46 +327,44 @@ def colors_of(key):
305327 return (color , on_color , attrs )
306328
307329
308- def output (page ):
309- # Need a better fancy method?
310- if page is not None :
311- print ()
312- for line in page :
313- line = line .rstrip ().decode ('utf-8' )
314- if len (line ) == 0 :
315- continue
316- elif line [0 ] == '#' :
317- line = ' ' * LEADING_SPACES_NUM + \
318- colored (line .replace ('# ' , '' ), * colors_of ('name' )) + '\n '
319- sys .stdout .buffer .write (line .encode ('utf-8' ))
320- elif line [0 ] == '>' :
321- line = ' ' * (LEADING_SPACES_NUM - 1 ) + \
322- colored (
323- line .replace ('>' , '' ).replace ('<' , '' ),
324- * colors_of ('description' )
325- )
326- sys .stdout .buffer .write (line .encode ('utf-8' ))
327- elif line [0 ] == '-' :
328- line = '\n ' + ' ' * LEADING_SPACES_NUM + \
329- colored (line , * colors_of ('example' ))
330- sys .stdout .buffer .write (line .encode ('utf-8' ))
331- elif line [0 ] == '`' :
332- line = line [1 :- 1 ] # need to actually parse ``
333- elements = [' ' * 2 * LEADING_SPACES_NUM ]
334- for item in COMMAND_SPLIT_REGEX .split (line ):
335- item , replaced = PARAM_REGEX .subn (
336- lambda x : colored (
337- x .group ('param' ), * colors_of ('parameter' )),
338- item )
339- if not replaced :
340- item = colored (item , * colors_of ('command' ))
341- elements .append (item )
342- sys .stdout .buffer .write ('' .join (elements ).encode ('utf-8' ))
343- print ()
330+ def output (page : str ) -> None :
331+ print ()
332+ for line in page :
333+ line = line .rstrip ().decode ('utf-8' )
334+ if len (line ) == 0 :
335+ continue
336+ elif line [0 ] == '#' :
337+ line = ' ' * LEADING_SPACES_NUM + \
338+ colored (line .replace ('# ' , '' ), * colors_of ('name' )) + '\n '
339+ sys .stdout .buffer .write (line .encode ('utf-8' ))
340+ elif line [0 ] == '>' :
341+ line = ' ' * (LEADING_SPACES_NUM - 1 ) + \
342+ colored (
343+ line .replace ('>' , '' ).replace ('<' , '' ),
344+ * colors_of ('description' )
345+ )
346+ sys .stdout .buffer .write (line .encode ('utf-8' ))
347+ elif line [0 ] == '-' :
348+ line = '\n ' + ' ' * LEADING_SPACES_NUM + \
349+ colored (line , * colors_of ('example' ))
350+ sys .stdout .buffer .write (line .encode ('utf-8' ))
351+ elif line [0 ] == '`' :
352+ line = line [1 :- 1 ] # need to actually parse ``
353+ elements = [' ' * 2 * LEADING_SPACES_NUM ]
354+ for item in COMMAND_SPLIT_REGEX .split (line ):
355+ item , replaced = PARAM_REGEX .subn (
356+ lambda x : colored (
357+ x .group ('param' ), * colors_of ('parameter' )),
358+ item )
359+ if not replaced :
360+ item = colored (item , * colors_of ('command' ))
361+ elements .append (item )
362+ sys .stdout .buffer .write ('' .join (elements ).encode ('utf-8' ))
344363 print ()
364+ print ()
345365
346366
347- def update_cache (language = None ):
367+ def update_cache (language : Optional [ List [ str ]] = None ) -> None :
348368 if language is None :
349369 tldr_language = os .environ .get ("TLDR_LANGUAGE" , get_default_language ())
350370 language = tldr_language if tldr_language else 'en'
@@ -376,7 +396,7 @@ def update_cache(language=None):
376396 sys .exit ("Error: Unable to update cache from " + DOWNLOAD_CACHE_LOCATION )
377397
378398
379- def create_parser ():
399+ def create_parser () -> ArgumentParser :
380400 parser = ArgumentParser (
381401 prog = "tldr" ,
382402 usage = "tldr command [options]" ,
@@ -449,7 +469,7 @@ def create_parser():
449469 return parser
450470
451471
452- def main ():
472+ def main () -> None :
453473 parser = create_parser ()
454474
455475 options = parser .parse_args ()
@@ -491,7 +511,7 @@ def main():
491511 sys .exit ("Error fetching from tldr: {}" .format (e ))
492512
493513
494- def cli ():
514+ def cli () -> None :
495515 try :
496516 main ()
497517 except KeyboardInterrupt :
0 commit comments