33"""
44Common classes and values used around relenv.
55"""
6+ from __future__ import annotations
7+
68import http .client
79import logging
810import os
1618import textwrap
1719import threading
1820import time
21+ from typing import Any , BinaryIO , Iterable , Mapping , Optional , Union
1922
2023# relenv package version
2124__version__ = "0.21.1"
@@ -101,22 +104,24 @@ class RelenvException(Exception):
101104 """
102105
103106
104- def format_shebang (python , tpl = SHEBANG_TPL ):
107+ def format_shebang (python : str , tpl : str = SHEBANG_TPL ) -> str :
105108 """
106109 Return a formatted shebang.
107110 """
108111 return tpl .format (python ).strip () + "\n "
109112
110113
111- def build_arch ():
114+ def build_arch () -> str :
112115 """
113116 Return the current machine.
114117 """
115118 machine = platform .machine ()
116119 return machine .lower ()
117120
118121
119- def work_root (root = None ):
122+ def work_root (
123+ root : Optional [Union [str , os .PathLike [str ]]] = None ,
124+ ) -> pathlib .Path :
120125 """
121126 Get the root directory that all other relenv working directories should be based on.
122127
@@ -133,7 +138,9 @@ def work_root(root=None):
133138 return base
134139
135140
136- def work_dir (name , root = None ):
141+ def work_dir (
142+ name : str , root : Optional [Union [str , os .PathLike [str ]]] = None
143+ ) -> pathlib .Path :
137144 """
138145 Get the absolute path to the relenv working directory of the given name.
139146
@@ -161,17 +168,17 @@ class WorkDirs:
161168 :type root: str
162169 """
163170
164- def __init__ (self , root ) :
165- self .root = root
166- self .data = DATA_DIR
167- self .toolchain_config = work_dir ("toolchain" , self .root )
168- self .toolchain = work_dir ("toolchain" , DATA_DIR )
169- self .build = work_dir ("build" , DATA_DIR )
170- self .src = work_dir ("src" , DATA_DIR )
171- self .logs = work_dir ("logs" , DATA_DIR )
172- self .download = work_dir ("download" , DATA_DIR )
171+ def __init__ (self , root : Union [ str , os . PathLike [ str ]]) -> None :
172+ self .root : pathlib . Path = pathlib . Path ( root )
173+ self .data : pathlib . Path = DATA_DIR
174+ self .toolchain_config : pathlib . Path = work_dir ("toolchain" , self .root )
175+ self .toolchain : pathlib . Path = work_dir ("toolchain" , DATA_DIR )
176+ self .build : pathlib . Path = work_dir ("build" , DATA_DIR )
177+ self .src : pathlib . Path = work_dir ("src" , DATA_DIR )
178+ self .logs : pathlib . Path = work_dir ("logs" , DATA_DIR )
179+ self .download : pathlib . Path = work_dir ("download" , DATA_DIR )
173180
174- def __getstate__ (self ):
181+ def __getstate__ (self ) -> dict [ str , pathlib . Path ] :
175182 """
176183 Return an object used for pickling.
177184
@@ -187,7 +194,7 @@ def __getstate__(self):
187194 "download" : self .download ,
188195 }
189196
190- def __setstate__ (self , state ) :
197+ def __setstate__ (self , state : Mapping [ str , pathlib . Path ]) -> None :
191198 """
192199 Unwrap the object returned from unpickling.
193200
@@ -203,7 +210,9 @@ def __setstate__(self, state):
203210 self .download = state ["download" ]
204211
205212
206- def work_dirs (root = None ):
213+ def work_dirs (
214+ root : Optional [Union [str , os .PathLike [str ]]] = None ,
215+ ) -> WorkDirs :
207216 """
208217 Returns a WorkDirs instance based on the given root.
209218
@@ -216,7 +225,10 @@ def work_dirs(root=None):
216225 return WorkDirs (work_root (root ))
217226
218227
219- def get_toolchain (arch = None , root = None ):
228+ def get_toolchain (
229+ arch : Optional [str ] = None ,
230+ root : Optional [Union [str , os .PathLike [str ]]] = None ,
231+ ) -> Optional [pathlib .Path ]:
220232 """
221233 Get a the toolchain directory, specific to the arch if supplied.
222234
@@ -250,7 +262,7 @@ def get_toolchain(arch=None, root=None):
250262 return TOOLCHAIN_PATH
251263
252264
253- def get_triplet (machine = None , plat = None ):
265+ def get_triplet (machine : Optional [ str ] = None , plat : Optional [ str ] = None ) -> str :
254266 """
255267 Get the target triplet for the specified machine and platform.
256268
@@ -280,7 +292,7 @@ def get_triplet(machine=None, plat=None):
280292 raise RelenvException (f"Unknown platform { plat } " )
281293
282294
283- def plat_from_triplet (plat ) :
295+ def plat_from_triplet (plat : str ) -> str :
284296 """
285297 Convert platform from build to the value of sys.platform.
286298 """
@@ -293,11 +305,11 @@ def plat_from_triplet(plat):
293305 raise RelenvException (f"Unkown platform { plat } " )
294306
295307
296- def list_archived_builds ():
308+ def list_archived_builds () -> list [ tuple [ str , str , str ]] :
297309 """
298310 Return a list of version, architecture and platforms for builds.
299311 """
300- builds = []
312+ builds : list [ tuple [ str , str , str ]] = []
301313 dirs = work_dirs (DATA_DIR )
302314 for root , dirs , files in os .walk (dirs .build ):
303315 for file in files :
@@ -309,7 +321,7 @@ def list_archived_builds():
309321 return builds
310322
311323
312- def archived_build (triplet = None ):
324+ def archived_build (triplet : Optional [ str ] = None ) -> pathlib . Path :
313325 """
314326 Finds a the location of an archived build.
315327
@@ -326,7 +338,9 @@ def archived_build(triplet=None):
326338 return dirs .build / archive
327339
328340
329- def extract_archive (to_dir , archive ):
341+ def extract_archive (
342+ to_dir : Union [str , os .PathLike [str ]], archive : Union [str , os .PathLike [str ]]
343+ ) -> None :
330344 """
331345 Extract an archive to a specific location.
332346
@@ -354,7 +368,7 @@ def extract_archive(to_dir, archive):
354368 t .extractall (to_dir )
355369
356370
357- def get_download_location (url , dest ) :
371+ def get_download_location (url : str , dest : Union [ str , os . PathLike [ str ]]) -> str :
358372 """
359373 Get the full path to where the url will be downloaded to.
360374
@@ -369,7 +383,7 @@ def get_download_location(url, dest):
369383 return os .path .join (dest , os .path .basename (url ))
370384
371385
372- def check_url (url , timestamp = None , timeout = 30 ):
386+ def check_url (url : str , timestamp : Optional [ float ] = None , timeout : float = 30 ) -> bool :
373387 """
374388 Check that the url returns a 200.
375389 """
@@ -400,7 +414,7 @@ def check_url(url, timestamp=None, timeout=30):
400414 return True
401415
402416
403- def fetch_url (url , fp , backoff = 3 , timeout = 30 ):
417+ def fetch_url (url : str , fp : BinaryIO , backoff : int = 3 , timeout : float = 30 ) -> None :
404418 """
405419 Fetch the contents of a url.
406420
@@ -447,7 +461,7 @@ def fetch_url(url, fp, backoff=3, timeout=30):
447461 log .info ("Download complete %s" , url )
448462
449463
450- def fetch_url_content (url , backoff = 3 , timeout = 30 ):
464+ def fetch_url_content (url : str , backoff : int = 3 , timeout : float = 30 ) -> str :
451465 """
452466 Fetch the contents of a url.
453467
@@ -503,7 +517,13 @@ def fetch_url_content(url, backoff=3, timeout=30):
503517 return fp .read ().decode ()
504518
505519
506- def download_url (url , dest , verbose = True , backoff = 3 , timeout = 60 ):
520+ def download_url (
521+ url : str ,
522+ dest : Union [str , os .PathLike [str ]],
523+ verbose : bool = True ,
524+ backoff : int = 3 ,
525+ timeout : float = 60 ,
526+ ) -> str :
507527 """
508528 Download the url to the provided destination.
509529
@@ -541,7 +561,7 @@ def download_url(url, dest, verbose=True, backoff=3, timeout=60):
541561 return local
542562
543563
544- def runcmd (* args , ** kwargs ) :
564+ def runcmd (* args : Any , ** kwargs : Any ) -> subprocess . Popen [ str ] :
545565 """
546566 Run a command.
547567
@@ -626,7 +646,11 @@ def enqueue_process(process, queue):
626646 return p
627647
628648
629- def relative_interpreter (root_dir , scripts_dir , interpreter ):
649+ def relative_interpreter (
650+ root_dir : Union [str , os .PathLike [str ]],
651+ scripts_dir : Union [str , os .PathLike [str ]],
652+ interpreter : Union [str , os .PathLike [str ]],
653+ ) -> pathlib .Path :
630654 """
631655 Return a relativized path to the given scripts_dir and interpreter.
632656 """
@@ -644,7 +668,7 @@ def relative_interpreter(root_dir, scripts_dir, interpreter):
644668 return relscripts / relinterp
645669
646670
647- def makepath (* paths ) :
671+ def makepath (* paths : Union [ str , os . PathLike [ str ]]) -> tuple [ str , str ] :
648672 """
649673 Make a normalized path name from paths.
650674 """
@@ -656,15 +680,15 @@ def makepath(*paths):
656680 return dir , os .path .normcase (dir )
657681
658682
659- def addpackage (sitedir , name ) :
683+ def addpackage (sitedir : str , name : Union [ str , os . PathLike [ str ]]) -> list [ str ] | None :
660684 """
661685 Add editable package to path.
662686 """
663687 import io
664688 import stat
665689
666690 fullname = os .path .join (sitedir , name )
667- paths = []
691+ paths : list [ str ] = []
668692 try :
669693 st = os .lstat (fullname )
670694 except OSError :
@@ -710,11 +734,11 @@ def addpackage(sitedir, name):
710734 return paths
711735
712736
713- def sanitize_sys_path (sys_path_entries ) :
737+ def sanitize_sys_path (sys_path_entries : Iterable [ str ]) -> list [ str ] :
714738 """
715739 Sanitize `sys.path` to only include paths relative to the onedir environment.
716740 """
717- __sys_path = []
741+ __sys_path : list [ str ] = []
718742 __valid_path_prefixes = tuple (
719743 {
720744 pathlib .Path (sys .prefix ).resolve (),
@@ -735,6 +759,8 @@ def sanitize_sys_path(sys_path_entries):
735759 for known_path in __sys_path [:]:
736760 for _ in pathlib .Path (known_path ).glob ("__editable__.*.pth" ):
737761 paths = addpackage (known_path , _ )
762+ if not paths :
763+ continue
738764 for p in paths :
739765 if p not in __sys_path :
740766 __sys_path .append (p )
@@ -746,11 +772,14 @@ class Version:
746772 Version comparisons.
747773 """
748774
749- def __init__ (self , data ):
750- self .major , self .minor , self .micro = self .parse_string (data )
751- self ._data = data
775+ def __init__ (self , data : str ) -> None :
776+ major , minor , micro = self .parse_string (data )
777+ self .major : int = major
778+ self .minor : Optional [int ] = minor
779+ self .micro : Optional [int ] = micro
780+ self ._data : str = data
752781
753- def __str__ (self ):
782+ def __str__ (self ) -> str :
754783 """
755784 Version as string.
756785 """
@@ -762,7 +791,7 @@ def __str__(self):
762791 # XXX What if minor was None but micro was an int.
763792 return _
764793
765- def __hash__ (self ):
794+ def __hash__ (self ) -> int :
766795 """
767796 Hash of the version.
768797
@@ -771,7 +800,7 @@ def __hash__(self):
771800 return hash ((self .major , self .minor , self .micro ))
772801
773802 @staticmethod
774- def parse_string (data ) :
803+ def parse_string (data : str ) -> tuple [ int , Optional [ int ], Optional [ int ]] :
775804 """
776805 Parse a version string into major, minor, and micro integers.
777806 """
@@ -785,7 +814,7 @@ def parse_string(data):
785814 else :
786815 raise RuntimeError ("Too many parts to parse" )
787816
788- def __eq__ (self , other ) :
817+ def __eq__ (self , other : "Version" ) -> bool :
789818 """
790819 Equality comparisons.
791820 """
@@ -797,7 +826,7 @@ def __eq__(self, other):
797826 micro = 0 if other .micro is None else other .micro
798827 return mymajor == major and myminor == minor and mymicro == micro
799828
800- def __lt__ (self , other ) :
829+ def __lt__ (self , other : "Version" ) -> bool :
801830 """
802831 Less than comparrison.
803832 """
@@ -816,7 +845,7 @@ def __lt__(self, other):
816845 return True
817846 return False
818847
819- def __le__ (self , other ) :
848+ def __le__ (self , other : "Version" ) -> bool :
820849 """
821850 Less than or equal to comparrison.
822851 """
@@ -832,13 +861,13 @@ def __le__(self, other):
832861 return True
833862 return False
834863
835- def __gt__ (self , other ) :
864+ def __gt__ (self , other : "Version" ) -> bool :
836865 """
837866 Greater than comparrison.
838867 """
839868 return not self .__le__ (other )
840869
841- def __ge__ (self , other ) :
870+ def __ge__ (self , other : "Version" ) -> bool :
842871 """
843872 Greater than or equal to comparrison.
844873 """
0 commit comments