@@ -29,15 +29,6 @@ class BreakingChangeType(str, Enum):
29
29
REMOVED_OR_RENAMED_MODULE = "RemovedOrRenamedModule"
30
30
REMOVED_FUNCTION_KWARGS = "RemovedFunctionKwargs"
31
31
32
- # General non-breaking changes
33
- class ChangeType (str , Enum ):
34
- ADDED_CLIENT = "AddedClient"
35
- ADDED_CLIENT_METHOD = "AddedClientMethod"
36
- ADDED_CLASS = "AddedClass"
37
- ADDED_CLASS_METHOD = "AddedClassMethod"
38
- ADDED_CLASS_METHOD_PARAMETER = "AddedClassMethodParameter"
39
- ADDED_CLASS_PROPERTY = "AddedClassProperty"
40
- ADDED_FUNCTION_PARAMETER = "AddedFunctionParameter"
41
32
42
33
class BreakingChangesTracker :
43
34
REMOVED_OR_RENAMED_CLIENT_MSG = \
@@ -97,50 +88,20 @@ class BreakingChangesTracker:
97
88
"The function '{}.{}' changed from accepting keyword arguments to not accepting them in " \
98
89
"the current version"
99
90
100
- # ----------------- General Changes -----------------
101
- ADDED_CLIENT_MSG = \
102
- "The client '{}.{}' was added in the current version"
103
- ADDED_CLIENT_METHOD_MSG = \
104
- "The '{}.{}' client method '{}' was added in the current version"
105
- ADDED_CLASS_MSG = \
106
- "The model or publicly exposed class '{}.{}' was added in the current version"
107
- ADDED_CLASS_METHOD_MSG = \
108
- "The '{}.{}' method '{}' was added in the current version"
109
- ADDED_CLASS_METHOD_PARAMETER_MSG = \
110
- "The model or publicly exposed class '{}.{}' had property '{}' added in the {} method in the current version"
111
- ADDED_FUNCTION_PARAMETER_MSG = \
112
- "The function '{}.{}' had parameter '{}' added in the current version"
113
- ADDED_CLASS_PROPERTY_MSG = \
114
- "The model or publicly exposed class '{}.{}' had property '{}' added in the current version"
115
-
116
-
117
91
def __init__ (self , stable : Dict , current : Dict , diff : Dict , package_name : str , ** kwargs : Any ) -> None :
118
92
self .stable = stable
119
93
self .current = current
120
94
self .diff = diff
121
95
self .breaking_changes = []
122
- self .features_added = []
123
96
self .package_name = package_name
124
97
self .module_name = None
125
98
self .class_name = None
126
99
self .function_name = None
127
100
self .parameter_name = None
128
101
self .ignore = kwargs .get ("ignore" , None )
129
- self .changelog = kwargs .get ("changelog" , False )
130
-
131
- def __str__ (self ):
132
- formatted = "\n "
133
- for bc in self .breaking_changes :
134
- formatted += bc + "\n "
135
-
136
- formatted += f"\n Found { len (self .breaking_changes )} breaking changes.\n "
137
- formatted += "\n See aka.ms/azsdk/breaking-changes-tool to resolve " \
138
- "any reported breaking changes or false positives.\n "
139
- return formatted
102
+ self .previous_version = kwargs .get ("previous_version" , None )
140
103
141
104
def run_checks (self ) -> None :
142
- if self .changelog :
143
- self .run_non_breaking_change_diff_checks ()
144
105
self .run_breaking_change_diff_checks ()
145
106
self .check_parameter_ordering () # not part of diff
146
107
@@ -157,88 +118,6 @@ def run_breaking_change_diff_checks(self) -> None:
157
118
self .run_class_level_diff_checks (module )
158
119
self .run_function_level_diff_checks (module )
159
120
160
- def run_non_breaking_change_diff_checks (self ) -> None :
161
- for module_name , module in self .diff .items ():
162
- self .module_name = module_name
163
- if self .module_name not in self .stable and not isinstance (self .module_name , jsondiff .Symbol ):
164
- continue # TODO add this to reported changes
165
-
166
- self .run_non_breaking_class_level_diff_checks (module )
167
-
168
- def run_non_breaking_class_level_diff_checks (self , module : Dict ) -> None :
169
- for class_name , class_components in module .get ("class_nodes" , {}).items ():
170
- self .class_name = class_name
171
- stable_class_nodes = self .stable [self .module_name ]["class_nodes" ]
172
- if not isinstance (class_name , jsondiff .Symbol ):
173
- if self .class_name not in stable_class_nodes :
174
- if self .class_name .endswith ("Client" ):
175
- # This is a new client
176
- fa = (
177
- self .ADDED_CLIENT_MSG ,
178
- ChangeType .ADDED_CLIENT ,
179
- self .module_name , class_name
180
- )
181
- self .features_added .append (fa )
182
- else :
183
- # This is a new class
184
- fa = (
185
- self .ADDED_CLASS_MSG ,
186
- ChangeType .ADDED_CLASS ,
187
- self .module_name , class_name
188
- )
189
- self .features_added .append (fa )
190
- else :
191
- # Check existing class for new methods
192
- stable_methods_node = stable_class_nodes [self .class_name ]["methods" ]
193
- for method_name , method_components in class_components .get ("methods" , {}).items ():
194
- self .function_name = method_name
195
- if not isinstance (self .function_name , jsondiff .Symbol ):
196
- if self .function_name not in stable_methods_node :
197
- if self .class_name .endswith ("Client" ):
198
- # This is a new client method
199
- fa = (
200
- self .ADDED_CLIENT_METHOD_MSG ,
201
- ChangeType .ADDED_CLIENT_METHOD ,
202
- self .module_name , self .class_name , method_name
203
- )
204
- self .features_added .append (fa )
205
- else :
206
- # This is a new class method
207
- fa = (
208
- self .ADDED_CLASS_METHOD_MSG ,
209
- ChangeType .ADDED_CLASS_METHOD ,
210
- self .module_name , class_name , method_name
211
- )
212
- self .features_added .append (fa )
213
- else :
214
- # Check existing methods for new parameters
215
- stable_parameters_node = stable_methods_node [self .function_name ]["parameters" ]
216
- current_parameters_node = self .current [self .module_name ]["class_nodes" ][self .class_name ]["methods" ][self .function_name ]["parameters" ]
217
- for param_name , param_components in method_components .get ("parameters" , {}).items ():
218
- self .parameter_name = param_name
219
- if self .parameter_name not in stable_parameters_node and \
220
- not isinstance (self .parameter_name , jsondiff .Symbol ):
221
- if self .function_name == "__init__" :
222
- # If this is a new class property skip reporting it here and let the class properties check handle it.
223
- # This is because we'll get multiple reports for the same new property if it's a parameter in __init__
224
- # and a class level attribute.
225
- if self .parameter_name in class_components .get ("properties" , {}).keys ():
226
- continue
227
- self .check_non_positional_parameter_added (
228
- current_parameters_node [param_name ]
229
- )
230
- stable_property_node = stable_class_nodes [self .class_name ]["properties" ]
231
- for property_name , property_components in class_components .get ("properties" , {}).items ():
232
- if property_name not in stable_property_node and \
233
- not isinstance (property_name , jsondiff .Symbol ):
234
- fa = (
235
- self .ADDED_CLASS_PROPERTY_MSG ,
236
- ChangeType .ADDED_CLASS_PROPERTY ,
237
- self .module_name , class_name , property_name
238
- )
239
- self .features_added .append (fa )
240
-
241
-
242
121
def run_class_level_diff_checks (self , module : Dict ) -> None :
243
122
for class_name , class_components in module .get ("class_nodes" , {}).items ():
244
123
self .class_name = class_name
@@ -540,23 +419,6 @@ def check_positional_parameter_added(self, current_parameters_node: Dict) -> Non
540
419
)
541
420
)
542
421
543
- def check_non_positional_parameter_added (self , current_parameters_node : Dict ) -> None :
544
- if current_parameters_node ["param_type" ] != "positional_or_keyword" :
545
- if self .class_name :
546
- self .features_added .append (
547
- (
548
- self .ADDED_CLASS_METHOD_PARAMETER_MSG , ChangeType .ADDED_CLASS_METHOD_PARAMETER ,
549
- self .module_name , self .class_name , self .parameter_name , self .function_name
550
- )
551
- )
552
- else :
553
- self .features_added .append (
554
- (
555
- self .ADDED_FUNCTION_PARAMETER_MSG , ChangeType .ADDED_FUNCTION_PARAMETER ,
556
- self .module_name , self .function_name , self .parameter_name
557
- )
558
- )
559
-
560
422
def check_positional_parameter_removed_or_renamed (
561
423
self , param_type : str ,
562
424
deleted : str ,
@@ -712,33 +574,23 @@ def get_reportable_breaking_changes(self, ignore_changes: Dict) -> List:
712
574
reportable_changes .append (bc )
713
575
return reportable_changes
714
576
715
- def report_changelog (self ) -> None :
716
- # Code borrowed and modified from the previous change log tool
717
- def _build_md (content : list , title : str , buffer : list ):
718
- buffer .append (title )
719
- buffer .append ("" )
720
- for _ , bc in enumerate (content ):
721
- msg , _ , * args = bc
722
- buffer .append (msg .format (* args ))
723
- buffer .append ("" )
724
- return buffer
725
-
726
- buffer = []
727
-
728
- if self .breaking_changes :
729
- _build_md (self .breaking_changes , "### Breaking Changes" , buffer )
730
- if self .features_added :
731
- _build_md (self .features_added , "### Features Added" , buffer )
732
- content = "\n " .join (buffer ).strip ()
733
- return content
734
-
735
- def report_breaking_changes (self ) -> None :
577
+ def report_changes (self ) -> None :
736
578
ignore_changes = self .ignore if self .ignore else IGNORE_BREAKING_CHANGES
737
579
if self .package_name in ignore_changes :
738
580
self .breaking_changes = self .get_reportable_breaking_changes (ignore_changes )
739
581
582
+ # If there are no breaking changes after the ignore check, return early
583
+ if not self .breaking_changes :
584
+ return f"\n No breaking changes found for { self .package_name } between stable version { self .previous_version } and current version."
585
+
586
+ formatted = "\n "
740
587
for idx , bc in enumerate (self .breaking_changes ):
741
588
msg , * args = bc
742
589
# For simple breaking changes reporting, prepend the change code to the message
743
- msg = "({}): " + msg
744
- self .breaking_changes [idx ] = msg .format (* args )
590
+ msg = "({}): " + msg + "\n "
591
+ formatted += msg .format (* args )
592
+
593
+ formatted += f"\n Found { len (self .breaking_changes )} breaking changes.\n "
594
+ formatted += "\n See aka.ms/azsdk/breaking-changes-tool to resolve " \
595
+ "any reported breaking changes or false positives.\n "
596
+ return formatted
0 commit comments