mygraph-client (Python)
Python client for the MyGraph server. It talks to the server over TCP using MyGraph protocol v1 (PROTOCOL.md) and needs only the standard library (Python ≥ 3.10).
Install
The package is on PyPI as mygraph-client:
pip install mygraph-client
The import name is mygraph:
import mygraph
For development, from the repository root:
pip install -e python/
Start a server
cargo run -p mygraph-server -- start # 127.0.0.1:6660, in memory
cargo run -p mygraph-server -- start --port 6660 --data ./data
Command line client
pip install also installs the mygraph-client command. With a server on
port 6660 (for example docker compose up -d):
mygraph-client "MATCH (n) RETURN n;"
n
(0:User {"age": 25, "name": "Alice"})
(1:User {"name": "Bob"})
Without a query argument the script is read from stdin, so multi-line queries work too:
mygraph-client <<'CYPHER'
MATCH (n)
RETURN n;
CYPHER
| Option | Default | |
|---|---|---|
--host HOST |
localhost |
Server host |
--port PORT |
6660 |
Server port |
--json |
off | One JSON object per record |
Without installing, python3 -m mygraph does the same. On error it prints
the message to stderr and exits with status 1.
Usage
import mygraph
with mygraph.connect("localhost", 6660) as db:
# Any Cypher, with parameters as a dict and/or keyword arguments
r = db.run("MATCH (u:User) WHERE u.age > $min RETURN u.name AS name", min=18)
for record in r: # records are dicts
print(record["name"])
r.value("name"); r.values("name"); r.single(); r.stats.nodes_created
# Create
alice = db.create_node("User", {"name": "Alice", "age": 25}) # -> Node
bob = db.create_node(["User", "Admin"], {"name": "Bob"})
knows = db.create_relationship(alice.id, bob.id, "KNOWS", {"since": 2020})
# Search
db.get_node(alice.id) # Node | None
db.find_nodes("User", {"name": "Alice"}, order_by="age", limit=10) # list[Node]
db.count_nodes("User")
db.find_relationships("KNOWS", start_id=alice.id) # list[Relationship]
# Update
db.update_node(alice.id, {"age": 26}) # merge: SET n += $props (None removes a key)
db.update_node(alice.id, {"name": "Alicia"}, replace=True) # SET n = $props
db.update_node(alice.id, add_labels="VIP", remove_labels="Admin")
db.update_relationship(knows.id, {"since": 2021})
# Delete
db.delete_relationship(knows.id)
db.delete_node(alice.id) # DETACH DELETE by default
db.delete_nodes("User", {"name": "Bob"}) # returns how many
# Transactions: commit on exit, rollback on exception
with db.transaction() as tx:
tx.create_node("User", {"name": "Carol"})
tx.run("MATCH (u:User {name: 'Carol'}) SET u.vip = true")
# Databases and schemas (the current one is per connection)
db.create_database("shop"); db.use_database("shop"); db.databases()
Node has id, labels, properties (and node["key"]). Relationship
has id, start_node, end_node, type, properties. Path (from
RETURN p of a named or shortest path) has nodes, relationships,
start, end, and len(path) is its length in relationships.
Helpers write labels, types and property keys as backtick-quoted identifiers, and always send values as parameters, so user input is never spliced into the query text.
Errors
| Exception | When |
|---|---|
CypherSyntaxError |
Invalid Cypher (.line, .column) |
NotFoundError, AlreadyExistsError |
Unknown or duplicate database/schema |
TransactionError |
e.g. COMMIT with no open transaction |
ConstraintError |
A write broke a unique or not-null constraint; the statement was undone |
QueryError |
Base class of the above; .code holds the engine error kind |
ProtocolError |
The server or the client broke protocol v1 |
ConnectionClosedError |
Cannot connect, or the connection was lost/closed |
An error in a statement does not close the connection.
Notes for MyGraph v0.1
- An open transaction blocks every other connection until it commits or rolls back. Keep transactions short.
- While a transaction is open, everything sent on that client runs inside it.
- A client serializes its requests with a lock. Threads that share one client also share its current database and transaction, so use one client per thread for independent work.
AUTHis accepted but not checked yet (no users or roles on the server).
Tests
cd python
python3 -m unittest discover -s tests -t .
The integration tests build mygraph-server with cargo and start it on a
free port. Set MYGRAPH_SERVER_BIN to use an existing binary instead.
Releasing to PyPI
The workflow .github/workflows/pypi.yml
publishes the package when a tag that starts with py-v is pushed. It uses
PyPI trusted publishing, so no API token or password is stored in GitHub.
-
Increase
versioninpyproject.tomland__version__inmygraph/_version.py(a test checks that they are equal), for example0.2.0→0.2.1. PyPI does not accept a version number twice, even after you delete a release. -
Commit and push the change to
main. -
Create and push a tag with the same version:
git tag py-v0.1.1 git push origin py-v0.1.1
-
Check the run in the repository's Actions tab. When it finishes, the new version is on PyPI.
To check the package locally before you tag:
cd python
uv build
uvx twine check dist/*
The trusted publisher on PyPI is set for repository
julioacontreras/my-graph, workflow pypi.yml and environment pypi.
If you rename one of these, update the publisher in the project's
Publishing settings on PyPI. If you don't, the upload fails with
invalid-publisher.
Metadata
Release files for mygraph-client 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| mygraph_client-0.3.0.tar.gz | 20.8 kB | With provenance | Details for mygraph_client-0.3.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| mygraph_client-0.3.0-py3-none-any.whl | Python 3 | none | any | Details for mygraph_client-0.3.0-py3-none-any.whl |
Total release size: 38.8 kB
Release files / mygraph_client-0.3.0.tar.gz
| Download URL | mygraph_client-0.3.0.tar.gz |
|---|---|
| Size | 20.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
95208eb07f5975a4fa8e6d3566d8ff8e6f665a6dd53da3713ca17d8d99ae3517
|
|
BLAKE2b-256 checksum How to use checksums |
01d900831ae58525cb9496275530aa4efb778ad3a231b7c79174902b7b796dcd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 13, 2026.
Transparency logRelease files / mygraph_client-0.3.0-py3-none-any.whl
| Download URL | mygraph_client-0.3.0-py3-none-any.whl |
|---|---|
| Size | 18.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0c55016da86a2ecf1861ab8d7062caf7baa64eb81b0d3627e6c49b7ecd5552e8
|
|
BLAKE2b-256 checksum How to use checksums |
56edbba1c5975cf2766bbd927ad3ccf9a1941a4108fc1efbfbfcfa6e4b4135f6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 13, 2026.
Transparency logSecurity for mygraph-client 0.3.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
Both files in this release have been uploaded with provenance metadata.
Attestation for mygraph_client-0.3.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 13, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.