Skip to content

Commit d1c5749

Browse files
authored
🔄 Merge pull request Ambro17#20 from Ambro17/add-change-to-validation-result-object
✨ Enrich validation response with rule name and original change object to enable allowlist feature
2 parents 845d940 + 35e58a0 commit d1c5749

File tree

12 files changed

+322
-192
lines changed

12 files changed

+322
-192
lines changed

‎docs/changes/field.html‎

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ <h1 class="title">Module <code>schemadiff.changes.field</code></h1>
2626
<summary>
2727
<span>Expand source code</span>
2828
</summary>
29-
<pre><code class="python">from graphql import is_non_null_type
29+
<pre><code class="python">from graphql import is_non_null_type, GraphQLField
3030

3131
from schemadiff.changes import Change, Criticality, is_safe_type_change
3232

@@ -99,13 +99,14 @@ <h1 class="title">Module <code>schemadiff.changes.field</code></h1>
9999

100100

101101
class FieldArgumentAdded(Change):
102-
def __init__(self, parent, field_name, argument_name, arg_type):
102+
def __init__(self, parent, field_name: str, field: GraphQLField, argument_name, arg_type):
103103
self.criticality = Criticality.safe(&#39;Adding an optional argument is a safe change&#39;)\
104104
if not is_non_null_type(arg_type.type)\
105105
else Criticality.breaking(&#34;Adding a required argument to an existing field is a breaking &#34;
106106
&#34;change because it will break existing uses of this field&#34;)
107107
self.parent = parent
108108
self.field_name = field_name
109+
self.field = field
109110
self.argument_name = argument_name
110111
self.arg_type = arg_type
111112

@@ -154,7 +155,7 @@ <h2 class="section-title" id="header-classes">Classes</h2>
154155
<dl>
155156
<dt id="schemadiff.changes.field.FieldArgumentAdded"><code class="flex name class">
156157
<span>class <span class="ident">FieldArgumentAdded</span></span>
157-
<span>(</span><span>parent, field_name, argument_name, arg_type)</span>
158+
<span>(</span><span>parent, field_name: str, field: graphql.type.definition.GraphQLField, argument_name, arg_type)</span>
158159
</code></dt>
159160
<dd>
160161
<div class="desc"><p>Common interface of all schema changes</p>
@@ -166,13 +167,14 @@ <h2 class="section-title" id="header-classes">Classes</h2>
166167
<span>Expand source code</span>
167168
</summary>
168169
<pre><code class="python">class FieldArgumentAdded(Change):
169-
def __init__(self, parent, field_name, argument_name, arg_type):
170+
def __init__(self, parent, field_name: str, field: GraphQLField, argument_name, arg_type):
170171
self.criticality = Criticality.safe(&#39;Adding an optional argument is a safe change&#39;)\
171172
if not is_non_null_type(arg_type.type)\
172173
else Criticality.breaking(&#34;Adding a required argument to an existing field is a breaking &#34;
173174
&#34;change because it will break existing uses of this field&#34;)
174175
self.parent = parent
175176
self.field_name = field_name
177+
self.field = field
176178
self.argument_name = argument_name
177179
self.arg_type = arg_type
178180

‎docs/changes/object.html‎

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,19 @@ <h1 class="title">Module <code>schemadiff.changes.object</code></h1>
2626
<summary>
2727
<span>Expand source code</span>
2828
</summary>
29-
<pre><code class="python">from schemadiff.changes import Change, Criticality
29+
<pre><code class="python">from graphql import GraphQLField, GraphQLObjectType
30+
31+
from schemadiff.changes import Change, Criticality
3032

3133

3234
class ObjectTypeFieldAdded(Change):
3335

3436
criticality = Criticality.safe()
3537

36-
def __init__(self, parent, field_name):
38+
def __init__(self, parent: GraphQLObjectType, field_name, field: GraphQLField):
3739
self.parent = parent
3840
self.field_name = field_name
41+
self.field = field
3942
self.description = parent.fields[field_name].description
4043

4144
@property
@@ -82,7 +85,7 @@ <h2 class="section-title" id="header-classes">Classes</h2>
8285
<dl>
8386
<dt id="schemadiff.changes.object.ObjectTypeFieldAdded"><code class="flex name class">
8487
<span>class <span class="ident">ObjectTypeFieldAdded</span></span>
85-
<span>(</span><span>parent, field_name)</span>
88+
<span>(</span><span>parent: graphql.type.definition.GraphQLObjectType, field_name, field: graphql.type.definition.GraphQLField)</span>
8689
</code></dt>
8790
<dd>
8891
<div class="desc"><p>Common interface of all schema changes</p>
@@ -97,9 +100,10 @@ <h2 class="section-title" id="header-classes">Classes</h2>
97100

98101
criticality = Criticality.safe()
99102

100-
def __init__(self, parent, field_name):
103+
def __init__(self, parent: GraphQLObjectType, field_name, field: GraphQLField):
101104
self.parent = parent
102105
self.field_name = field_name
106+
self.field = field
103107
self.description = parent.fields[field_name].description
104108

105109
@property

‎docs/index.html‎

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ <h1 class="title">Package <code>schemadiff</code></h1>
3434
from schemadiff.diff.schema import Schema
3535
from schemadiff.schema_loader import SchemaLoader
3636
from schemadiff.formatting import print_diff, format_diff
37-
from schemadiff.validation import validate_diff
37+
from schemadiff.validation import validate_changes
3838

3939

4040
SDL = str # Alias for string describing schema through schema definition language
@@ -67,7 +67,7 @@ <h1 class="title">Package <code>schemadiff</code></h1>
6767
&#39;diff_from_file&#39;,
6868
&#39;format_diff&#39;,
6969
&#39;print_diff&#39;,
70-
&#39;validate_diff&#39;,
70+
&#39;validate_changes&#39;,
7171
&#39;Change&#39;,
7272
]</code></pre>
7373
</details>
@@ -182,13 +182,13 @@ <h2 id="returns">Returns</h2>
182182
print(format_diff(changes))</code></pre>
183183
</details>
184184
</dd>
185-
<dt id="schemadiff.validate_diff"><code class="name flex">
186-
<span>def <span class="ident">validate_diff</span></span>(<span>diff, rules: List[str]) ‑> bool</span>
185+
<dt id="schemadiff.validate_changes"><code class="name flex">
186+
<span>def <span class="ident">validate_changes</span></span>(<span>diff: List[<a title="schemadiff.changes.Change" href="changes/index.html#schemadiff.changes.Change">Change</a>], rules: List[str], allowed_changes: Dict[str, Any] = None) ‑> <a title="schemadiff.validation.ValidationResult" href="validation.html#schemadiff.validation.ValidationResult">ValidationResult</a></span>
187187
</code></dt>
188188
<dd>
189-
<div class="desc"><p>Given a diff between schemas and a list of rules
190-
names, it looks up for all rules matching the list
191-
and evaluates the changes against that list.</p>
189+
<div class="desc"><p>Given a list of changes between schemas and a list of rules,
190+
it runs all rules against the changes, to detect invalid changes.
191+
It also admits an allowlist of accepted invalid changes to document exceptions to the rules</p>
192192
<h2 id="returns">Returns</h2>
193193
<dl>
194194
<dt><code>bool</code></dt>
@@ -199,24 +199,30 @@ <h2 id="returns">Returns</h2>
199199
<summary>
200200
<span>Expand source code</span>
201201
</summary>
202-
<pre><code class="python">def validate_diff(diff, rules: List[str]) -&gt; bool:
203-
&#34;&#34;&#34;Given a diff between schemas and a list of rules
204-
names, it looks up for all rules matching the list
205-
and evaluates the changes against that list.
202+
<pre><code class="python">def validate_changes(diff: List[Change], rules: List[str], allowed_changes: Dict[str, Any] = None) -&gt; ValidationResult:
203+
&#34;&#34;&#34;Given a list of changes between schemas and a list of rules,
204+
it runs all rules against the changes, to detect invalid changes.
205+
It also admits an allowlist of accepted invalid changes to document exceptions to the rules
206206

207207
Returns:
208208
bool: True if there is at least one restricted change,
209209
False otherwise.
210210
&#34;&#34;&#34;
211-
is_restricted = False
211+
allowed_changes = allowed_changes or {}
212+
is_valid = True
213+
errors = []
212214
rules = ValidationRule.get_subclasses_by_names(rules)
213215
for change in diff:
214216
for rule in rules:
215217
if not rule(change).is_valid():
218+
if change.checksum() in allowed_changes:
219+
continue
220+
216221
change.restricted = rule(change).message
217-
is_restricted = True
222+
is_valid = False
223+
errors.append(ValidationError(rule.name, change.restricted, change))
218224

219-
return is_restricted</code></pre>
225+
return ValidationResult(is_valid, errors)</code></pre>
220226
</details>
221227
</dd>
222228
</dl>
@@ -497,7 +503,7 @@ <h1>Index</h1>
497503
<li><code><a title="schemadiff.diff_from_file" href="#schemadiff.diff_from_file">diff_from_file</a></code></li>
498504
<li><code><a title="schemadiff.format_diff" href="#schemadiff.format_diff">format_diff</a></code></li>
499505
<li><code><a title="schemadiff.print_diff" href="#schemadiff.print_diff">print_diff</a></code></li>
500-
<li><code><a title="schemadiff.validate_diff" href="#schemadiff.validate_diff">validate_diff</a></code></li>
506+
<li><code><a title="schemadiff.validate_changes" href="#schemadiff.validate_changes">validate_changes</a></code></li>
501507
</ul>
502508
</li>
503509
<li><h3><a href="#header-classes">Classes</a></h3>

0 commit comments

Comments
 (0)