New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allowing nested @optional` tags #120
Conversation
This will allow them to be tracked in the QueryMetadataTable.
Also fixes a bug where Backtrack blocks were incorrectly generated right before an Unfold block, pointing to invalid, unused, and unusable Locations.
@@ -219,3 +220,104 @@ def construct_where_filter_predicate(simple_optional_root_info): | |||
# A CompoundMatchQuery is a representation of several MatchQuery objects containing | |||
# - match_queries: a list MatchQuery objects | |||
CompoundMatchQuery = namedtuple('CompoundMatchQuery', ('match_queries')) | |||
|
|||
|
|||
class OptionalTraversalTrie(dict): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's discuss this in person, and figure out whether and how it might relate to the QueryMetadataTable work that has been happening in parallel.
graphql_compiler/compiler/helpers.py
Outdated
@@ -347,6 +349,26 @@ def __ne__(self, other): | |||
"""Check another object for non-equality against this one.""" | |||
return not self.__eq__(other) | |||
|
|||
def __lt__(self, other): | |||
"""Check another object for non-equality against this one.""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
copy-pasta docstring
graphql_compiler/compiler/helpers.py
Outdated
@@ -347,6 +349,26 @@ def __ne__(self, other): | |||
"""Check another object for non-equality against this one.""" | |||
return not self.__eq__(other) | |||
|
|||
def __lt__(self, other): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
other
could realistically be a FoldScopeLocation
, we'll have to handle that case.
Also, FoldScopeLocation
objects have to be comparable as well, which introduces some code duplication concerns. How about this:
- Implement
__eq__
and__lt__
onBaseLocation
by specifying the rules for which heterogeneous types compare to each other. For equality, they aren't equal, and for__lt__
they can compare in lexicographic order of the type's name. - Set
@total_ordering
onBaseLocation
. - If the two objects being compared are the same type, dispatch to a special private comparator method that is marked as an
@abstractmethod
inBaseLocation
. InLocation
, this method specifies the logic for comparingLocation
objects to each other, and inFoldScopeLocation
it specifies that object's comparison logic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be a separate PR? I don't think we need it for nested optionals.
if self.visit_counter != other.visit_counter: | ||
return self.visit_counter < other.visit_counter | ||
|
||
if self.field is None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't seem right. If other.field
is also None
, the objects are equal, which means that __lt__
must return False
. With this implementation, x < x
returns True
if x
is a Location
at a vertex field.
This means you need to add more tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should I just explicitly test that Location s objects are compared correctly?
# Simple optionals are ignored. | ||
# There should be no complex optionals after a simple optional. | ||
encountered_simple_optional = True | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove blank line at the end of block
|
||
# Recursively find all rooted subtrees of each of the children of the current node. | ||
location_to_list_of_subtrees = { | ||
location: [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this not just location: list(self.get_all_rooted_subtrees_as_lists(location))
? I don't think you need the nested comprehension.
Yeah probably a good idea to write some test cases for comparisons. You can
make the comparison logic a separate PR, I'll review it tomorrow AM and
then update this one with that PR's stuff.
…On Thu, Aug 30, 2018, 5:06 PM Amartya Shankha Biswas < ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In graphql_compiler/compiler/helpers.py
<#120 (comment)>
:
> @@ -347,6 +349,26 @@ def __ne__(self, other):
"""Check another object for non-equality against this one."""
return not self.__eq__(other)
+ def __lt__(self, other):
+ """Check another object for non-equality against this one."""
+ if len(self.query_path) != len(other.query_path):
+ return len(self.query_path) < len(other.query_path)
+
+ for self_vertex_field, other_vertex_field in zip(self.query_path, other.query_path):
+ if self_vertex_field != other_vertex_field:
+ return self_vertex_field < other_vertex_field
+
+ if self.visit_counter != other.visit_counter:
+ return self.visit_counter < other.visit_counter
+
+ if self.field is None:
Should I just explicitly test that Location s objects are compared
correctly?
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#120 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ACPWSof80xzrCUDjT8sRLa2JhLsAv8aHks5uWFPYgaJpZM4WCxSX>
.
|
graphql_compiler/compiler/helpers.py
Outdated
def __eq__(self, other): | ||
"""Return True if the other object is smaller than self in the total ordering.""" | ||
if isinstance(self, Location) and isinstance(other, Location): | ||
return self == other |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can leave __eq__
as an abstractmethod
. Otherwise, I think that this line will cause infinite recursion.
graphql_compiler/compiler/helpers.py
Outdated
raise NotImplementedError() | ||
|
||
def __eq__(self, other): | ||
"""Return True if the other object is smaller than self in the total ordering.""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
copy-pasta
graphql_compiler/compiler/helpers.py
Outdated
@@ -237,6 +237,45 @@ def get_location_name(self): | |||
"""Return a tuple of a unique name of the location, and the current field name (or None).""" | |||
raise NotImplementedError() | |||
|
|||
@abstractmethod | |||
def _compare(self, other): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about _check_if_object_of_same_type_is_smaller
or something similarly more descriptive than _compare
? Currently, it doesn't communicate that the other object is required to be of the same type as self
.
graphql_compiler/compiler/helpers.py
Outdated
if len(self.fold_path) != len(other.fold_path): | ||
return len(self.fold_path) < len(other.fold_path) | ||
|
||
for self_edge_tuple, other_edge_tuple in zip(self.fold_path, other.fold_path): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does if self.fold_path != other.fold_path: return self.fold_path < other.fold_path
not work? If I remember correctly, it's a tuple-of-tuples, which should sort correctly.
Also Github seems to think there are conflicts and that this can't be merged right now. |
9136e6f
to
cf181d0
Compare
@@ -38,6 +38,8 @@ def compare_ir_blocks(test_case, expected_blocks, received_blocks): | |||
for i in six.moves.xrange(len(expected_blocks)): | |||
expected = expected_blocks[i] | |||
received = received_blocks[i] | |||
if expected != received: | |||
__import__('pdb').set_trace() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should probably remove this before we merge into master
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Woops, fixed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it is, actually -- the if expected != received:
line is still there and it's causing a syntax error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My bad. Hopefully actually fixed now.
Most of the action happens in
OptionalTraversalTrie
(inutils.py
).The most recent test is not passing. This is the one with a 250 line output. I'll put it in a separate file later.