Skip to content

Instantly share code, notes, and snippets.

@keturn
Last active February 21, 2016 06:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save keturn/9dba29c7d0b4e00863fe to your computer and use it in GitHub Desktop.
Save keturn/9dba29c7d0b4e00863fe to your computer and use it in GitHub Desktop.
Can we force something like Cypher syntax in to Python? In the tradition of [Sugared DOM](https://gist.github.com/neilj/1532562) and [plumbum](https://pypi.python.org/pypi/plumbum).
# -*- coding: utf-8 -*-
"""THIS IS PROBABLY NOT A GOOD IDEA.
"""
def test_cases():
cases = [
(N(), "()"),
(E, "[]"),
(E[:], "[]"),
(N('Person'), "(:Person)"),
(E[:'Person'], "[:Person]"),
(N() - E[:], "()-[]"),
(E[:] - N(), "[]-()"),
(N('Person')--N('Club'), "(:Person)--(:Club)"),
(E[:'MemberOf'] > N('Club'), "[:MemberOf]->(:Club)"),
(N('Person') - E[:'MemberOf'] - N('Club'), "(:Person)-[:MemberOf]-(:Club)"),
(N('Person') - E[:'MemberOf'] > N('Club'), "(:Person)-[:MemberOf]->(:Club)"),
(N('Person') < E[:'HasMember'], "(:Person)<-[:HasMember]"),
(N('Person') < E[:'HasMember'] - N('Club'), "(:Person)<-[:HasMember]-(:Club)")
]
return cases
class N(object):
def __init__(self, *labels):
self.labels = labels
def __sub__(self, other):
return Path(self, other)
def __neg__(self):
return self
def __lt__(self, other):
return Path(self, other.as_direction(Edge.LEFT))
def __unicode__(self):
if self.labels:
label = ':' + self.labels[0]
else:
label = ''
return u"(%(label)s)" % dict(
label=label,
)
class Edge(object):
direction = None
RIGHT = "RIGHT"
LEFT = "LEFT"
def __init__(self, *labels):
self.labels = labels
def __sub__(self, other):
return Path(self, other)
def __gt__(self, other):
new = self.as_direction(self.RIGHT)
return Path(new, other)
def as_direction(self, direction):
new = self.__class__(*self.labels)
new.direction = direction
return new
def __unicode__(self):
if self.labels:
label = ':' + self.labels[0]
else:
label = ''
return u"[%(label)s]" % dict(
label=label
)
class EdgeFactory(object):
def __getitem__(self, item):
if item.stop:
edge = Edge(item.stop)
else:
edge = Edge()
return edge
def __unicode__(self):
return unicode(Edge())
class Path(object):
edge_separators = {
Edge.LEFT: '<-',
Edge.RIGHT: '->',
None: '-'
}
def __init__(self, *elements):
self.elements = elements
def __sub__(self, other):
return self.__class__(*(self.elements + (other,)))
def __gt__(self, other):
lead_elements, rightmost = self.elements[:-1], self.elements[-1]
tail = rightmost.__gt__(other)
return Path(*(lead_elements + tail.elements))
def as_direction(self, direction):
if direction == Edge.LEFT:
left_edge, tail = self.elements[0], self.elements[1:]
left_edge = left_edge.as_direction(direction)
return self.__class__(left_edge, *tail)
raise NotImplementedError(direction)
def __iter__(self):
for element in self.elements:
if isinstance(element, Path):
for subpath_element in element:
yield subpath_element
else:
yield element
def __unicode__(self):
elements = iter(self)
left_element = next(elements)
parts = [left_element]
for right_element in elements:
if isinstance(left_element, N) and isinstance(right_element, N):
separator = u'--'
elif isinstance(left_element, Edge) and isinstance(right_element, N):
if left_element.direction == Edge.RIGHT:
separator = self.edge_separators[Edge.RIGHT]
else:
separator = '-'
elif isinstance(left_element, N) and isinstance(right_element, Edge):
if right_element.direction == Edge.LEFT:
separator = self.edge_separators[Edge.LEFT]
else:
separator = '-'
else:
separator = u'-'
parts.append(separator)
parts.append(right_element)
left_element = right_element
return u"".join(unicode(p) for p in parts)
E = EdgeFactory()
def run_tests():
for val, expected in test_cases():
assert unicode(val) == expected, u"%s != %s" % (unicode(val), expected)
print expected
if __name__ == '__main__':
run_tests()
@keturn
Copy link
Author

keturn commented Feb 21, 2016

I just realized, Python doesn't have an -> operator, but it does have >>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment