1313import tempfile
1414import urllib .request
1515from collections import OrderedDict
16+ from collections .abc import Iterator
1617from contextlib import suppress
18+ from typing import Any , TextIO
1719
1820try :
1921 import requirements
9799 from tomllib import load as toml_load
98100 except ModuleNotFoundError :
99101 try :
100- from tomli import load as toml_load
102+ from tomli import load as toml_load # type: ignore
101103 except ModuleNotFoundError :
102104 sys .exit ('tomli modules is not installed. Run "pip install tomli"' )
103105
@@ -116,7 +118,7 @@ def get_pypi_url(name: str, filename: str) -> str:
116118 for release in body ["releases" ].values ():
117119 for source in release :
118120 if source ["filename" ] == filename :
119- return source ["url" ]
121+ return str ( source ["url" ])
120122 raise Exception (f"Failed to extract url from { url } " )
121123
122124
@@ -127,7 +129,7 @@ def get_tar_package_url_pypi(name: str, version: str) -> str:
127129 for ext in ["bz2" , "gz" , "xz" , "zip" , "none-any.whl" ]:
128130 for source in body ["urls" ]:
129131 if source ["url" ].endswith (ext ):
130- return source ["url" ]
132+ return str ( source ["url" ])
131133 err = f"Failed to get { name } -{ version } source from { url } "
132134 raise Exception (err )
133135
@@ -184,7 +186,7 @@ def download_tar_pypi(url: str, tempdir: str) -> None:
184186 shutil .copyfileobj (response , tar_file )
185187
186188
187- def parse_continuation_lines (fin ) :
189+ def parse_continuation_lines (fin : TextIO ) -> Iterator [ str ] :
188190 for raw_line in fin :
189191 line = raw_line .rstrip ("\n " )
190192 while line .endswith ("\\ " ):
@@ -209,8 +211,8 @@ def fprint(string: str) -> None:
209211if opts .requirements_file :
210212 requirements_file_input = os .path .expanduser (opts .requirements_file )
211213 try :
212- with open (requirements_file_input ) as req_file :
213- reqs = parse_continuation_lines (req_file )
214+ with open (requirements_file_input ) as in_req_file :
215+ reqs = parse_continuation_lines (in_req_file )
214216 reqs_as_str = "\n " .join ([r .split ("--hash" )[0 ] for r in reqs ])
215217 reqs_list_raw = reqs_as_str .splitlines ()
216218 py_version_regex = re .compile (
@@ -224,9 +226,9 @@ def fprint(string: str) -> None:
224226 packages = list (requirements .parse (reqs_new ))
225227 with tempfile .NamedTemporaryFile (
226228 "w" , delete = False , prefix = "requirements."
227- ) as req_file :
228- req_file .write (reqs_new )
229- requirements_file_output = req_file .name
229+ ) as temp_req_file :
230+ temp_req_file .write (reqs_new )
231+ requirements_file_output = temp_req_file .name
230232 except FileNotFoundError as err :
231233 print (err )
232234 sys .exit (1 )
@@ -265,8 +267,8 @@ def fprint(string: str) -> None:
265267 )
266268 sys .exit (0 )
267269
268- with open (requirements_file_output ) as req_file :
269- use_hash = "--hash=" in req_file .read ()
270+ with open (requirements_file_output ) as in_req_file :
271+ use_hash = "--hash=" in in_req_file .read ()
270272
271273python_version = "2" if opts .python2 else "3"
272274pip_executable = "pip2" if opts .python2 else "pip3"
@@ -307,8 +309,8 @@ def fprint(string: str) -> None:
307309else :
308310 output_filename = os .path .join (output_path , output_package ) + ".json"
309311
310- modules = []
311- vcs_modules = []
312+ modules : list [ dict [ str , str | list [ str ] | list [ dict [ str , Any ]]]] = []
313+ vcs_modules : list [ dict [ str , str | list [ str ] | list [ dict [ str , Any ]]]] = []
312314sources = {}
313315
314316unresolved_dependencies_errors = []
@@ -361,7 +363,7 @@ def fprint(string: str) -> None:
361363 with suppress (FileNotFoundError ):
362364 os .remove (os .path .join (tempdir , filename ))
363365
364- files = {get_package_name (f ): [] for f in os .listdir (tempdir )}
366+ files : dict [ str , list [ str ]] = {get_package_name (f ): [] for f in os .listdir (tempdir )}
365367
366368 for filename in os .listdir (tempdir ):
367369 name = get_package_name (filename )
@@ -371,52 +373,59 @@ def fprint(string: str) -> None:
371373 for name , files_list in files .items ():
372374 if len (files_list ) > 1 :
373375 zip_source = False
374- for f in files [name ]:
375- if f .endswith (".zip" ):
376+ for fname in files [name ]:
377+ if fname .endswith (".zip" ):
376378 zip_source = True
377379 if zip_source :
378- for f in files [name ]:
379- if not f .endswith (".zip" ):
380+ for fname in files [name ]:
381+ if not fname .endswith (".zip" ):
380382 with suppress (FileNotFoundError ):
381- os .remove (os .path .join (tempdir , f ))
383+ os .remove (os .path .join (tempdir , fname ))
382384
383- vcs_packages = {
384- x .name : {"vcs" : x .vcs , "revision" : x .revision , "uri" : x .uri }
385+ vcs_packages : dict [ str , dict [ str , str | None ]] = {
386+ str ( x .name ) : {"vcs" : x .vcs , "revision" : x .revision , "uri" : x .uri }
385387 for x in packages
386- if x .vcs
388+ if x .vcs and x . name
387389 }
388390
389391 fprint ("Obtaining hashes and urls" )
390392 for filename in os .listdir (tempdir ):
393+ source : OrderedDict [str , str | dict [str , str ]] = OrderedDict ()
391394 name = get_package_name (filename )
392395 sha256 = get_file_hash (os .path .join (tempdir , filename ))
393396 is_pypi = False
394397
395398 if name in vcs_packages :
396399 uri = vcs_packages [name ]["uri" ]
400+ if not uri :
401+ raise ValueError (f"Missing URI for VCS package: { name } " )
397402 revision = vcs_packages [name ]["revision" ]
398403 vcs = vcs_packages [name ]["vcs" ]
404+ if not vcs :
405+ raise ValueError (
406+ f"Unable to determine VCS type for VCS package: { name } "
407+ )
399408 url = "https://" + uri .split ("://" , 1 )[1 ]
400409 s = "commit"
401410 if vcs == "svn" :
402411 s = "revision"
403- source = OrderedDict (
404- [
405- ("type" , vcs ),
406- ("url" , url ),
407- (s , revision ),
408- ]
409- )
412+ source ["type" ] = vcs
413+ source ["url" ] = url
414+ if revision :
415+ source [s ] = revision
410416 is_vcs = True
411417 else :
412418 name = name .casefold ()
413419 is_pypi = True
414420 url = get_pypi_url (name , filename )
415- source = OrderedDict ([("type" , "file" ), ("url" , url ), ("sha256" , sha256 )])
421+ source ["type" ] = "file"
422+ source ["url" ] = url
423+ source ["sha256" ] = sha256
416424 if opts .checker_data :
417- source [ "x-checker-data" ] = {"type" : "pypi" , "name" : name }
425+ checker_data = {"type" : "pypi" , "name" : name }
418426 if url .endswith (".whl" ):
419- source ["x-checker-data" ]["packagetype" ] = "bdist_wheel"
427+ checker_data ["packagetype" ] = "bdist_wheel"
428+ source ["x-checker-data" ] = checker_data
420429 is_vcs = False
421430 sources [name ] = {"source" : source , "vcs" : is_vcs , "pypi" : is_pypi }
422431
@@ -579,10 +588,14 @@ def fprint(string: str) -> None:
579588 if opts .yaml :
580589
581590 class OrderedDumper (yaml .Dumper ):
582- def increase_indent (self , flow = False , indentless = False ):
583- return super ().increase_indent (flow , False )
584-
585- def dict_representer (dumper , data ):
591+ def increase_indent (
592+ self , flow : bool = False , indentless : bool = False
593+ ) -> None :
594+ return super ().increase_indent (flow , indentless )
595+
596+ def dict_representer (
597+ dumper : yaml .Dumper , data : OrderedDict [str , Any ]
598+ ) -> yaml .nodes .MappingNode :
586599 return dumper .represent_dict (data .items ())
587600
588601 OrderedDumper .add_representer (OrderedDict , dict_representer )
0 commit comments