Skip to content
Browse files

updating dist info

  • Loading branch information...
1 parent e0b6d11 commit d13261e36ca8e1fae8fec3d5f153543519c0ff9b @trhowe trhowe committed
Showing with 120 additions and 37 deletions.
  1. +13 −0 LICENCE.TXT
  2. +23 −0 README.txt
  3. +14 −1 agamemnon/__init__.py
  4. +14 −0 agamemnon/graph_constants.py
  5. +14 −0 agamemnon/primitives.py
  6. +1 −1 agamemnon/tests/functional_tests.py
  7. +29 −30 agamemnon/tests/unit_tests.py
  8. +4 −0 setup.cfg
  9. +8 −5 setup.py
View
13 LICENCE.TXT
@@ -0,0 +1,13 @@
+Copyright 2010 University of Chicago
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
View
23 README.txt
@@ -0,0 +1,23 @@
+==============
+Agamemnon
+==============
+
+Agamemnon is a thin library built on top of pycassa. It allows you to use the Cassandra
+database (<http://cassandra.apache.org>) as a graph database. Much of the api was inspired
+by the excellent neo4j.py project (<http://components.neo4j.org/neo4j.py/snapshot/>)
+
+Documentation
+==============
+Soon, I promise. For now, take a look at agamemnon.functional_tests This is a fairly complete
+example of basic behaviors. The unit tests are very "unit test-y" and might not be a great way
+to understand how to work with the library. They mostly focus on making sure that the correct
+information is being sent to Cassandra. But the functional tests are designed to actually interact
+with cassandra. Note, the functional tests require a instance of Cassandra running at localhost:9160
+
+Thanks To
+=============
+This project is an extension of the globusonline.org project and is being used to power the upcoming
+version of globusonline.org. I'd like to thank Ian Foster and Steve Tuecke for leading that project,
+and all of the members of the cloud services team for participating in this effort, especially:
+ Vijay Anand, Kyle Chard, Martin Feller and Mike Russell for helping with design and testing. I'd
+also like to thank Bryce Allen for his help with some of the python learning curve.
View
15 agamemnon/__init__.py
@@ -1,10 +1,23 @@
+# Copyright 2010 University of Chicago
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
from datetime import datetime
import logging
import pycassa.batch as batch
from pycassa.cassandra.ttypes import NotFoundException
import pycassa.system_manager as system_manager
import pycassa.columnfamily as cf
-import graph.primitives as prim
+import agamemnon.primitives as prim
from graph_constants import *
log = logging.getLogger(__name__)
View
14 agamemnon/graph_constants.py
@@ -1,3 +1,17 @@
+# Copyright 2010 University of Chicago
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
__author__ = 'trhowe'
View
14 agamemnon/primitives.py
@@ -1,3 +1,17 @@
+# Copyright 2010 University of Chicago
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
from pycassa.cassandra.ttypes import NotFoundException
__author__ = 'trhowe'
View
2 agamemnon/tests/functional_tests.py
@@ -2,7 +2,7 @@
from nose.plugins.attrib import attr
import pycassa
from pycassa.cassandra.ttypes import NotFoundException
-from graph import DataStore
+from agamemnon import DataStore
class GraphFunctionalTests(unittest.TestCase):
#This test requires a running cassandra instance at localhost:9160
View
59 agamemnon/tests/unit_tests.py
@@ -4,9 +4,9 @@
from nose.plugins.attrib import attr
import pycassa
from pycassa.cassandra.ttypes import NotFoundException
-import graph
-import graph.primitives as graph_prim
-from graph.graph_constants import ENDPOINT_NAME_TEMPLATE, RELATIONSHIP_KEY_PATTERN, RELATIONSHIP_INDEX
+import agamemnon
+import agamemnon.primitives as graph_prim
+from agamemnon.graph_constants import ENDPOINT_NAME_TEMPLATE, RELATIONSHIP_KEY_PATTERN, RELATIONSHIP_INDEX
relationship_type = 'pig_cow_alliance'
relationship_types_cf = '__relationship__types'
@@ -38,17 +38,17 @@ def side_effect(self, name):
return name
cf_mock.side_effect = side_effect
- self.store = graph.DataStore('test_space', self._pool, self._system_manager)
+ self.store = agamemnon.DataStore('test_space', self._pool, self._system_manager)
self.pig = graph_prim.Node(self.store, 'test_type', 'pig')
self.cow = graph_prim.Node(self.store, 'test_type', 'cow')
- @attr(module='graph', type='unit')
+ @attr(module='agamemnon', type='unit')
def test_get_non_existent_cf(self):
with patch('pycassa.columnfamily.ColumnFamily') as cf_mock:
cf_mock.side_effect = NotFoundException()
self.failIf(self.store.cf_exists('test_type'))
- @attr(module='graph', type='unit')
+ @attr(module='agamemnon', type='unit')
def test_create_node(self):
#create the node
with patch('pycassa.columnfamily.ColumnFamily') as cf_mock:
@@ -74,7 +74,7 @@ def side_effect(name):
comparator_type=pycassa.system_manager.ASCII_TYPE)
cf_mock.return_value.insert.assert_called_with('cow', {'sound': 'moo'})
- @attr(module='graph', type='unit')
+ @attr(module='agamemnon', type='unit')
def test_create_node_existing_cf(self):
with patch('pycassa.columnfamily.ColumnFamily') as cf_mock:
def side_effect(name):
@@ -87,8 +87,7 @@ def side_effect(name):
self.store.create_node('test_type', 'pig', {'sound': 'oink'})
self.failIf(self._system_manager.create_column_family.called)
- #TODO: unclear what this should really do
- @attr(module='graph', type='unit')
+ @attr(module='agamemnon', type='unit')
def test_create_duplicate_node(self):
with patch('pycassa.columnfamily.ColumnFamily') as cf_mock:
def side_effect(name):
@@ -102,7 +101,7 @@ def side_effect(name):
cf_mock.return_value.insert.assert_called_with('pig', {'sound': 'oink'})
- @attr(module='graph', type='unit')
+ @attr(module='agamemnon', type='unit')
def test_get_node(self):
with patch('pycassa.columnfamily.ColumnFamily') as cf_mock:
cf_mock.return_value.get.return_value = {'sound': 'oink'}
@@ -112,7 +111,7 @@ def test_get_node(self):
self.failUnlessEqual(pig.key, 'pig')
self.failUnlessEqual(pig['sound'], 'oink')
- @attr(module='graph', type='unit')
+ @attr(module='agamemnon', type='unit')
def test_get_non_existent_node(self):
with patch('pycassa.columnfamily.ColumnFamily') as cf_mock:
#Test if node is not in datastore
@@ -120,10 +119,10 @@ def test_get_non_existent_node(self):
try:
self.store.get_node('test_type', 'pig')
self.fail()
- except graph.NodeNotFoundException:
+ except agamemnon.NodeNotFoundException:
pass
- @attr(module='graph', type='unit')
+ @attr(module='agamemnon', type='unit')
def test_delete_node_simple(self):
node_mock = Mock()
node_mock.remove = Mock()
@@ -133,9 +132,9 @@ def test_delete_node_simple(self):
in_bound_rel_mock.get.return_value = {}
def side_effect(pool, type):
- if type == 'outbound__%s' % graph.RELATIONSHIP_INDEX:
+ if type == 'outbound__%s' % agamemnon.RELATIONSHIP_INDEX:
return out_bound_rel_mock
- elif type == 'inbound__%s' % graph.RELATIONSHIP_INDEX:
+ elif type == 'inbound__%s' % agamemnon.RELATIONSHIP_INDEX:
return in_bound_rel_mock
elif type == type_cf:
return node_mock
@@ -152,7 +151,7 @@ def side_effect(pool, type):
contextualized_batch_mock.remove.assert_called_with(node_mock, 'pig')
- @attr(module='graph', type='unit')
+ @attr(module='agamemnon', type='unit')
def test_create_relationship(self):
# These are the inserts we expect to get. The first one is adding friend to the list of relation types
# the second and third are the to and from relationship inserts. This is a pretty complicated action. It
@@ -195,10 +194,10 @@ def side_effect(self, name):
# And, let's test our assumptions
self.failUnlessEqual(contextualized_batch_mock.insert.call_args_list, expected_calls)
- @attr(module='graph', type='unit')
+ @attr(module='agamemnon', type='unit')
def test_delete_relationship(self):
- inbound_rel_index_cf = 'inbound__%s' % graph.RELATIONSHIP_INDEX
- outbound_rel_index_cf = 'outbound__%s' % graph.RELATIONSHIP_INDEX
+ inbound_rel_index_cf = 'inbound__%s' % agamemnon.RELATIONSHIP_INDEX
+ outbound_rel_index_cf = 'outbound__%s' % agamemnon.RELATIONSHIP_INDEX
mocks = {inbound_rel_index_cf: Mock(), outbound_rel_index_cf: Mock()}
from_key = ENDPOINT_NAME_TEMPLATE % (type_cf, 'pig')
to_key = ENDPOINT_NAME_TEMPLATE % (type_cf, 'cow')
@@ -226,10 +225,10 @@ def side_effect(self, name):
# Test our assumptions
self.failUnlessEqual(contextualized_batch_mock.remove.call_args_list, expected_calls)
- @attr(module='graph', type='unit')
+ @attr(module='agamemnon', type='unit')
def test_get_relationships_of_given_type_outbound_only(self):
- inbound_rel_index_cf = 'inbound__%s' % graph.RELATIONSHIP_INDEX
- outbound_rel_index_cf = 'outbound__%s' % graph.RELATIONSHIP_INDEX
+ inbound_rel_index_cf = 'inbound__%s' % agamemnon.RELATIONSHIP_INDEX
+ outbound_rel_index_cf = 'outbound__%s' % agamemnon.RELATIONSHIP_INDEX
out_bound_mock = Mock()
out_bound_mock.get.return_value = {
'friend__pig_cow_alliance': {'rel_type': 'friend', 'source__type': 'test_type', 'source_key': 'pig',
@@ -258,10 +257,10 @@ def side_effect(pool, type):
expected = pig.friend(cow, 'pig_cow_alliance')
self.failUnlessEqual(expected, rel)
- @attr(module='graph', type='unit')
+ @attr(module='agamemnon', type='unit')
def test_get_relationships_of_given_type_inbound_only(self):
- inbound_rel_index_cf = 'inbound__%s' % graph.RELATIONSHIP_INDEX
- outbound_rel_index_cf = 'outbound__%s' % graph.RELATIONSHIP_INDEX
+ inbound_rel_index_cf = 'inbound__%s' % agamemnon.RELATIONSHIP_INDEX
+ outbound_rel_index_cf = 'outbound__%s' % agamemnon.RELATIONSHIP_INDEX
out_bound_mock = Mock()
out_bound_mock.get.side_effect = NotFoundException()
in_bound_mock = Mock()
@@ -290,12 +289,12 @@ def side_effect(pool, type):
expected = chicken.friend(pig, 'chicken_pig_alliance')
self.failUnlessEqual(expected, rel)
- @attr(module='graph', type='unit')
+ @attr(module='agamemnon', type='unit')
def test_delete_node_with_relationships(self):
- mocks = {'test_type': Mock(), 'outbound__%s' % graph.RELATIONSHIP_INDEX: Mock(),
- 'inbound__%s' % graph.RELATIONSHIP_INDEX: Mock()}
- inbound = 'inbound__%s' % graph.RELATIONSHIP_INDEX
- outbound = 'outbound__%s' % graph.RELATIONSHIP_INDEX
+ mocks = {'test_type': Mock(), 'outbound__%s' % agamemnon.RELATIONSHIP_INDEX: Mock(),
+ 'inbound__%s' % agamemnon.RELATIONSHIP_INDEX: Mock()}
+ inbound = 'inbound__%s' % agamemnon.RELATIONSHIP_INDEX
+ outbound = 'outbound__%s' % agamemnon.RELATIONSHIP_INDEX
mocks['test_type'].remove = Mock()
mocks[inbound].get.side_effect = NotFoundException()
View
4 setup.cfg
@@ -0,0 +1,4 @@
+[nosetests]
+verbosity=2
+detailed-errors=1
+attr=type=unit
View
13 setup.py
@@ -6,24 +6,27 @@
README = open(os.path.join(here, 'README.txt')).read()
CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
-requires = ['pycassa']
+requires = ['pycassa', 'thrift05', 'setuptools']
+tests_requires = requires + ['nose', 'mock']
setup(name='agamemnon',
- version='0.0',
+ version='0.1.0',
description='A graph database built on top of cassandra',
- long_description=README + '\n\n' + CHANGES,
+ long_description=README,
classifiers=[
"Programming Language :: Python",
],
author='Tom Howe',
author_email='trhowe@ci.uchicago.edu',
url='https://github.com/turtlebender/agamemnon',
+ license='LICENSE.txt',
keywords='cassandra',
packages=find_packages(),
include_package_data=True,
- zip_safe=False,
+ zip_safe=True,
+ setup_requires=['nose>=0.11'],
install_requires=requires,
- tests_require=requires,
+ tests_require=tests_requires,
test_suite="nose.collector",
)

0 comments on commit d13261e

Please sign in to comment.
Something went wrong with that request. Please try again.