### Install pycypher Source: https://github.com/mizzlr/pycypher/blob/master/README.md Install the pycypher package using pip. ```bash pip install pycypher ``` -------------------------------- ### Set up development environment Source: https://github.com/mizzlr/pycypher/blob/master/README.md Instructions for cloning the repository, setting up a virtual environment, installing dependencies, and running tests. ```bash git clone https://github.com/Mizzlr/pycypher cd pycypher python -m venv .venv && source .venv/bin/activate pip install antlr4-python3-runtime pytest python -m pytest tests/ -v ``` -------------------------------- ### Parse a Cypher mutation query Source: https://github.com/mizzlr/pycypher/blob/master/README.md Example of parsing a MERGE statement with ON CREATE and ON MATCH clauses, demonstrating how to handle mutations. ```python result = parse(''' MERGE (n:User {id: $userId}) ON CREATE SET n.created = timestamp() ON MATCH SET n.lastSeen = timestamp() RETURN n ''') ``` -------------------------------- ### Supported Cypher Features Examples Source: https://context7.com/mizzlr/pycypher/llms.txt Demonstrates the usage of PyCypher with various complex Cypher constructs including pattern matching, data mutations, subqueries, and more. ```APIDOC ## Cypher Feature Examples ### Description Examples showcasing PyCypher's ability to parse a wide range of Cypher syntax, including advanced features. ### Method POST ### Endpoint /parse ### Parameters #### Request Body - **query_string** (string) - Required - The Cypher query string to parse. ### Examples #### Pattern Matching with Variable-Length Paths ```python parse('MATCH p = (a)-[*1..3]->(b) RETURN p;') parse('MATCH p = shortestPath((a)-[*..5]->(b)) RETURN p;') ``` #### Data Mutations ```python parse('CREATE (n:Person {name: "Bob", age: 30}) RETURN n;') parse('MERGE (n:User {id: 42}) ON CREATE SET n.created = timestamp() ON MATCH SET n.lastSeen = timestamp() RETURN n;') parse('MATCH (n) DETACH DELETE n;') ``` #### Subqueries and EXISTS Patterns ```python parse('CALL { MATCH (n) RETURN n LIMIT 1 } RETURN n;') parse('MATCH (n) WHERE EXISTS { (n)-[:KNOWS]->(:Person) } RETURN n;') ``` #### List Comprehensions and Predicate Functions ```python parse('MATCH (n) RETURN [x IN n.list WHERE x > 0 | x * 2];') parse('MATCH (n) WHERE ALL(x IN n.list WHERE x > 0) RETURN n;') ``` #### Pattern Comprehensions ```python parse('MATCH (n) RETURN [(n)-[:KNOWS]->(m) WHERE m.age > 30 | m.name];') ``` #### Procedure Calls with YIELD ```python parse('CALL db.labels() YIELD label RETURN label;') ``` #### FOREACH for Batch Updates ```python parse('MATCH p = (a)-[*]->(b) FOREACH (n IN nodes(p) | SET n.marked = true);') ``` #### Parameters and Escaped Identifiers ```python parse('MATCH (n:`My Label`) WHERE n.id = $id RETURN n.`strange prop`;') ``` ``` -------------------------------- ### Parse a basic MATCH query Source: https://github.com/mizzlr/pycypher/blob/master/README.md Example of parsing a simple MATCH clause. Ensure the 'errors' list is empty for a successful parse. ```python from pycypher import parse result = parse('MATCH (n:Person) RETURN n.name;') assert result['errors'] == [] ``` -------------------------------- ### Parse Cypher with Data Mutations Source: https://context7.com/mizzlr/pycypher/llms.txt Examples of parsing Cypher queries for creating, merging, and deleting nodes and relationships. ```python from pycypher import parse # Data mutations parse('CREATE (n:Person {name: "Bob", age: 30}) RETURN n;') parse('MERGE (n:User {id: 42}) ON CREATE SET n.created = timestamp() ON MATCH SET n.lastSeen = timestamp() RETURN n;') parse('MATCH (n) DETACH DELETE n;') ``` -------------------------------- ### Access PyCypher Version Information Source: https://context7.com/mizzlr/pycypher/llms.txt Retrieves and validates the installed PyCypher library version. Useful for compatibility checks and logging. ```python from pycypher import __version__ print(f"PyCypher version: {__version__}") # Output: 1.0.0 # Version validation major, minor, patch = __version__.split('.') assert all(part.isdigit() for part in [major, minor, patch]) ``` -------------------------------- ### Parse Cypher with Pattern Comprehensions Source: https://context7.com/mizzlr/pycypher/llms.txt Example of parsing Cypher queries that use pattern comprehensions to generate lists of nodes or relationships. ```python from pycypher import parse # Pattern comprehensions parse('MATCH (n) RETURN [(n)-[:KNOWS]->(m) WHERE m.age > 30 | m.name];') ``` -------------------------------- ### Parse Cypher with Parameters and Escaped Identifiers Source: https://context7.com/mizzlr/pycypher/llms.txt Example of parsing Cypher queries that use parameters and escaped identifiers for labels and properties. ```python from pycypher import parse # Parameters and escaped identifiers parse('MATCH (n:`My Label`) WHERE n.id = $id RETURN n.`strange prop`;') ``` -------------------------------- ### AST Structure Traversal Source: https://context7.com/mizzlr/pycypher/llms.txt Demonstrates how to traverse the Abstract Syntax Tree (AST) generated by PyCypher to access query components. ```APIDOC ## AST Traversal ### Description Provides a method to recursively traverse the Abstract Syntax Tree (AST) returned by the `parse` function, allowing inspection of query components. ### Method POST ### Endpoint /parse ### Parameters #### Request Body - **query_string** (string) - Required - The Cypher query string to parse. ### Request Example ```python from pycypher import parse def traverse_ast(node, depth=0): """Recursively traverse and print AST structure.""" indent = " " * depth node_info = node.get('node', {}) text = node_info.get('text', '') parent = node_info.get('parent', '') interval = node_info.get('sourceInterval', {}) if text: # Skip empty nodes print(f"{indent}{parent}: '{text}' at {interval}") for child in node.get('children', []): traverse_ast(child, depth + 1) # Parse and traverse result = parse('MATCH (n:Person) WHERE n.age > 25 RETURN n.name;') for top_node in result['result']: traverse_ast(top_node) ``` ### Response #### Success Response (200) - **result** (list) - A list representing the parsed AST structure. - **errors** (list) - A list of syntax errors encountered during parsing. #### Response Example (Output of traversal) ``` MATCH 'MATCH (n:Person) WHERE n.age > 25 RETURN n.name' at {'start': 0, 'length': 46} variable: 'n' at {'start': 7, 'length': 1} labelName: 'Person' at {'start': 9, 'length': 6} WHERE 'WHERE n.age > 25' at {'start': 20, 'length': 17} variable: 'n' at {'start': 27, 'length': 1} propertyKey: 'age' at {'start': 29, 'length': 3} comparisonOperator: '>' at {'start': 33, 'length': 1} literal: '25' at {'start': 35, 'length': 2} RETURN 'RETURN n.name' at {'start': 47, 'length': 10} variable: 'n' at {'start': 53, 'length': 1} propertyKey: 'name' at {'start': 54, 'length': 4} ``` ``` -------------------------------- ### Parse Cypher with Pattern Matching Source: https://context7.com/mizzlr/pycypher/llms.txt Demonstrates parsing Cypher queries involving variable-length paths and shortest path computations. ```python from pycypher import parse # Pattern matching with variable-length paths parse('MATCH p = (a)-[*1..3]->(b) RETURN p;') parse('MATCH p = shortestPath((a)-[*..5]->(b)) RETURN p;') ``` -------------------------------- ### Parse Cypher with FOREACH Source: https://context7.com/mizzlr/pycypher/llms.txt Demonstrates parsing Cypher queries using the FOREACH clause for batch updates on path elements. ```python from pycypher import parse # FOREACH for batch updates parse('MATCH p = (a)-[*]->(b) FOREACH (n IN nodes(p) | SET n.marked = true);') ``` -------------------------------- ### pycypher API - __version__ Source: https://github.com/mizzlr/pycypher/blob/master/README.md Accesses the package version string. ```APIDOC ## GET /api/version ### Description Retrieves the current version of the pycypher package. ### Method GET ### Endpoint /api/version ### Response #### Success Response (200) - **version** (string) - The package version string (e.g., "1.0.0") #### Response Example ```json { "version": "1.0.0" } ``` ``` -------------------------------- ### Parse Cypher with List Comprehensions Source: https://context7.com/mizzlr/pycypher/llms.txt Demonstrates parsing Cypher queries utilizing list comprehensions and predicate functions like ALL. ```python from pycypher import parse # List comprehensions and predicate functions parse('MATCH (n) RETURN [x IN n.list WHERE x > 0 | x * 2];') parse('MATCH (n) WHERE ALL(x IN n.list WHERE x > 0) RETURN n;') ``` -------------------------------- ### Parse Cypher with Subqueries and EXISTS Source: https://context7.com/mizzlr/pycypher/llms.txt Shows how to parse Cypher queries that include subqueries and the EXISTS pattern for conditional matching. ```python from pycypher import parse # Subqueries and EXISTS patterns parse('CALL { MATCH (n) RETURN n LIMIT 1 } RETURN n;') parse('MATCH (n) WHERE EXISTS { (n)-[:KNOWS]->(:Person) } RETURN n;') ``` -------------------------------- ### Parse Cypher with Procedure Calls Source: https://context7.com/mizzlr/pycypher/llms.txt Shows how to parse Cypher queries that involve calling database procedures and yielding results. ```python from pycypher import parse # Procedure calls with YIELD parse('CALL db.labels() YIELD label RETURN label;') ``` -------------------------------- ### Parse a relationship traversal query Source: https://github.com/mizzlr/pycypher/blob/master/README.md Demonstrates parsing a Cypher query involving multiple relationship traversals, a WHERE clause, ORDER BY, and LIMIT. ```python result = parse(''' MATCH (a:Person)-[:KNOWS]->(b:Person)-[:LIVES_IN]->(c:City) WHERE b.age > 25 RETURN a.name, b.name, c.name ORDER BY b.age DESC LIMIT 10 ''') ``` -------------------------------- ### Parse a query with subqueries Source: https://github.com/mizzlr/pycypher/blob/master/README.md Illustrates parsing a Cypher query that includes an EXISTS subquery and a CALL subquery. ```python result = parse(''' MATCH (n:Person) WHERE EXISTS { MATCH (n)-[:KNOWS]->(m) WHERE m.age > 30 } CALL { MATCH (x) RETURN x LIMIT 1 } RETURN n.name ''') ``` -------------------------------- ### PyCypher Parsing API Source: https://context7.com/mizzlr/pycypher/llms.txt The primary entry point for parsing Cypher queries. This function takes a Cypher query string and returns a dictionary containing the parsed AST and any syntax errors encountered during parsing. ```APIDOC ## POST /parse ### Description Parses a Cypher query string into an Abstract Syntax Tree (AST) and returns any syntax errors. ### Method POST ### Endpoint /parse ### Parameters #### Request Body - **query_string** (string) - Required - The Cypher query string to parse. ### Request Example ```json { "query_string": "MATCH (n:Person {name: \"Alice\"}) RETURN n;" } ``` ### Response #### Success Response (200) - **result** (list) - A list representing the parsed AST structure. - **errors** (list) - A list of syntax errors encountered during parsing. #### Response Example ```json { "result": [ { "node": { "parent": "MATCH", "text": "MATCH (n:Person {name: \"Alice\"})", "sourceInterval": { "start": 0, "length": 36 } }, "children": [ { "node": { "parent": "variable", "text": "n", "sourceInterval": { "start": 7, "length": 1 } } }, { "node": { "parent": "labelName", "text": "Person", "sourceInterval": { "start": 9, "length": 6 } } }, { "node": { "parent": "propertyKey", "text": "name", "sourceInterval": { "start": 18, "length": 4 } } }, { "node": { "parent": "propertyValue", "text": "\"Alice\"", "sourceInterval": { "start": 24, "length": 7 } } } ] }, { "node": { "parent": "RETURN", "text": "RETURN n", "sourceInterval": { "start": 37, "length": 8 } }, "children": [ { "node": { "parent": "variable", "text": "n", "sourceInterval": { "start": 43, "length": 1 } } } ] } ], "errors": [] } ``` ``` -------------------------------- ### Regenerate the ANTLR parser Source: https://github.com/mizzlr/pycypher/blob/master/README.md Steps to regenerate the Python parser files from the ANTLR grammar files. This involves downloading ANTLR, running the generator, and copying the output files. ```bash # Download ANTLR curl -O https://www.antlr.org/download/antlr-4.13.2-complete.jar # Generate Python files java -jar antlr-4.13.2-complete.jar \ -Dlanguage=Python3 -visitor \ grammar/CypherLexer.g4 grammar/CypherParser.g4 # Copy generated files into the package cp CypherLexer.py pycypher/lexer.py cp CypherParser.py pycypher/parser.py cp CypherParserVisitor.py pycypher/visitor.py cp CypherParserListener.py pycypher/listener.py ``` -------------------------------- ### pycypher API - parse function Source: https://github.com/mizzlr/pycypher/blob/master/README.md The `parse` function takes a Cypher query string and returns an Abstract Syntax Tree (AST) dictionary. It also provides a list of any parsing errors encountered. ```APIDOC ## POST /api/parse ### Description Parses a Cypher query string and returns an AST dictionary. ### Method POST ### Endpoint /api/parse ### Parameters #### Request Body - **query_string** (str) - Required - A Cypher query (e.g., "MATCH (n) RETURN n;") ### Request Example ```json { "query_string": "MATCH (n:Person)-[:KNOWS]->(m) WHERE m.age > 30 RETURN n.name, m.name;" } ``` ### Response #### Success Response (200) - **result** (list) - List of AST nodes. Each node has: - **node** (dict) - Dict with `parent` (rule name), `text` (source text), `sourceInterval` (token range) - **children** (dict) - Nested dict with `result` (child nodes) and `errors` (child parse errors) - **errors** (list) - List of top-level parse error nodes #### Response Example ```json { "result": [ { "node": { "parent": "query", "text": "MATCH (n:Person)-[:KNOWS]->(m) WHERE m.age > 30 RETURN n.name, m.name;", "sourceInterval": { "start": 0, "stop": 72 } }, "children": { "result": [ { "node": { "parent": "match", "text": "MATCH (n:Person)-[:KNOWS]->(m)", "sourceInterval": { "start": 0, "stop": 34 } }, "children": { "result": [ { "node": { "parent": "pattern", "text": "(n:Person)-[:KNOWS]->(m)", "sourceInterval": { "start": 6, "stop": 33 } }, "children": { "result": [ { "node": { "parent": "nodePattern", "text": "(n:Person)", "sourceInterval": { "start": 6, "stop": 15 } }, "children": { "result": [ { "node": { "parent": "variable", "text": "n", "sourceInterval": { "start": 7, "stop": 7 } }, "children": { "result": [], "errors": [] } }, { "node": { "parent": "labelName", "text": "Person", "sourceInterval": { "start": 9, "stop": 14 } }, "children": { "result": [], "errors": [] } } ], "errors": [] } }, { "node": { "parent": "relationshipPattern", "text": "-[:KNOWS]->", "sourceInterval": { "start": 16, "stop": 27 } }, "children": { "result": [ { "node": { "parent": "relationshipType", "text": "KNOWS", "sourceInterval": { "start": 18, "stop": 22 } }, "children": { "result": [], "errors": [] } }, { "node": { "parent": "variable", "text": "m", "sourceInterval": { "start": 26, "stop": 26 } }, "children": { "result": [], "errors": [] } } ], "errors": [] } } ], "errors": [] } }, { "node": { "parent": "where", "text": "WHERE m.age > 30", "sourceInterval": { "start": 35, "stop": 50 } }, "children": { "result": [ { "node": { "parent": "comparisonExpression", "text": "m.age > 30", "sourceInterval": { "start": 41, "stop": 50 } }, "children": { "result": [ { "node": { "parent": "propertyExpression", "text": "m.age", "sourceInterval": { "start": 41, "stop": 45 } }, "children": { "result": [ { "node": { "parent": "variable", "text": "m", "sourceInterval": { "start": 41, "stop": 41 } }, "children": { "result": [], "errors": [] } } ], "errors": [] } } ], "errors": [] } } ], "errors": [] } }, { "node": { "parent": "return", "text": "RETURN n.name, m.name", "sourceInterval": { "start": 52, "stop": 71 } }, "children": { "result": [ { "node": { "parent": "returnItem", "text": "n.name", "sourceInterval": { "start": 59, "stop": 64 } }, "children": { "result": [ { "node": { "parent": "propertyExpression", "text": "n.name", "sourceInterval": { "start": 59, "stop": 64 } }, "children": { "result": [ { "node": { "parent": "variable", "text": "n", "sourceInterval": { "start": 59, "stop": 59 } }, "children": { "result": [], "errors": [] } } ], "errors": [] } } ], "errors": [] } }, { "node": { "parent": "returnItem", "text": "m.name", "sourceInterval": { "start": 66, "stop": 71 } }, "children": { "result": [ { "node": { "parent": "propertyExpression", "text": "m.name", "sourceInterval": { "start": 66, "stop": 71 } }, "children": { "result": [ { "node": { "parent": "variable", "text": "m", "sourceInterval": { "start": 66, "stop": 66 } }, "children": { "result": [], "errors": [] } } ], "errors": [] } } ], "errors": [] } } ], "errors": [] } } ], "errors": [] } } ], "errors": [] } } ], "errors": [] } ``` ``` -------------------------------- ### Traverse AST Structure Recursively Source: https://context7.com/mizzlr/pycypher/llms.txt A utility function to recursively traverse the AST generated by PyCypher, printing node information. Useful for analyzing query structure. ```python from pycypher import parse def traverse_ast(node, depth=0): """Recursively traverse and print AST structure.""" indent = " " * depth node_info = node.get('node', {}) text = node_info.get('text', '') parent = node_info.get('parent', '') interval = node_info.get('sourceInterval', {}) if text: # Skip empty nodes print(f"{indent}{parent}: '{text}' at {interval}") for child in node.get('children', []): traverse_ast(child, depth + 1) # Parse and traverse result = parse('MATCH (n:Person) WHERE n.age > 25 RETURN n.name;') for top_node in result['result']: traverse_ast(top_node) ``` -------------------------------- ### Detect parse errors in invalid Cypher Source: https://github.com/mizzlr/pycypher/blob/master/README.md Shows how to parse an invalid Cypher string and check the 'errors' list in the result to detect parsing issues. ```python result = parse('THIS IS NOT VALID CYPHER') if result['errors']: print(f"Parse errors found: {len(result['errors'])}") ``` -------------------------------- ### Parse a simple Cypher query Source: https://github.com/mizzlr/pycypher/blob/master/README.md Use the parse function to convert a Cypher query string into an AST. Check the 'errors' key for any parsing issues and access the AST via the 'result' key. ```python from pycypher import parse result = parse('MATCH (n:Person)-[:KNOWS]->(m) WHERE m.age > 30 RETURN n.name, m.name;') # Check for parse errors print(result['errors']) # [] # Access the AST for node in result['result']: print(node['node']['parent'], '->', node['node']['text'][:50]) ``` -------------------------------- ### Parse Cypher Query and Access AST Source: https://context7.com/mizzlr/pycypher/llms.txt Use the `parse` function to convert a Cypher query string into an AST. Access the parsed result and any errors encountered. The AST structure can be traversed to inspect query components. ```python from pycypher import parse # Basic query parsing result = parse('MATCH (n:Person {name: "Alice"}) RETURN n;') # Access the AST structure if not result['errors']: for node in result['result']: print(f"Node type: {node['node']['parent']}") print(f"Text: {node['node']['text']}") print(f"Source interval: {node['node']['sourceInterval']}") # Traverse children recursively for child in node.get('children', []): print(f" Child: {child['node']['text']}") # Handle parsing errors gracefully invalid_result = parse('NOT VALID CYPHER ???') if invalid_result['errors']: print(f"Found {len(invalid_result['errors'])} parsing errors") # Parse complex queries with relationships relationship_query = ''' MATCH (user:User)-[:POSTED]->(post:Post) WHERE user.active = true AND post.date > $startDate WITH user, collect(post) AS posts RETURN user.name, size(posts) AS postCount ORDER BY postCount DESC LIMIT 10 ''' ast = parse(relationship_query) print(f"Parsed with {len(ast['errors'])} errors") ``` -------------------------------- ### Count Errors in AST with PyCypher Source: https://context7.com/mizzlr/pycypher/llms.txt Recursively counts errors present in a dictionary or list structure representing an AST. Handles nested structures. ```python def count_errors(obj): total = 0 if isinstance(obj, dict): total += len(obj.get('errors', [])) for v in obj.values(): total += count_errors(v) elif isinstance(obj, list): for item in obj: total += count_errors(item) return total errors = count_errors(result) print(f"Total errors in AST: {errors}") ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.