<s> from io import StringIO <EOL> from json import dumps as json_dumps <EOL> from sys import stdout <EOL> from py2neo . compat import ustr <EOL> from py2neo . types import Node , Relationship , Path <EOL> from py2neo . util import is_collection <EOL> class CypherWriter ( object ) : <EOL> """<STR_LIT>""" <EOL> safe_first_chars = u"<STR_LIT>" <EOL> safe_chars = u"<STR_LIT>" <EOL> default_sequence_separator = u"<STR_LIT:U+002C>" <EOL> default_key_value_separator = u"<STR_LIT::>" <EOL> def __init__ ( self , file = None , ** kwargs ) : <EOL> self . file = file or stdout <EOL> self . sequence_separator = kwargs . get ( "<STR_LIT>" , self . default_sequence_separator ) <EOL> self . key_value_separator = kwargs . get ( "<STR_LIT>" , self . default_key_value_separator ) <EOL> def write ( self , obj ) : <EOL> """<STR_LIT>""" <EOL> if obj is None : <EOL> pass <EOL> elif isinstance ( obj , Node ) : <EOL> self . write_node ( obj ) <EOL> elif isinstance ( obj , Relationship ) : <EOL> self . write_relationship ( obj ) <EOL> elif isinstance ( obj , Path ) : <EOL> self . write_walkable ( obj ) <EOL> elif isinstance ( obj , dict ) : <EOL> self . write_map ( obj ) <EOL> elif is_collection ( obj ) : <EOL> self . write_list ( obj ) <EOL> else : <EOL> self . write_value ( obj ) <EOL> def write_value ( self , value ) : <EOL> """<STR_LIT>""" <EOL> self . file . write ( ustr ( json_dumps ( value , ensure_ascii = False ) ) ) <EOL> def write_identifier ( self , identifier ) : <EOL> """<STR_LIT>""" <EOL> if not identifier : <EOL> raise ValueError ( "<STR_LIT>" ) <EOL> identifier = ustr ( identifier ) <EOL> safe = ( identifier [ <NUM_LIT:0> ] in self . safe_first_chars and <EOL> all ( ch in self . safe_chars for ch in identifier [ <NUM_LIT:1> : ] ) ) <EOL> if not safe : <EOL> self . file . write ( u"<STR_LIT>" ) <EOL> self . file . write ( identifier . replace ( u"<STR_LIT>" , u"<STR_LIT>" ) ) <EOL> self . file . write ( u"<STR_LIT>" ) <EOL> else : <EOL> self . file . write ( identifier ) <EOL> def write_list ( self , collection ) : <EOL> """<STR_LIT>""" <EOL> self . file . write ( u"<STR_LIT:[>" ) <EOL> link = u"<STR_LIT>" <EOL> for value in collection : <EOL> self . file . write ( link ) <EOL> self . write ( value ) <EOL> link = self . sequence_separator <EOL> self . file . write ( u"<STR_LIT:]>" ) <EOL> def write_literal ( self , text ) : <EOL> """<STR_LIT>""" <EOL> self . file . write ( ustr ( text ) ) <EOL> def write_map ( self , mapping , private = False ) : <EOL> """<STR_LIT>""" <EOL> self . file . write ( u"<STR_LIT:{>" ) <EOL> link = u"<STR_LIT>" <EOL> for key , value in sorted ( dict ( mapping ) . items ( ) ) : <EOL> if key . startswith ( "<STR_LIT:_>" ) and not private : <EOL> continue <EOL> self . file . write ( link ) <EOL> self . write_identifier ( key ) <EOL> self . file . write ( self . key_value_separator ) <EOL> self . write ( value ) <EOL> link = self . sequence_separator <EOL> self . file . write ( u"<STR_LIT:}>" ) <EOL> def write_node ( self , node , name = None , full = True ) : <EOL> """<STR_LIT>""" <EOL> self . file . write ( u"<STR_LIT:(>" ) <EOL> if name is None : <EOL> name = node . __name__ <EOL> self . write_identifier ( name ) <EOL> if full : <EOL> for label in sorted ( node . labels ( ) ) : <EOL> self . write_literal ( u"<STR_LIT::>" ) <EOL> self . write_identifier ( label ) <EOL> if node : <EOL> self . file . write ( u"<STR_LIT:U+0020>" ) <EOL> self . write_map ( dict ( node ) ) <EOL> self . file . write ( u"<STR_LIT:)>" ) <EOL> def write_relationship ( self , relationship , name = None ) : <EOL> """<STR_LIT>""" <EOL> self . write_node ( relationship . start_node ( ) , full = False ) <EOL> self . file . write ( u"<STR_LIT:->" ) <EOL> self . write_relationship_detail ( relationship , name ) <EOL> self . file . write ( u"<STR_LIT>" ) <EOL> self . write_node ( relationship . end_node ( ) , full = False ) <EOL> def write_relationship_detail ( self , relationship , name = None ) : <EOL> """<STR_LIT>""" <EOL> self . file . write ( u"<STR_LIT:[>" ) <EOL> if name is not None : <EOL> self . write_identifier ( name ) <EOL> if type : <EOL> self . file . write ( u"<STR_LIT::>" ) <EOL> self . write_identifier ( relationship . type ( ) ) <EOL> if relationship : <EOL> self . file . write ( u"<STR_LIT:U+0020>" ) <EOL> self . write_map ( relationship ) <EOL> self . file . write ( u"<STR_LIT:]>" ) <EOL> def write_subgraph ( self , subgraph ) : <EOL> """<STR_LIT>""" <EOL> self . write_literal ( "<STR_LIT>" ) <EOL> for i , node in enumerate ( subgraph . nodes ( ) ) : <EOL> if i > <NUM_LIT:0> : <EOL> self . write_literal ( "<STR_LIT:U+002CU+0020>" ) <EOL> self . write_node ( node ) <EOL> self . write_literal ( "<STR_LIT>" ) <EOL> for i , relationship in enumerate ( subgraph . relationships ( ) ) : <EOL> if i > <NUM_LIT:0> : <EOL> self . write_literal ( "<STR_LIT:U+002CU+0020>" ) <EOL> self . write_relationship ( relationship ) <EOL> self . write_literal ( "<STR_LIT>" ) <EOL> def write_walkable ( self , walkable ) : <EOL> """<STR_LIT>""" <EOL> nodes = walkable . nodes ( ) <EOL> for i , relationship in enumerate ( walkable ) : <EOL> node = nodes [ i ] <EOL> self . write_node ( node , full = False ) <EOL> forward = relationship . start_node ( ) == node <EOL> self . file . write ( u"<STR_LIT:->" if forward else u"<STR_LIT>" ) <EOL> self . write_relationship_detail ( relationship ) <EOL> self . file . write ( u"<STR_LIT>" if forward else u"<STR_LIT:->" ) <EOL> self . write_node ( nodes [ - <NUM_LIT:1> ] , full = False ) <EOL> def cypher_escape ( identifier ) : <EOL> """<STR_LIT>""" <EOL> s = StringIO ( ) <EOL> writer = CypherWriter ( s ) <EOL> writer . write_identifier ( identifier ) <EOL> return s . getvalue ( ) <EOL> def cypher_repr ( obj ) : <EOL> """<STR_LIT>""" <EOL> s = StringIO ( ) <EOL> writer = CypherWriter ( s ) <EOL> writer . write ( obj ) <EOL> return s . getvalue ( ) </s>
