Repository: ziyasal/pyley
Branch: master
Commit: a2b961abfd5f
Files: 18
Total size: 26.5 KB
Directory structure:
gitextract_tu09thrq/
├── .appveyor.sh
├── .gitignore
├── .travis.sh
├── .travis.yml
├── MANIFEST.in
├── README.rst
├── UNLICENSE
├── appveyor.yml
├── pyley/
│ ├── __init__.py
│ └── pyley.py
├── requirements.testing.txt
├── requirements.txt
├── setup.cfg
├── setup.py
├── tests/
│ ├── __init__.py
│ ├── test_cayley_client.py
│ └── test_gizmo_query.py
└── tox.ini
================================================
FILE CONTENTS
================================================
================================================
FILE: .appveyor.sh
================================================
appveyor DownloadFile https://github.com/cayleygraph/cayley/releases/download/v0.7.0/cayley_0.7.0_windows_amd64.zip -Timeout 5000
7z x cayley_0.7.0_windows_amd64.zip cayley_0.7.0_windows_amd64
cd /?
cd cayley_0.7.0_windows_amd64
cd /?
dir /a
cayley.exe http --dbpath=30kmoviedata.nq.gz &
sleep 2
================================================
FILE: .gitignore
================================================
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
# C extensions
*.so
#PyCharm project folder
.idea/
# Distribution / packaging
.Python
env/
bin/
build/
develop-eggs/
dist/
eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.cache
nosetests.xml
coverage.xml
# Translations
*.mo
# Mr Developer
.mr.developer.cfg
.project
.pydevproject
# Rope
.ropeproject
# Django stuff:
*.log
*.pot
# Sphinx documentation
docs/_build/
================================================
FILE: .travis.sh
================================================
#!/bin/bash
wget https://github.com/cayleygraph/cayley/releases/download/v0.7.0/cayley_0.7.0_linux_amd64.tar.gz
tar -xvzf cayley_0.7.0_linux_amd64.tar.gz
cd cayley_0.7.0_linux_amd64
./cayley http --dbpath=30kmoviedata.nq.gz &
sleep 2
================================================
FILE: .travis.yml
================================================
language: python
python:
- "2.7"
- "3.4"
- "3.5"
- "3.6"
- "3.7"
- "3.8"
before_script:
- /bin/bash ./.travis.sh
install:
- pip install -r requirements.txt
- pip install -r requirements.testing.txt
- pip install .
script:
- nosetests --with-coverage --cover-package=pyley
after_success:
- coveralls
================================================
FILE: MANIFEST.in
================================================
include README.md
================================================
FILE: README.rst
================================================
.. image:: https://github.com/ziyasal/pyley/raw/master/pyley.png?raw=true
pyley
=====
.. image:: https://img.shields.io/pypi/v/pyley.svg
:target: https://pypi.org/project/pyley
.. image:: https://img.shields.io/pypi/pyversions/pyley.svg
:target: https://pypi.org/project/pyley
.. image:: https://travis-ci.org/ziyasal/pyley.svg?branch=master
:target: https://travis-ci.org/ziyasal/pyley
.. image:: https://coveralls.io/repos/ziyasal/pyley/badge.svg?branch=master&service=github
:target: https://coveralls.io/github/ziyasal/pyley?branch=master
`Python <https://www.python.org/>`_ client for an open-source graph database **Cayley** `<https://github.com/google/cayley>`_.
Cayley is an open-source graph inspired by the graph database behind `Freebase <http://freebase.com/>`_ and Google's `Knowledge Graph <http://www.google.com/insidesearch/features/search/knowledge.html>`_. Its goal is to be a part of the developer's toolbox where `Linked Data <http://linkeddata.org/>`_ and graph-shaped data (semantic webs, social networks, etc) in general are concerned.
Install via pip
---------------
You can install pyley using::
$ pip install pyley
Sample
------
**Import pyley:**
.. code-block:: python
from pyley import CayleyClient, GraphObject
# Create cayley client
# this creates client with default parameters `http://localhost:64210/api/v1/query/gizmo`
client = CayleyClient()
# or specify `url` and `version` parameters
client = CayleyClient("http://localhost:64210", "v1")
g = GraphObject()
# Query all vertices in the graph, limit to the first 5 vertices found.
g.Vertex().GetLimit(5)
# Start with only one vertex, the literal name "Humphrey Bogart", and retrieve all of them.
query = g.Vertex("Humphrey Bogart").All();
response = client.Send(query)
# response.result contains JSON data and response.r contains raw response
print response.result
# `g` and `V` are synonyms for `graph` and `Vertex` respectively, as they are quite common.
query = g.V("Humphrey Bogart").All()
response = client.Send(query)
# "Humphrey Bogart" is a name, but not an entity.
# Let's find the entities with this name in our dataset.
# Follow links that are pointing In to our "Humphrey Bogart" node with the predicate "name".
query = g.V("Humphrey Bogart").In("<name>").All()
response = client.Send(query)
# Notice that "name" is a generic predicate in our dataset.
# Starting with a movie gives a similar effect.
query = g.V("Casablanca").In("name").All()
response = client.Send(query)
# Relatedly, we can ask the reverse; all ids with the name "Casablanca"
query = g.V().Has("name", "Casablanca").All()
response = client.Send(query)
# Let's get the list of actors in the film
query = g.V().Has("name", "Casablanca") \
.Out("/film/film/starring") \
.Out("/film/performance/actor") \
.Out("name") \
.All()
response = client.Send(query)
# But this is starting to get long.
# Let's use a morphism -- a pre-defined path stored in a variable -- as our linkage
film_to_actor = g.Morphism().Out("/film/film/starring").Out("/film/performance/actor")
query = g.V() \
.Has("name", "Casablanca") \
.Follow(film_to_actor) \
.Out("name") \
.All()
response = client.Send(query)
# Add data programatically to the JSON result list. Can be any JSON type.
query = g.Emit({'name': "John Doe", 'age': 41, 'isActor': True})
response = client.Send(query)
Bugs
----
If you encounter a bug, performance issue, or malfunction, please add an `Issues <https://github.com/ziyasal/pyley/issues>`_ with steps on how to reproduce the problem
or feel to free to open a pull request.
TODO
----
- Improve Gizmo implementation (Basic steps implemented at the moment)
- Add more tests
- Add more documentation
Open Source Projects in Use
----------------------------
- `requests <https://github.com/kennethreitz/requests>`_ by @kennethreitz
License
-------
@ziλasal & @abdullahselek
================================================
FILE: UNLICENSE
================================================
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>
================================================
FILE: appveyor.yml
================================================
environment:
matrix:
- PYTHON: "C:\\Python27"
- PYTHON: "C:\\Python34"
- PYTHON: "C:\\Python35"
- PYTHON: "C:\\Python27-x64"
DISTUTILS_USE_SDK: "1"
- PYTHON: "C:\\Python34-x64"
DISTUTILS_USE_SDK: "1"
- PYTHON: "C:\\Python35-x64"
- PYTHON: "C:\\Python36-x64"
DIR_CAYLEY: C:\cayley
cache:
- '%DIR_CAYLEY% -> appveyor.yml'
install:
- set PATH=%PYTHON%;%PYTHON%\Scripts;C:\OpenSSL-Win64;%DIR_CAYLEY%;%SystemRoot%\system32;%PATH%
- if not exist %DIR_CAYLEY% (
appveyor DownloadFile https://github.com/cayleygraph/cayley/releases/download/v0.7.0/cayley_0.7.0_windows_amd64.zip &&
7z x cayley_0.7.0_windows_amd64.zip -y -aoa -oC:\ > NULs
)
# - appveyor DownloadFile https://github.com/cayleygraph/cayley/releases/download/v0.7.0/cayley_0.7.0_windows_amd64.zip -Timeout 5000
# - 7z x cayley_0.7.0_windows_amd64.zip cayley_0.7.0_windows_amd64
# - cd cayley_0.7.0_windows_amd64
- ps: $CayleyProcess = Start-Process "cayley http --dbpath=30kmoviedata.nq.gz" -PassThru
# We need wheel installed to build wheels
- "%PYTHON%\\python.exe -m pip install wheel"
- "%PYTHON%\\python.exe -m pip install -r requirements.txt"
- "%PYTHON%\\python.exe -m pip install -r requirements.testing.txt"
build: off
test_script:
- "%PYTHON%\\python.exe -m nose --with-coverage --cover-package=pyley"
after_test:
# This step builds your wheels.
- "%PYTHON%\\python.exe setup.py bdist_wheel"
artifacts:
# bdist_wheel puts your built wheel in the dist directory
- path: dist\*
on_finish:
- ps: Stop-Process -Id $CayleyProcess.Id
================================================
FILE: pyley/__init__.py
================================================
"""pyley Python client for an open-source graph database Cayley"""
__title__ = 'pyley'
__version__ = '0.2.2.2'
__author__ = 'Ziya SARIKAYA @ziyasal'
__email__ = 'sarikayaziya@gmail.com',
__license__ = 'MIT License'
__copyright__ = 'Copyright 2014 Ziya SARIKAYA @ziyasal'
__url__ = 'https://github.com/ziyasal/pyley'
__download_url__ = 'https://pypi.org/pypi/pyley'
__description__ = 'Python client for an open-source graph database Cayley'
from .pyley import (
CayleyResponse,
CayleyClient,
GraphObject
)
================================================
FILE: pyley/pyley.py
================================================
import json
import requests
class CayleyResponse(object):
def __init__(self, raw_response, result):
self.r = raw_response
self.result = result
class CayleyClient(object):
def __init__(self, url="http://localhost:64210", version="v1"):
self.url = "%s/api/%s/query/gizmo" % (url, version)
self.write_url = "%s/api/%s/write" % (url, version)
self.delete_url = "%s/api/%s/delete" % (url, version)
def add_query_limit(self, limit):
if isinstance(limit, int):
self.url = self.url + '?limit=' + str(limit)
else:
raise Exception("Invalid parameter for adding query limit, should be integer.")
def Send(self, query):
if isinstance(query, str):
r = requests.post(self.url, data=query.encode('utf-8'))
return CayleyResponse(r, r.json())
elif isinstance(query, _GizmoQuery):
r = requests.post(self.url, data=str(query).encode('utf-8'))
return CayleyResponse(r, r.json())
else:
raise Exception("Invalid query parameter in Send")
def AddQuad(self, subject, predicate, object_, label=None):
return self.AddQuads([(subject, predicate, object_, label)])
def AddQuads(self, quads):
quads = [
{
"subject": q[0],
"predicate": q[1],
"object": q[2],
"label": None if len(q) < 4 else q[3]
}
for q in quads
]
r = requests.post(self.write_url, json=quads)
return CayleyResponse(r, r.json())
def DeleteQuad(self, subject, predicate, object_, label=None):
return self.DeleteQuads([(subject, predicate, object_, label)])
def DeleteQuads(self, quads):
quads = [
{
"subject": q[0],
"predicate": q[1],
"object": q[2],
"label": None if len(q) < 4 else q[3]
}
for q in quads
]
r = requests.post(self.delete_url, json=quads)
return CayleyResponse(r, r.json())
class _GizmoQuery(object):
queryDeclarations = None
def __init__(self):
self.queryDeclarations = []
def __str__(self):
return ".".join([str(d) for d in self.queryDeclarations])
def _put(self, token, *parameters):
q = _QueryDefinition(token, *parameters)
self.queryDeclarations.append(q)
class GraphObject(object):
def V(self):
return _Vertex("g.V()")
def V(self, *node_ids):
builder = []
l = len(node_ids)
for index, node_id in enumerate(node_ids):
if index == l - 1:
builder.append(u"'{0:s}'".format(node_id))
else:
builder.append(u"'{0:s}',".format(node_id))
return _Vertex(u"g.V({0:s})".format("".join(builder)))
def M(self):
return _Morphism("g.Morphism()")
def Vertex(self):
return self.V()
def Vertex(self, *node_ids):
if len(node_ids) == 0:
return self.V()
return self.V(*node_ids)
def Morphism(self):
return self.M()
def Emit(self, data):
return "g.Emit({0:s})".format(json.dumps(data, default=lambda o: o.__dict__, sort_keys=True))
class _Path(_GizmoQuery):
def __init__(self, parent):
_GizmoQuery.__init__(self)
self._put(parent)
def Out(self, predicate=None, tags=None):
self._bounds("Out", predicate, tags)
return self
def In(self, predicate=None, tags=None):
self._bounds("In", predicate, tags)
return self
def Both(self, predicate=None, tags=None):
self._bounds("Both", predicate, tags)
return self
def _bounds(self, method, predicate=None, tags=None):
if predicate is None and tags is None:
self._put("%s()", method)
elif tags is None:
self._put("%s(%s)", method, self._format_input_bounds(predicate))
else:
self._put(
"%s(%s, %s)",
method,
self._format_input_bounds(predicate),
self._format_input_bounds(tags)
)
return self
def _format_input_bounds(self, value):
if type(value) is dict:
return json.dumps(value)
if type(value) is str:
return "'%s'" % value
if value is None:
return 'null'
return value
def Is(self, *nodes):
self._put("Is('%s')", "', '".join(nodes))
return self
def Has(self, predicate, object):
self._put("Has('%s', '%s')", predicate, object)
return self
def HasR(self, predicate, object):
self._put("Has('%s', '%s')", object, predicate)
return self
def Tag(self, *tags):
self._put("Tag(%s)", json.dumps(tags))
return self
def Back(self, tag):
self._put("Back('%s')", tag)
return self
def Save(self, predicate, tag):
self._put("Save('%s', '%s')", predicate, tag)
return self
def Intersect(self, query):
if not isinstance(query, _Vertex) and type(query) is not str:
raise Exception("Invalid parameter in intersect query")
self._put("Intersect(%s)", query)
return self
def Union(self, query):
if not isinstance(query, _Vertex) and type(query) is not str:
raise Exception("Invalid parameter in union query")
self._put("Union(%s)", query)
return self
def Follow(self, query):
if not isinstance(query, _Morphism) and type(query) is not str:
raise Exception("Invalid parameter in follow query")
self._put("Follow(%s)", query)
return self
def FollowR(self, query):
if not isinstance(query, _Morphism) and type(query) is not str:
raise Exception("Invalid parameter in followr query")
self._put("FollowR(%s)", query)
return self
def build(self):
return str(self)
class _Vertex(_Path):
def All(self):
self._put("All()")
return self
def GetLimit(self, limit):
self._put("GetLimit(%d)", limit)
return self
class _Morphism(_Path):
pass
class _QueryDefinition(object):
def __init__(self, token, *parameters):
self.token = token
self.parameters = parameters
def __str__(self):
if len(self.parameters) > 0:
return str(self.token) % self.parameters
else:
return str(self.token)
================================================
FILE: requirements.testing.txt
================================================
python-coveralls
coverage
nose
================================================
FILE: requirements.txt
================================================
requests
================================================
FILE: setup.cfg
================================================
[bdist_wheel]
universal = 1
[aliases]
test = nosetest
[check-manifest]
ignore =
.travis.yml
================================================
FILE: setup.py
================================================
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import absolute_import, print_function
import os
import re
import codecs
from setuptools import setup, find_packages
cwd = os.path.abspath(os.path.dirname(__file__))
def read(filename):
with codecs.open(os.path.join(cwd, filename), 'rb', 'utf-8') as h:
return h.read()
metadata = read(os.path.join(cwd, 'pyley', '__init__.py'))
def extract_metaitem(meta):
meta_match = re.search(r"""^__{meta}__\s+=\s+['\"]([^'\"]*)['\"]""".format(meta=meta),
metadata, re.MULTILINE)
if meta_match:
return meta_match.group(1)
raise RuntimeError('Unable to find __{meta}__ string.'.format(meta=meta))
setup(
name='pyley',
version=extract_metaitem('version'),
license=extract_metaitem('license'),
description=extract_metaitem('description'),
long_description=(read('README.rst')),
author=extract_metaitem('author'),
author_email=extract_metaitem('email'),
url=extract_metaitem('url'),
download_url=extract_metaitem('download_url'),
packages=find_packages(exclude=('tests')),
platforms=['Any'],
install_requires=['requests'],
tests_require=['python-coveralls', 'coverage', 'nose'],
keywords='graph database, cayley, cayley python client, client',
include_package_data=True,
classifiers=[
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
'Operating System :: OS Independent',
'Topic :: Software Development :: Libraries :: Python Modules',
'Programming Language :: Python',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
],
)
================================================
FILE: tests/__init__.py
================================================
================================================
FILE: tests/test_cayley_client.py
================================================
from unittest import TestCase
from pyley import CayleyClient, GraphObject
_CLIENT_URL = 'http://localhost:64210'
class CayleyClientTests(TestCase):
def test_add_limit(self):
client = CayleyClient(_CLIENT_URL)
client.add_query_limit(10000)
self.assertEqual(client.url, 'http://localhost:64210/api/v1/query/gizmo?limit=10000')
def test_add_limit_fails(self):
client = CayleyClient(_CLIENT_URL)
with self.assertRaises(Exception):
client.add_query_limit('str')
def test_send(self):
client = CayleyClient(_CLIENT_URL)
g = GraphObject()
query = g.V().Has("name", "Casablanca") \
.Out("/film/film/starring") \
.Out("/film/performance/actor") \
.Out("name") \
.All()
response = client.Send(query)
self.assertTrue(response.r.status_code == 200)
self.assertTrue(response.r is not None)
self.assertTrue(len(response.result) > 0)
query = g.V().HasR("name", "Casablanca") \
.Out("/film/film/starring") \
.Out("/film/performance/actor") \
.Out("name") \
.All()
response = client.Send(query)
self.assertTrue(response.r.status_code == 200)
self.assertTrue(response.r is not None)
self.assertTrue(len(response.result) > 0)
def test_a_add_quad(self):
client = CayleyClient(_CLIENT_URL)
response = client.AddQuad('foo', 'to', 'bar')
self.assertEqual(response.r.status_code, 200)
g = GraphObject()
query = g.V("foo").Out('to').Is('bar').All()
response = client.Send(query)
self.assertEqual(len(response.result['result']), 1)
def test_b_delete_quad(self):
client = CayleyClient(_CLIENT_URL)
response = client.DeleteQuad('foo', 'to', 'bar')
self.assertEqual(response.r.status_code, 200)
g = GraphObject()
query = g.V("foo").Out('to').Is("bar").All()
response = client.Send(query)
self.assertIsNone(response.result['result'])
def test_c_add_quads(self):
client = CayleyClient(_CLIENT_URL)
response = client.AddQuads([
('foo', 'to', 'bar'),
('baz', 'from', 'quux')
])
self.assertEqual(response.r.status_code, 200)
g = GraphObject()
query = g.V("foo").Out('to').Is("bar").Union(
g.V("baz").Out('from').Is("quux")
).All()
response = client.Send(query)
self.assertEqual(len(response.result['result']), 2)
def test_d_delete_quads(self):
client = CayleyClient(_CLIENT_URL)
response = client.DeleteQuads([
('foo', 'to', 'bar'),
('baz', 'from', 'quux')
])
self.assertEqual(response.r.status_code, 200)
g = GraphObject()
query = g.V("foo").Out('to').Is("bar").Union(
g.V("baz").Out('from').Is('quux')
).All()
response = client.Send(query)
self.assertIsNone(response.result['result'])
================================================
FILE: tests/test_gizmo_query.py
================================================
import unittest
from pyley import GraphObject
class GizmoQueryTests(unittest.TestCase):
def setUp(self):
self.opts = dict(url='http://localhost:64210/api/v1/query/gizmo')
def test_vertex_query(self):
g = GraphObject()
query = g.Vertex()
self.assertEqual(query.build(), "g.V()")
def test_vertex_query_with_parameters(self):
g = GraphObject()
query = g.V("Humphrey Bogart")
actual = query.build()
self.assertEqual(actual, "g.V('Humphrey Bogart')")
def test_morphism_query(self):
g = GraphObject()
query = g.Morphism()
self.assertEqual(query.build(), "g.Morphism()")
def test_out_query(self):
g = GraphObject()
query = g.V().Out('name')
actual = query.build()
self.assertEqual(actual, "g.V().Out('name')")
def test_out_query_with_predicate(self):
g = GraphObject()
query = g.V().Out(g.Vertex())
actual = query.build()
self.assertEqual(actual, "g.V().Out(g.V())")
def test_out_query_with_predicate_as_dict_and_label(self):
g = GraphObject()
query = g.V().Out(['foo', 'bar'], 'qux')
actual = query.build()
self.assertEqual(actual, "g.V().Out(['foo', 'bar'], 'qux')")
def test_out_query_with_predicate_as_none_and_label_as_dict(self):
g = GraphObject()
query = g.V().Out(None, ['foo', 'bar'])
actual = query.build()
self.assertEqual(actual, "g.V().Out(null, ['foo', 'bar'])")
def test_in_query(self):
g = GraphObject()
query = g.V().In("name").All()
actual = query.build()
self.assertEqual(actual, "g.V().In('name').All()")
def test_both(self):
g = GraphObject()
query = g.V("F").Both("follows")
actual = query.build()
print(actual)
self.assertEqual(actual, "g.V('F').Both('follows')")
def test_is(self):
g = GraphObject()
query = g.V().Is('B', 'C')
actual = query.build()
self.assertEqual(actual, "g.V().Is('B', 'C')")
def test_tag(self):
g = GraphObject()
query = g.V().Tag('B', 'C')
actual = query.build()
self.assertEqual(actual, 'g.V().Tag(["B", "C"])')
def test_save(self):
g = GraphObject()
query = g.V().Save('B', 'C')
actual = query.build()
self.assertEqual(actual, "g.V().Save('B', 'C')")
def test_back(self):
g = GraphObject()
query = g.V().Back('B')
actual = query.build()
self.assertEqual(actual, "g.V().Back('B')")
def test_all_query(self):
g = GraphObject()
query = g.V("Humphrey Bogart").All()
actual = query.build()
self.assertEqual(actual, "g.V('Humphrey Bogart').All()")
def test_has_query(self):
g = GraphObject()
query = g.V().Has("name", "Casablanca").All()
actual = query.build()
self.assertEqual(actual, "g.V().Has('name', 'Casablanca').All()")
def test_complex_query1(self):
g = GraphObject()
query = g.V().Has("name", "Casablanca") \
.Out("/film/film/starring") \
.Out("/film/performance/actor") \
.Out("name") \
.All()
actual = query.build()
self.assertEqual(actual, "g.V().Has('name', 'Casablanca')"
".Out('/film/film/starring')"
".Out('/film/performance/actor')"
".Out('name')"
".All()")
def test_follow_with_morphism_path_and_typed_query(self):
g = GraphObject()
film_to_actor = g.Morphism().Out("/film/film/starring").Out("/film/performance/actor")
query = g.V().Has("name", "Casablanca").Follow(film_to_actor).Out("name").All()
actual = query.build()
self.assertEqual(actual, "g.V().Has('name', 'Casablanca')"
".Follow("
"g.Morphism().Out('/film/film/starring').Out('/film/performance/actor')"
").Out('name')"
".All()")
def test_follow_with_morphism_path_and_str_query(self):
g = GraphObject()
film_to_actor = g.Morphism().Out("/film/film/starring").Out("/film/performance/actor")
query = g.V().Has("name", "Casablanca").Follow(film_to_actor.build()).Out("name").All()
actual = query.build()
self.assertEqual(actual, "g.V().Has('name', 'Casablanca')"
".Follow("
"g.Morphism().Out('/film/film/starring').Out('/film/performance/actor')"
").Out('name')"
".All()")
def test_follow_with_vertex(self):
g = GraphObject()
with self.assertRaises(Exception):
g.V().Follow(g.V()).build()
def test_union(self):
g = GraphObject()
query = g.Vertex().Union(g.Vertex())
actual = query.build()
self.assertEqual(actual, "g.V().Union(g.V())")
def test_intersect(self):
g = GraphObject()
query = g.Vertex().Intersect(g.Vertex())
actual = query.build()
self.assertEqual(actual, "g.V().Intersect(g.V())")
def test_get_limit(self):
g = GraphObject()
query = g.Vertex().GetLimit(5)
actual = query.build()
self.assertEqual(actual, "g.V().GetLimit(5)")
def test_emit(self):
g = GraphObject()
query = g.Emit({'name': 'John', 'lastName': 'DOE', 'age': 25})
self.assertEqual(query, 'g.Emit({"age": 25, "lastName": "DOE", "name": "John"})')
if __name__ == '__main__':
unittest.main()
================================================
FILE: tox.ini
================================================
[tox]
envlist = clean,py27,py3,py36,pypy,pypy3
skip_missing_interpreters = True
[testenv]
deps = -Ur{toxinidir}/requirements.testing.txt
commands = python -m nose
whitelist_externals = pyenv install -s 2.7.11
pyenv install -s 3.6.1
pyenv install -s pypy-5.3.1
pyenv local 2.7.11 3.6.1 pypy-5.3.1
[testenv:clean]
deps = coverage
commands = coverage erase
[testenv:report]
commands = nosetests --with-coverage --cover-package=pyley
gitextract_tu09thrq/ ├── .appveyor.sh ├── .gitignore ├── .travis.sh ├── .travis.yml ├── MANIFEST.in ├── README.rst ├── UNLICENSE ├── appveyor.yml ├── pyley/ │ ├── __init__.py │ └── pyley.py ├── requirements.testing.txt ├── requirements.txt ├── setup.cfg ├── setup.py ├── tests/ │ ├── __init__.py │ ├── test_cayley_client.py │ └── test_gizmo_query.py └── tox.ini
SYMBOL INDEX (82 symbols across 4 files)
FILE: pyley/pyley.py
class CayleyResponse (line 4) | class CayleyResponse(object):
method __init__ (line 6) | def __init__(self, raw_response, result):
class CayleyClient (line 11) | class CayleyClient(object):
method __init__ (line 13) | def __init__(self, url="http://localhost:64210", version="v1"):
method add_query_limit (line 19) | def add_query_limit(self, limit):
method Send (line 26) | def Send(self, query):
method AddQuad (line 37) | def AddQuad(self, subject, predicate, object_, label=None):
method AddQuads (line 41) | def AddQuads(self, quads):
method DeleteQuad (line 55) | def DeleteQuad(self, subject, predicate, object_, label=None):
method DeleteQuads (line 59) | def DeleteQuads(self, quads):
class _GizmoQuery (line 73) | class _GizmoQuery(object):
method __init__ (line 76) | def __init__(self):
method __str__ (line 80) | def __str__(self):
method _put (line 84) | def _put(self, token, *parameters):
class GraphObject (line 89) | class GraphObject(object):
method V (line 90) | def V(self):
method V (line 94) | def V(self, *node_ids):
method M (line 106) | def M(self):
method Vertex (line 110) | def Vertex(self):
method Vertex (line 114) | def Vertex(self, *node_ids):
method Morphism (line 120) | def Morphism(self):
method Emit (line 124) | def Emit(self, data):
class _Path (line 128) | class _Path(_GizmoQuery):
method __init__ (line 130) | def __init__(self, parent):
method Out (line 135) | def Out(self, predicate=None, tags=None):
method In (line 140) | def In(self, predicate=None, tags=None):
method Both (line 145) | def Both(self, predicate=None, tags=None):
method _bounds (line 150) | def _bounds(self, method, predicate=None, tags=None):
method _format_input_bounds (line 165) | def _format_input_bounds(self, value):
method Is (line 178) | def Is(self, *nodes):
method Has (line 183) | def Has(self, predicate, object):
method HasR (line 188) | def HasR(self, predicate, object):
method Tag (line 193) | def Tag(self, *tags):
method Back (line 198) | def Back(self, tag):
method Save (line 203) | def Save(self, predicate, tag):
method Intersect (line 208) | def Intersect(self, query):
method Union (line 216) | def Union(self, query):
method Follow (line 224) | def Follow(self, query):
method FollowR (line 232) | def FollowR(self, query):
method build (line 240) | def build(self):
class _Vertex (line 244) | class _Vertex(_Path):
method All (line 246) | def All(self):
method GetLimit (line 251) | def GetLimit(self, limit):
class _Morphism (line 256) | class _Morphism(_Path):
class _QueryDefinition (line 260) | class _QueryDefinition(object):
method __init__ (line 262) | def __init__(self, token, *parameters):
method __str__ (line 267) | def __str__(self):
FILE: setup.py
function read (line 13) | def read(filename):
function extract_metaitem (line 19) | def extract_metaitem(meta):
FILE: tests/test_cayley_client.py
class CayleyClientTests (line 7) | class CayleyClientTests(TestCase):
method test_add_limit (line 9) | def test_add_limit(self):
method test_add_limit_fails (line 15) | def test_add_limit_fails(self):
method test_send (line 21) | def test_send(self):
method test_a_add_quad (line 47) | def test_a_add_quad(self):
method test_b_delete_quad (line 58) | def test_b_delete_quad(self):
method test_c_add_quads (line 70) | def test_c_add_quads(self):
method test_d_delete_quads (line 87) | def test_d_delete_quads(self):
FILE: tests/test_gizmo_query.py
class GizmoQueryTests (line 5) | class GizmoQueryTests(unittest.TestCase):
method setUp (line 7) | def setUp(self):
method test_vertex_query (line 11) | def test_vertex_query(self):
method test_vertex_query_with_parameters (line 17) | def test_vertex_query_with_parameters(self):
method test_morphism_query (line 24) | def test_morphism_query(self):
method test_out_query (line 30) | def test_out_query(self):
method test_out_query_with_predicate (line 38) | def test_out_query_with_predicate(self):
method test_out_query_with_predicate_as_dict_and_label (line 46) | def test_out_query_with_predicate_as_dict_and_label(self):
method test_out_query_with_predicate_as_none_and_label_as_dict (line 54) | def test_out_query_with_predicate_as_none_and_label_as_dict(self):
method test_in_query (line 62) | def test_in_query(self):
method test_both (line 70) | def test_both(self):
method test_is (line 78) | def test_is(self):
method test_tag (line 86) | def test_tag(self):
method test_save (line 94) | def test_save(self):
method test_back (line 102) | def test_back(self):
method test_all_query (line 110) | def test_all_query(self):
method test_has_query (line 118) | def test_has_query(self):
method test_complex_query1 (line 126) | def test_complex_query1(self):
method test_follow_with_morphism_path_and_typed_query (line 142) | def test_follow_with_morphism_path_and_typed_query(self):
method test_follow_with_morphism_path_and_str_query (line 155) | def test_follow_with_morphism_path_and_str_query(self):
method test_follow_with_vertex (line 168) | def test_follow_with_vertex(self):
method test_union (line 175) | def test_union(self):
method test_intersect (line 184) | def test_intersect(self):
method test_get_limit (line 193) | def test_get_limit(self):
method test_emit (line 201) | def test_emit(self):
Condensed preview — 18 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (29K chars).
[
{
"path": ".appveyor.sh",
"chars": 296,
"preview": "appveyor DownloadFile https://github.com/cayleygraph/cayley/releases/download/v0.7.0/cayley_0.7.0_windows_amd64.zip -Tim"
},
{
"path": ".gitignore",
"chars": 574,
"preview": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n\n# C extensions\n*.so\n\n#PyCharm project folder\n.idea/\n\n# D"
},
{
"path": ".travis.sh",
"chars": 234,
"preview": "#!/bin/bash\nwget https://github.com/cayleygraph/cayley/releases/download/v0.7.0/cayley_0.7.0_linux_amd64.tar.gz\ntar -xvz"
},
{
"path": ".travis.yml",
"chars": 328,
"preview": "language: python\n\npython:\n - \"2.7\"\n - \"3.4\"\n - \"3.5\"\n - \"3.6\"\n - \"3.7\"\n - \"3.8\"\n\nbefore_script:\n - /bin/bash ./.t"
},
{
"path": "MANIFEST.in",
"chars": 18,
"preview": "include README.md\n"
},
{
"path": "README.rst",
"chars": 4200,
"preview": ".. image:: https://github.com/ziyasal/pyley/raw/master/pyley.png?raw=true\n\npyley\n=====\n\n.. image:: https://img.shields.i"
},
{
"path": "UNLICENSE",
"chars": 1211,
"preview": "This is free and unencumbered software released into the public domain.\n\nAnyone is free to copy, modify, publish, use, c"
},
{
"path": "appveyor.yml",
"chars": 1601,
"preview": "environment:\n\n matrix:\n\n - PYTHON: \"C:\\\\Python27\"\n - PYTHON: \"C:\\\\Python34\"\n - PYTHON: \"C:\\\\Python35\"\n - PY"
},
{
"path": "pyley/__init__.py",
"chars": 562,
"preview": "\"\"\"pyley Python client for an open-source graph database Cayley\"\"\"\n\n__title__ = 'pyley'\n__version__ = '0.2.2"
},
{
"path": "pyley/pyley.py",
"chars": 6633,
"preview": "import json\nimport requests\n\nclass CayleyResponse(object):\n\n def __init__(self, raw_response, result):\n self.r"
},
{
"path": "requirements.testing.txt",
"chars": 31,
"preview": "python-coveralls\ncoverage\nnose\n"
},
{
"path": "requirements.txt",
"chars": 9,
"preview": "requests\n"
},
{
"path": "setup.cfg",
"chars": 96,
"preview": "[bdist_wheel]\nuniversal = 1\n\n[aliases]\ntest = nosetest\n\n[check-manifest]\nignore =\n .travis.yml\n"
},
{
"path": "setup.py",
"chars": 1866,
"preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\nfrom __future__ import absolute_import, print_function\n\nimport os\nimport r"
},
{
"path": "tests/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "tests/test_cayley_client.py",
"chars": 3078,
"preview": "from unittest import TestCase\nfrom pyley import CayleyClient, GraphObject\n\n_CLIENT_URL = 'http://localhost:64210'\n\n\nclas"
},
{
"path": "tests/test_gizmo_query.py",
"chars": 5908,
"preview": "import unittest\nfrom pyley import GraphObject\n\n\nclass GizmoQueryTests(unittest.TestCase):\n\n def setUp(self):\n "
},
{
"path": "tox.ini",
"chars": 490,
"preview": "[tox]\nenvlist = clean,py27,py3,py36,pypy,pypy3\nskip_missing_interpreters = True\n\n[testenv]\ndeps = -Ur{toxinidir}/require"
}
]
About this extraction
This page contains the full source code of the ziyasal/pyley GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 18 files (26.5 KB), approximately 7.4k tokens, and a symbol index with 82 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.