3333
3434class _ClassNodeFound (Exception ):
3535 """Raised to short-circuit AST traversal when the target class is found."""
36+
3637 pass
3738
3839
@@ -97,9 +98,7 @@ def test_find_modules(pkg_root_path: str) -> Dict:
9798
9899 # Add current path as module name if _init.py is present
99100 if "__init__.py" in files :
100- module_name = os .path .relpath (root , pkg_root_path ).replace (
101- os .path .sep , "."
102- )
101+ module_name = os .path .relpath (root , pkg_root_path ).replace (os .path .sep , "." )
103102 modules [module_name ] = []
104103 for f in files :
105104 if f .endswith (".py" ):
@@ -179,22 +178,17 @@ def get_property_names(node: ast.AST, attribute_names: Dict) -> None:
179178 if hasattr (assign , "target" ):
180179 if hasattr (assign .target , "attr" ) and not assign .target .attr .startswith ("_" ):
181180 attr = assign .target
182- attribute_names .update ({attr .attr : {
183- "attr_type" : get_property_type (assign )
184- }})
181+ attribute_names .update ({attr .attr : {"attr_type" : get_property_type (assign )}})
185182 if hasattr (assign , "targets" ):
186183 for target in assign .targets :
187184 if hasattr (target , "attr" ) and not target .attr .startswith ("_" ):
188- attribute_names .update ({target .attr : {
189- "attr_type" : get_property_type (assign )
190- }})
185+ attribute_names .update ({target .attr : {"attr_type" : get_property_type (assign )}})
191186
192187
193188def check_base_classes (cls_node : ast .ClassDef ) -> bool :
194189 should_look = False
195190 init_node = [
196- node for node in cls_node .body
197- if isinstance (node , ast .FunctionDef ) and node .name .startswith ("__init__" )
191+ node for node in cls_node .body if isinstance (node , ast .FunctionDef ) and node .name .startswith ("__init__" )
198192 ]
199193 if init_node :
200194 if hasattr (init_node , "body" ):
@@ -231,26 +225,23 @@ def get_properties(cls: Type) -> Dict:
231225 path = inspect .getsourcefile (base_class )
232226 module = _get_parsed_module (path )
233227 except (TypeError , SyntaxError ):
234- _LOGGER .info (f"Unable to create ast of { base_class } " )
228+ _LOGGER .debug (f"Unable to create ast of { base_class } " )
235229 continue # was a built-in, e.g. "object", Exception, or a Model from msrest fails here
236230
237231 cls_node = _find_class_node (module , base_class .__name__ )
238232 if cls_node :
239233 get_property_names (cls_node , attribute_names )
240234 else :
241235 # Abstract base classes fail here, e.g. "collections.abc.MuttableMapping"
242- _LOGGER .info (f"Unable to get class node for { base_class .__name__ } . Skipping..." )
236+ _LOGGER .debug (f"Unable to get class node for { base_class .__name__ } . Skipping..." )
243237 else :
244238 get_property_names (cls_node , attribute_names )
245239 return attribute_names
246240
247241
248242def create_function_report (f : Callable , is_async : bool = False ) -> Dict :
249243 function = inspect .signature (f )
250- func_obj = {
251- "parameters" : {},
252- "is_async" : is_async
253- }
244+ func_obj = {"parameters" : {}, "is_async" : is_async }
254245
255246 for par in function .parameters .values ():
256247 default_value = get_parameter_default (par )
@@ -308,46 +299,55 @@ def create_parameters(args: ast.arg) -> Dict:
308299 if hasattr (args , "posonlyargs" ):
309300 for arg in args .posonlyargs :
310301 # Initialize the function parameters
311- params .update ({arg .arg : {
312- "type" : get_parameter_type (arg .annotation ),
313- "default" : None ,
314- "param_type" : "positional_only"
315- }})
302+ params .update (
303+ {
304+ arg .arg : {
305+ "type" : get_parameter_type (arg .annotation ),
306+ "default" : None ,
307+ "param_type" : "positional_only" ,
308+ }
309+ }
310+ )
316311 if hasattr (args , "args" ):
317312 for arg in args .args :
318313 # Initialize the function parameters
319- params .update ({arg .arg : {
320- "type" : get_parameter_type (arg .annotation ),
321- "default" : None ,
322- "param_type" : "positional_or_keyword"
323- }})
314+ params .update (
315+ {
316+ arg .arg : {
317+ "type" : get_parameter_type (arg .annotation ),
318+ "default" : None ,
319+ "param_type" : "positional_or_keyword" ,
320+ }
321+ }
322+ )
324323 # Range through the corresponding default values
325324 all_args = args .posonlyargs + args .args
326325 positional_defaults = [None ] * (len (all_args ) - len (args .defaults )) + args .defaults
327326 for arg , default in zip (all_args , positional_defaults ):
328327 params [arg .arg ]["default" ] = get_parameter_default_ast (default )
329328 if hasattr (args , "vararg" ):
330329 if args .vararg :
331- params .update ({args .vararg .arg : {
332- "type" : get_parameter_type (args .vararg .annotation ),
333- "default" : None ,
334- "param_type" : "var_positional"
335- }})
330+ params .update (
331+ {
332+ args .vararg .arg : {
333+ "type" : get_parameter_type (args .vararg .annotation ),
334+ "default" : None ,
335+ "param_type" : "var_positional" ,
336+ }
337+ }
338+ )
336339 if hasattr (args , "kwonlyargs" ):
337340 for arg in args .kwonlyargs :
338341 # Initialize the function parameters
339- params .update ({
340- arg .arg : {
341- "type" : get_parameter_type (arg .annotation ),
342- "default" : None ,
343- "param_type" : "keyword_only"
344- }
345- })
342+ params .update (
343+ {arg .arg : {"type" : get_parameter_type (arg .annotation ), "default" : None , "param_type" : "keyword_only" }}
344+ )
346345 # Range through the corresponding default values
347346 for i in range (len (args .kwonlyargs ) - len (args .kw_defaults ), len (args .kwonlyargs )):
348347 params [args .kwonlyargs [i ].arg ]["default" ] = get_parameter_default_ast (args .kw_defaults [i ])
349348 return params
350349
350+
351351def get_overloads (cls : Type , cls_methods : Dict ):
352352 path = inspect .getsourcefile (cls )
353353 module = _get_parsed_module (path )
@@ -361,22 +361,24 @@ def get_overloads(cls: Type, cls_methods: Dict):
361361 path = inspect .getsourcefile (base_class )
362362 module = _get_parsed_module (path )
363363 except (TypeError , SyntaxError ):
364- _LOGGER .info (f"Unable to create ast of { base_class } " )
364+ _LOGGER .debug (f"Unable to create ast of { base_class } " )
365365 continue # was a built-in, e.g. "object", Exception, or a Model from msrest fails here
366366
367367 cls_node = _find_class_node (module , base_class .__name__ )
368368 if cls_node :
369369 get_overload_data (cls_node , cls_methods )
370370 else :
371371 # Abstract base classes fail here, e.g. "collections.abc.MuttableMapping"
372- _LOGGER .info (f"Unable to get class node for { base_class .__name__ } . Skipping..." )
372+ _LOGGER .debug (f"Unable to get class node for { base_class .__name__ } . Skipping..." )
373373 else :
374374 get_overload_data (cls_node , cls_methods )
375375
376376
377377def get_overload_data (node : ast .ClassDef , cls_methods : Dict ) -> None :
378378 func_nodes = [node for node in node .body if isinstance (node , (ast .FunctionDef , ast .AsyncFunctionDef ))]
379- public_func_nodes = [func for func in func_nodes if not func .name .startswith ("_" ) or func .name .startswith ("__init__" )]
379+ public_func_nodes = [
380+ func for func in func_nodes if not func .name .startswith ("_" ) or func .name .startswith ("__init__" )
381+ ]
380382 # Check for method overloads on a class
381383 for func in public_func_nodes :
382384 if func .name not in cls_methods :
@@ -393,7 +395,7 @@ def get_overload_data(node: ast.ClassDef, cls_methods: Dict) -> None:
393395 overload_report = {
394396 "parameters" : create_parameters (func .args ),
395397 "is_async" : is_async ,
396- "return_type" : None
398+ "return_type" : None ,
397399 }
398400 cls_methods [func .name ]["overloads" ].append (overload_report )
399401
@@ -422,7 +424,7 @@ def create_class_report(cls: Type) -> Dict:
422424 except AttributeError :
423425 _LOGGER .info (f"Skipping method check for { method } on { cls } ." )
424426 continue
425-
427+
426428 if inspect .isfunction (m ) or inspect .ismethod (m ):
427429 if inspect .iscoroutinefunction (m ):
428430 async_func = True
@@ -464,7 +466,9 @@ def build_library_report(target_module: str) -> Dict:
464466 return public_api
465467
466468
467- def test_compare_reports (pkg_dir : str , changelog : bool , source_report : str = "stable.json" , target_report : str = "current.json" ) -> None :
469+ def test_compare_reports (
470+ pkg_dir : str , changelog : bool , source_report : str = "stable.json" , target_report : str = "current.json"
471+ ) -> None :
468472 package_name = os .path .basename (pkg_dir )
469473
470474 # Preserve the original argument values so we can decide later whether cleanup is safe.
@@ -489,18 +493,18 @@ def test_compare_reports(pkg_dir: str, changelog: bool, source_report: str = "st
489493 stable ,
490494 current ,
491495 package_name ,
492- checkers = CHECKERS ,
493- ignore = IGNORE_BREAKING_CHANGES ,
494- post_processing_checkers = POST_PROCESSING_CHECKERS
496+ checkers = CHECKERS ,
497+ ignore = IGNORE_BREAKING_CHANGES ,
498+ post_processing_checkers = POST_PROCESSING_CHECKERS ,
495499 )
496500 if changelog :
497501 checker = ChangelogTracker (
498502 stable ,
499503 current ,
500504 package_name ,
501- checkers = CHECKERS ,
502- ignore = IGNORE_BREAKING_CHANGES ,
503- post_processing_checkers = POST_PROCESSING_CHECKERS ,
505+ checkers = CHECKERS ,
506+ ignore = IGNORE_BREAKING_CHANGES ,
507+ post_processing_checkers = POST_PROCESSING_CHECKERS ,
504508 )
505509 checker .run_checks ()
506510
@@ -531,7 +535,7 @@ def remove_json_files(pkg_dir: str) -> None:
531535
532536
533537def report_azure_mgmt_versioned_module (code_report ):
534-
538+
535539 def parse_module_name (module ):
536540 split_module = module .split ("." )
537541 # Azure mgmt packages are typically in the form of: azure.mgmt.<service>
@@ -555,17 +559,17 @@ def parse_module_name(module):
555559
556560
557561def main (
558- package_name : str ,
559- target_module : str ,
560- version : str ,
561- in_venv : Union [bool , str ],
562- pkg_dir : str ,
563- changelog : bool ,
564- code_report : bool ,
565- latest_pypi_version : bool ,
566- source_report : Optional [Path ],
567- target_report : Optional [Path ]
568- ):
562+ package_name : str ,
563+ target_module : str ,
564+ version : str ,
565+ in_venv : Union [bool , str ],
566+ pkg_dir : str ,
567+ changelog : bool ,
568+ code_report : bool ,
569+ latest_pypi_version : bool ,
570+ source_report : Optional [Path ],
571+ target_report : Optional [Path ],
572+ ):
569573 # If code_report is set, only generate a code report for the package and return
570574 if code_report :
571575 public_api = build_library_report (target_module )
@@ -583,6 +587,7 @@ def main(
583587 if not version :
584588
585589 from pypi_tools .pypi import PyPIClient
590+
586591 client = PyPIClient ()
587592
588593 try :
@@ -601,28 +606,10 @@ def main(
601606 packages = [f"{ package_name } =={ version } " , "jsondiff==1.2.0" ]
602607 with create_venv_with_package (packages ) as venv :
603608 subprocess .check_call (
604- [
605- venv .env_exe ,
606- "-m" ,
607- "pip" ,
608- "install" ,
609- "-r" ,
610- os .path .join (pkg_dir , "dev_requirements.txt" )
611- ]
609+ [venv .env_exe , "-m" , "pip" , "install" , "-r" , os .path .join (pkg_dir , "dev_requirements.txt" )]
612610 )
613611 _LOGGER .info (f"Installed version { version } of { package_name } in a venv" )
614- args = [
615- venv .env_exe ,
616- __file__ ,
617- "-t" ,
618- package_name ,
619- "-m" ,
620- target_module ,
621- "--in-venv" ,
622- "true" ,
623- "-s" ,
624- version
625- ]
612+ args = [venv .env_exe , __file__ , "-t" , package_name , "-m" , target_module , "--in-venv" , "true" , "-s" , version ]
626613 try :
627614 subprocess .check_call (args )
628615 except subprocess .CalledProcessError :
@@ -650,9 +637,7 @@ def main(
650637
651638
652639if __name__ == "__main__" :
653- parser = argparse .ArgumentParser (
654- description = "Run breaking changes checks against target folder."
655- )
640+ parser = argparse .ArgumentParser (description = "Run breaking changes checks against target folder." )
656641
657642 parser .add_argument (
658643 "-t" ,
@@ -670,19 +655,15 @@ def main(
670655 )
671656
672657 parser .add_argument (
673- "-v" ,
674- "--in-venv" ,
675- dest = "in_venv" ,
676- help = "Check if we are in the newly created venv." ,
677- default = False
658+ "-v" , "--in-venv" , dest = "in_venv" , help = "Check if we are in the newly created venv." , default = False
678659 )
679660
680661 parser .add_argument (
681662 "-s" ,
682663 "--stable_version" ,
683664 dest = "stable_version" ,
684665 help = "The stable version of the target package, if it exists on PyPi." ,
685- default = None
666+ default = None ,
686667 )
687668
688669 parser .add_argument (
@@ -736,13 +717,18 @@ def main(
736717
737718 # We dont need to block for code report generation
738719 if not args .code_report :
739- if package_name not in RUN_BREAKING_CHANGES_PACKAGES and not any (bool (re .findall (p , package_name )) for p in RUN_BREAKING_CHANGES_PACKAGES ):
740- _LOGGER .info (f"{ package_name } opted out of breaking changes checks. "
741- f"See http://aka.ms/azsdk/breaking-changes-tool to opt-in." )
720+ if package_name not in RUN_BREAKING_CHANGES_PACKAGES and not any (
721+ bool (re .findall (p , package_name )) for p in RUN_BREAKING_CHANGES_PACKAGES
722+ ):
723+ _LOGGER .info (
724+ f"{ package_name } opted out of breaking changes checks. "
725+ f"See http://aka.ms/azsdk/breaking-changes-tool to opt-in."
726+ )
742727 exit (0 )
743728
744729 if not target_module and not (args .source_report and args .target_report ):
745730 from ci_tools .parsing import ParsedSetup
731+
746732 pkg_details = ParsedSetup .from_path (pkg_dir )
747733 target_module = pkg_details .namespace
748734
@@ -755,4 +741,15 @@ def main(
755741 _LOGGER .exception ("If providing the `--target-report` flag, the `--source-report` flag is also required." )
756742 exit (1 )
757743
758- main (package_name , target_module , stable_version , in_venv , pkg_dir , changelog , args .code_report , args .latest_pypi_version , args .source_report , args .target_report )
744+ main (
745+ package_name ,
746+ target_module ,
747+ stable_version ,
748+ in_venv ,
749+ pkg_dir ,
750+ changelog ,
751+ args .code_report ,
752+ args .latest_pypi_version ,
753+ args .source_report ,
754+ args .target_report ,
755+ )
0 commit comments