# pyorientdb
**State**
[![Build Status](https://travis-ci.org/mogui/pyorient.svg?branch=master)](https://travis-ci.org/mogui/pyorient) [![Coverage Status](https://coveralls.io/repos/mogui/pyorient/badge.svg?branch=master&service=github)](https://coveralls.io/github/mogui/pyorient?branch=master)
[Orientdb](http://www.orientechnologies.com/) driver for python that uses the binary protocol.
## Disclaimer
This fork of [`pyorient` by Ostico](https://github.com/Ostico/pyorient) is an updated version of the fork maintained by [orienttechnologies](https://github.com/orientechnologies/pyorient). Efforts were made to have the [`pyorient`](https://pypi.org/project/pyorient/) PyPI package transferred to orienttechnologies, but after a year there has been no progress (see [the GitHub issue](https://github.com/orientechnologies/pyorient/issues/34)). Additionally, orienttechnologies does not appear to be actively maintaining this driver, and I have made some small modifications to get it working with OrientDB 3.0+, **but I do not plan to actively update this fork**. Rather, I wanted to have a working PyPI package that those using Python with OrientDB can easily download and install, so I am creating a new package called `pyorientdb` using my updated fork. Any and all contributions and support are welcome.
## Installation
```bash
pip install pyorientdb
```
## Documentation
[OrientDB PyOrient Python Driver](http://orientdb.com/docs/last/PyOrient.html)
## How to run tests
- Ensure you have `ant` and `nose` installed properly
- Bootstrap orient by running `./ci/ci-start.sh` from project directory
* It will download latest orient and make some change on config and database for the tests*
- Run with `nosetests`
## Using this library with OrientDB 3.1+
As of OrientDB 3.1+, session tokens are now required for interacting with databases. You can find a brief description
of how to use [session tokens below](#persistent-connections---session-token) for older version, but now they are
enabled by default when a client is initialized:
```python
client = pyorient.OrientDB("localhost", 2424)
client.db_open("GratefulDeadConcerts", "admin", "admin")
client.command("create class my_class if not exists extends V")
client.command(f"insert into my_class (row_id, work, holiday) values (1, 'banker', 'christmas')")
client.query('select from V limit 1')
```
Note that one can connect to a database and run commands and queries within that database without a session ID. Some
methods will require creating a session ID in order to perform (e.g. checking the existence of a database or creating
a new one):
```python
client = pyorient.OrientDB("localhost", 2424)
client.db_exists("GratefulDeadConcerts")
# Results in an error: pyorient.exceptions.PyOrientSecurityException:
# com.orientechnologies.orient.enterprise.channel.binary.OTokenSecurityException - missing session and token
```
To create new databases, or perform other restricted actions, you must connect to the client with approved user
credentials:
```python
client = pyorient.OrientDB("localhost", 2424)
client.connect("root", "rootPassword")
client.db_exists("GratefulDeadConcerts")
# True
```
### Init the Client
```python
client = pyorient.OrientDB("localhost", 2424)
session_id = client.connect( "admin", "admin" )
```
### Create a DB
```python
client.db_create( db_name, pyorient.DB_TYPE_GRAPH, pyorient.STORAGE_TYPE_MEMORY )
```
### Check if a DB exists
```python
client.db_exists( db_name, pyorient.STORAGE_TYPE_MEMORY )
```
### Open a DB
```python
client.db_open( db_name, "admin", "admin" )
```
### Close a DB and destroy the connection ( by OrientDB design )
```python
client.db_close()
```
### Get the the list of databases ( needs to be connected )
```python
client.db_list()
```
### Get the size of a database ( needs a DB opened )
```python
client.db_size()
```
### Get the number of records in a database in the OrientDB Server instance
```python
client.db_count_records()
```
### Send a command
```python
cluster_id = client.command( "create class my_class extends V" )
client.command(
"insert into my_class ( 'accommodation', 'work', 'holiday' ) values( 'B&B', 'garage', 'mountain' )"
)
```
### Create a record
> **Warning** Some issues are experimented with record_create/record_upload and OrientDB < 2.0. These command are strongly discouraged with these versions
```python
rec = { '@my_class': { 'accommodation': 'house', 'work': 'office', 'holiday': 'sea' } }
rec_position = client.record_create( cluster_id, rec )
```
### Update a record
> **Warning** Some issues are experimented with record_create/record_upload and OrientDB < 2.0. These command are strongly discouraged with these versions
```python
rec3 = { '@my_class': { 'accommodation': 'hotel', 'work': 'home', 'holiday': 'hills' } }
update_success = client.record_update( rec_position._rid, rec_position._rid, rec3, rec_position._version )
```
### Load a record
```python
client.record_load( rec_position._rid )
```
### Load a record with cache
```python
def _my_callback(for_every_record):
print(for_every_record)
client.record_load( rec_position._rid, "*:-1", _my_callback )
```
### Make a query
```python
result = client.query("select from my_class", 10, '*:0')
```
### Make an Async query
```python
def _my_callback(for_every_record):
print(for_every_record)
result = client.query_async("select from my_class", 10, '*:0', _my_callback)
```
### Delete a record
```python
client.record_delete( cluster_id, rec_position._rid )
```
### Drop a DB
```python
client.db_drop( db_name )
```
### Create a new cluster
```python
new_cluster_id = client.data_cluster_add(
'my_cluster_1234567', pyorient.CLUSTER_TYPE_PHYSICAL
)
```
### Reload DB ( refresh clusters info )
```python
client.db_reload()
```
### Get the range of record ids for a cluster
```python
client.data_cluster_data_range( new_cluster_id )
```
### Get the number of records in one or more clusters
```python
client.data_cluster_count( [ 1, 2, 3, 4, 11 ] )
```
### Drop a data cluster
```python
client.data_cluster_drop( new_cluster_id )
```
### Shut down the server. Requires "shutdown" permission to be set in orientdb-server-config.xml file
```python
client.shutdown( "root", "a_super_secret_password" )
```
### Transactions
```python
### use a cluster
cluster_id = 3
### execute real create to get some info
rec = { 'accommodation': 'mountain hut', 'work': 'not!', 'holiday': 'lake' }
rec_position = client.record_create( cluster_id, rec )
tx = client.tx_commit()
tx.begin()
### create a new record
rec1 = { 'accommodation': 'home', 'work': 'some work', 'holiday': 'surf' }
rec_position1 = client.record_create( -1, rec1 )
### prepare for an update
rec2 = { 'accommodation': 'hotel', 'work': 'office', 'holiday': 'mountain' }
update_record = client.record_update( cluster_id, rec_position._rid, rec2, rec_position._version )
tx.attach( rec_position1 )
tx.attach( rec_position1 )
tx.attach( update_record )
res = tx.commit()
assert res["#3:1"].holiday == 'mountain'
assert res["#3:2"].holiday == 'surf'
assert res["#3:3"].holiday == 'surf'
```
### Execute OrientDB SQL Batch
```python
cmd = ("begin;"
"let a = create vertex set script = true;"
"let b = select from v limit 1;"
"let e = create edge from $a to $b;"
"commit retry 100;")
edge_result = self.client.batch(cmd)
```
### Persistent Connections - Session Token
Since version 27 is introduced an extension to allow use a token based session. This functionality must be enabled on the server config.
- In the first negotiation the client can ask for a token based authentication using the ```client.set_session_token``` method.
- The server will reply with a token or with an empty string meaning that it not support token based session and is using an old style session.
- For each request, the client will send the token and eventually it will get a new one if token lifetime ends.
When using the token based authentication, the connections can be shared between users of the same server.
```python
client = pyorient.OrientDB("localhost", 2424)
client.set_session_token( True ) # set true to enable the token based
authentication
client.db_open( "GratefulDeadConcerts", "admin", "admin" )
### store this token somewhere
sessionToken = client.get_session_token()
### destroy the old client, equals to another user/socket/ip ecc.
del client
### create a new client
client = pyorient.OrientDB("localhost", 2424)
### set the previous obtained token to re-attach to the old session
client.set_session_token( sessionToken )
### now the dbOpen is not needed to perform database operations
record = client.query( 'select from V where @rid = #9:1' )
### set the flag again to true if you want to renew the token
client.set_session_token( True ) # set true
client.db_open( "GratefulDeadConcerts", "admin", "admin" )
new_sessionToken = client.get_session_token()
assert sessionToken != new_sessionToken
```
### A GRAPH Example
The GRAPH representation of animals and its food
```python
import pyorientdb
client = pyorientdb.OrientDB("localhost", 2424) # host, port
### open a connection (username and password)
client.connect("admin", "admin")
### create a database
client.db_create("animals", pyorientdb.DB_TYPE_GRAPH, pyorientdb.STORAGE_TYPE_MEMORY)
### select to use that database
client.db_open("animals", "admin", "admin")
### Create the Vertex Animal
client.command("create class Animal extends V")
### Insert a new value
client.command("insert into Animal set name = 'rat', specie = 'rodent'")
### query the values
client.query("select * from Animal")
[ < OrientRecord
at
0x7f > ..., ...]
### Create the vertex and insert the food values
client.command('create class Food extends V')
client.command("insert into Food set name = 'pea', color = 'green'")
### Create the edge for the Eat action
client.command('create class Eat extends E')
### Lets the rat likes to eat pea
eat_edges = client.command(
"create edge Eat from ("
"select from Animal where name = 'rat'"
") to ("
"select from Food where name = 'pea'"
")"
)
### Who eats the peas?
pea_eaters = client.command("select expand( in( Eat )) from Food where name = 'pea'")
for animal in pea_eaters:
print(animal.name, animal.specie)
'rat rodent'
...
### What each animal eats?
animal_foods = client.command("select expand( out( Eat )) from Animal")
for food in animal_foods:
animal = client.query(
"select name from ( select expand( in('Eat') ) from Food where name = 'pea' )"
)[0]
print(food.name, food.color, animal.name)
'pea green rat'
```
## Authors
- [mogui](https://github.com/mogui/)
- [ostico](https://github.com/ostico/)
- [brucetony](https://github.com/brucetony)
Raw data
{
"_id": null,
"home_page": "https://github.com/brucetony/pyorientdb",
"name": "pyorientdb",
"maintainer": "Bruce Schultz",
"docs_url": null,
"requires_python": "",
"maintainer_email": "bschultz013@gmail.com",
"keywords": "",
"author": "Bruce Schultz",
"author_email": "bschultz013@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/d1/92/0d96a9b302d3ff6fd7a62fdc5728e825ae29b2507ae301a3af851f82d0e3/pyorientdb-1.0.0.tar.gz",
"platform": null,
"description": "# pyorientdb\n\n**State** \n[![Build Status](https://travis-ci.org/mogui/pyorient.svg?branch=master)](https://travis-ci.org/mogui/pyorient) [![Coverage Status](https://coveralls.io/repos/mogui/pyorient/badge.svg?branch=master&service=github)](https://coveralls.io/github/mogui/pyorient?branch=master)\n\n[Orientdb](http://www.orientechnologies.com/) driver for python that uses the binary protocol.\n\n## Disclaimer\nThis fork of [`pyorient` by Ostico](https://github.com/Ostico/pyorient) is an updated version of the fork maintained by [orienttechnologies](https://github.com/orientechnologies/pyorient). Efforts were made to have the [`pyorient`](https://pypi.org/project/pyorient/) PyPI package transferred to orienttechnologies, but after a year there has been no progress (see [the GitHub issue](https://github.com/orientechnologies/pyorient/issues/34)). Additionally, orienttechnologies does not appear to be actively maintaining this driver, and I have made some small modifications to get it working with OrientDB 3.0+, **but I do not plan to actively update this fork**. Rather, I wanted to have a working PyPI package that those using Python with OrientDB can easily download and install, so I am creating a new package called `pyorientdb` using my updated fork. Any and all contributions and support are welcome. \n\n## Installation\n```bash\npip install pyorientdb\n```\n\n## Documentation\n\n [OrientDB PyOrient Python Driver](http://orientdb.com/docs/last/PyOrient.html)\n\n## How to run tests\n\n- Ensure you have `ant` and `nose` installed properly\n- Bootstrap orient by running `./ci/ci-start.sh` from project directory \n * It will download latest orient and make some change on config and database for the tests*\n- Run with `nosetests`\n\n## Using this library with OrientDB 3.1+\nAs of OrientDB 3.1+, session tokens are now required for interacting with databases. You can find a brief description \nof how to use [session tokens below](#persistent-connections---session-token) for older version, but now they are \nenabled by default when a client is initialized:\n```python\nclient = pyorient.OrientDB(\"localhost\", 2424)\nclient.db_open(\"GratefulDeadConcerts\", \"admin\", \"admin\")\nclient.command(\"create class my_class if not exists extends V\")\nclient.command(f\"insert into my_class (row_id, work, holiday) values (1, 'banker', 'christmas')\")\nclient.query('select from V limit 1')\n```\n\nNote that one can connect to a database and run commands and queries within that database without a session ID. Some \nmethods will require creating a session ID in order to perform (e.g. checking the existence of a database or creating\na new one):\n```python\nclient = pyorient.OrientDB(\"localhost\", 2424)\nclient.db_exists(\"GratefulDeadConcerts\")\n# Results in an error: pyorient.exceptions.PyOrientSecurityException: \n# com.orientechnologies.orient.enterprise.channel.binary.OTokenSecurityException - missing session and token\n```\n\nTo create new databases, or perform other restricted actions, you must connect to the client with approved user \ncredentials:\n```python\nclient = pyorient.OrientDB(\"localhost\", 2424)\nclient.connect(\"root\", \"rootPassword\")\nclient.db_exists(\"GratefulDeadConcerts\")\n# True\n```\n\n\n### Init the Client\n```python\nclient = pyorient.OrientDB(\"localhost\", 2424)\nsession_id = client.connect( \"admin\", \"admin\" )\n```\n\n### Create a DB\n```python\nclient.db_create( db_name, pyorient.DB_TYPE_GRAPH, pyorient.STORAGE_TYPE_MEMORY )\n```\n\n### Check if a DB exists\n```python\nclient.db_exists( db_name, pyorient.STORAGE_TYPE_MEMORY )\n```\n\n### Open a DB\n```python\nclient.db_open( db_name, \"admin\", \"admin\" )\n```\n\n### Close a DB and destroy the connection ( by OrientDB design )\n```python\nclient.db_close()\n```\n\n### Get the the list of databases ( needs to be connected )\n```python\nclient.db_list()\n```\n\n### Get the size of a database ( needs a DB opened )\n```python\nclient.db_size()\n```\n\n### Get the number of records in a database in the OrientDB Server instance\n```python\nclient.db_count_records()\n```\n\n### Send a command\n```python\ncluster_id = client.command( \"create class my_class extends V\" )\nclient.command(\n \"insert into my_class ( 'accommodation', 'work', 'holiday' ) values( 'B&B', 'garage', 'mountain' )\"\n)\n```\n\n### Create a record\n> **Warning** Some issues are experimented with record_create/record_upload and OrientDB < 2.0. These command are strongly discouraged with these versions\n\n```python\nrec = { '@my_class': { 'accommodation': 'house', 'work': 'office', 'holiday': 'sea' } }\nrec_position = client.record_create( cluster_id, rec )\n```\n### Update a record\n> **Warning** Some issues are experimented with record_create/record_upload and OrientDB < 2.0. These command are strongly discouraged with these versions\n\n```python\nrec3 = { '@my_class': { 'accommodation': 'hotel', 'work': 'home', 'holiday': 'hills' } }\nupdate_success = client.record_update( rec_position._rid, rec_position._rid, rec3, rec_position._version )\n```\n\n### Load a record\n```python\nclient.record_load( rec_position._rid )\n```\n\n### Load a record with cache\n```python\ndef _my_callback(for_every_record):\n print(for_every_record)\n\nclient.record_load( rec_position._rid, \"*:-1\", _my_callback )\n```\n\n### Make a query\n```python\nresult = client.query(\"select from my_class\", 10, '*:0')\n```\n\n### Make an Async query\n```python\ndef _my_callback(for_every_record):\n print(for_every_record)\n\nresult = client.query_async(\"select from my_class\", 10, '*:0', _my_callback)\n```\n\n### Delete a record\n```python\nclient.record_delete( cluster_id, rec_position._rid )\n```\n\n### Drop a DB\n```python\nclient.db_drop( db_name )\n```\n\n### Create a new cluster\n```python\nnew_cluster_id = client.data_cluster_add(\n 'my_cluster_1234567', pyorient.CLUSTER_TYPE_PHYSICAL\n)\n```\n\n### Reload DB ( refresh clusters info )\n```python\nclient.db_reload()\n```\n\n### Get the range of record ids for a cluster\n```python\nclient.data_cluster_data_range( new_cluster_id )\n```\n\n### Get the number of records in one or more clusters\n```python\nclient.data_cluster_count( [ 1, 2, 3, 4, 11 ] )\n```\n\n### Drop a data cluster\n```python\nclient.data_cluster_drop( new_cluster_id )\n```\n\n### Shut down the server. Requires \"shutdown\" permission to be set in orientdb-server-config.xml file\n```python\nclient.shutdown( \"root\", \"a_super_secret_password\" )\n```\n\n### Transactions\n```python\n### use a cluster\ncluster_id = 3\n\n### execute real create to get some info\nrec = { 'accommodation': 'mountain hut', 'work': 'not!', 'holiday': 'lake' }\nrec_position = client.record_create( cluster_id, rec )\n\ntx = client.tx_commit()\ntx.begin()\n\n### create a new record\nrec1 = { 'accommodation': 'home', 'work': 'some work', 'holiday': 'surf' }\nrec_position1 = client.record_create( -1, rec1 )\n\n### prepare for an update\nrec2 = { 'accommodation': 'hotel', 'work': 'office', 'holiday': 'mountain' }\nupdate_record = client.record_update( cluster_id, rec_position._rid, rec2, rec_position._version )\n\ntx.attach( rec_position1 )\ntx.attach( rec_position1 )\ntx.attach( update_record )\nres = tx.commit()\n\nassert res[\"#3:1\"].holiday == 'mountain'\nassert res[\"#3:2\"].holiday == 'surf'\nassert res[\"#3:3\"].holiday == 'surf'\n```\n\n### Execute OrientDB SQL Batch\n```python\ncmd = (\"begin;\"\n \"let a = create vertex set script = true;\"\n \"let b = select from v limit 1;\"\n \"let e = create edge from $a to $b;\"\n \"commit retry 100;\")\n\n edge_result = self.client.batch(cmd)\n```\n\n### Persistent Connections - Session Token\nSince version 27 is introduced an extension to allow use a token based session. This functionality must be enabled on the server config.\n\n- In the first negotiation the client can ask for a token based authentication using the ```client.set_session_token``` method.\n- The server will reply with a token or with an empty string meaning that it not support token based session and is using an old style session.\n- For each request, the client will send the token and eventually it will get a new one if token lifetime ends.\n\nWhen using the token based authentication, the connections can be shared between users of the same server.\n```python\nclient = pyorient.OrientDB(\"localhost\", 2424)\nclient.set_session_token( True ) # set true to enable the token based\nauthentication\nclient.db_open( \"GratefulDeadConcerts\", \"admin\", \"admin\" )\n\n### store this token somewhere\nsessionToken = client.get_session_token()\n\n### destroy the old client, equals to another user/socket/ip ecc.\ndel client\n\n### create a new client\nclient = pyorient.OrientDB(\"localhost\", 2424)\n\n### set the previous obtained token to re-attach to the old session\nclient.set_session_token( sessionToken )\n\n### now the dbOpen is not needed to perform database operations\nrecord = client.query( 'select from V where @rid = #9:1' )\n\n### set the flag again to true if you want to renew the token\nclient.set_session_token( True ) # set true\nclient.db_open( \"GratefulDeadConcerts\", \"admin\", \"admin\" )\nnew_sessionToken = client.get_session_token()\n\nassert sessionToken != new_sessionToken\n```\n\n### A GRAPH Example\n\nThe GRAPH representation of animals and its food\n\n```python\nimport pyorientdb\n\nclient = pyorientdb.OrientDB(\"localhost\", 2424) # host, port\n\n### open a connection (username and password)\nclient.connect(\"admin\", \"admin\")\n\n### create a database\nclient.db_create(\"animals\", pyorientdb.DB_TYPE_GRAPH, pyorientdb.STORAGE_TYPE_MEMORY)\n\n### select to use that database\nclient.db_open(\"animals\", \"admin\", \"admin\")\n\n### Create the Vertex Animal\nclient.command(\"create class Animal extends V\")\n\n### Insert a new value\nclient.command(\"insert into Animal set name = 'rat', specie = 'rodent'\")\n\n### query the values\nclient.query(\"select * from Animal\")\n[ < OrientRecord\nat\n0x7f > ..., ...]\n\n### Create the vertex and insert the food values\n\nclient.command('create class Food extends V')\nclient.command(\"insert into Food set name = 'pea', color = 'green'\")\n\n### Create the edge for the Eat action\nclient.command('create class Eat extends E')\n\n### Lets the rat likes to eat pea\neat_edges = client.command(\n \"create edge Eat from (\"\n \"select from Animal where name = 'rat'\"\n \") to (\"\n \"select from Food where name = 'pea'\"\n \")\"\n)\n\n### Who eats the peas?\npea_eaters = client.command(\"select expand( in( Eat )) from Food where name = 'pea'\")\nfor animal in pea_eaters:\n print(animal.name, animal.specie)\n'rat rodent'\n...\n\n### What each animal eats?\nanimal_foods = client.command(\"select expand( out( Eat )) from Animal\")\nfor food in animal_foods:\n animal = client.query(\n \"select name from ( select expand( in('Eat') ) from Food where name = 'pea' )\"\n )[0]\n print(food.name, food.color, animal.name)\n'pea green rat'\n```\n\n## Authors\n- [mogui](https://github.com/mogui/)\n- [ostico](https://github.com/ostico/)\n- [brucetony](https://github.com/brucetony)\n",
"bugtrack_url": null,
"license": "Apache-2.0",
"summary": "OrientDB native client library",
"version": "1.0.0",
"project_urls": {
"Homepage": "https://github.com/brucetony/pyorientdb",
"Issue Tracker": "https://github.com/brucetony/pyorientdb/issues",
"Source Code": "https://github.com/brucetony/pyorientdb"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "ea9b2ea28c9f13fdd09e4080040f958560f8579bc4dc10d683428fbee31a6123",
"md5": "c586857bfeabb5a6841671d3b67e3b8e",
"sha256": "73213c1bbe0ebd4057d9670bb9cca3416a73b2057f49c7867b184fa62fd1e392"
},
"downloads": -1,
"filename": "pyorientdb-1.0.0-py2.py3-none-any.whl",
"has_sig": false,
"md5_digest": "c586857bfeabb5a6841671d3b67e3b8e",
"packagetype": "bdist_wheel",
"python_version": "py2.py3",
"requires_python": null,
"size": 85714,
"upload_time": "2022-07-13T12:05:44",
"upload_time_iso_8601": "2022-07-13T12:05:44.139291Z",
"url": "https://files.pythonhosted.org/packages/ea/9b/2ea28c9f13fdd09e4080040f958560f8579bc4dc10d683428fbee31a6123/pyorientdb-1.0.0-py2.py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "d1920d96a9b302d3ff6fd7a62fdc5728e825ae29b2507ae301a3af851f82d0e3",
"md5": "a20664a76790211ac0befee0e0af879e",
"sha256": "5e08668792d69a9477aafb150ca78b99d1cf89a23f088bb93b3d905e4e43a7cb"
},
"downloads": -1,
"filename": "pyorientdb-1.0.0.tar.gz",
"has_sig": false,
"md5_digest": "a20664a76790211ac0befee0e0af879e",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 140215,
"upload_time": "2022-07-13T12:05:46",
"upload_time_iso_8601": "2022-07-13T12:05:46.274874Z",
"url": "https://files.pythonhosted.org/packages/d1/92/0d96a9b302d3ff6fd7a62fdc5728e825ae29b2507ae301a3af851f82d0e3/pyorientdb-1.0.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2022-07-13 12:05:46",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "brucetony",
"github_project": "pyorientdb",
"travis_ci": true,
"coveralls": false,
"github_actions": false,
"tox": true,
"lcname": "pyorientdb"
}