Browse files

update example code

  • Loading branch information...
1 parent 9704a4c commit a188bd55a29b86bb0e3e194d304c39e266ed0c59 @enki committed Jun 26, 2010
Showing with 115 additions and 176 deletions.
  1. +30 −69 README.md
  2. +1 −1 cassandra/constants.py
  3. +13 −1 cassandra/ttypes.py
  4. +11 −11 devtools/README.template.md
  5. +19 −58 examples/twitty.py
  6. +1 −2 tragedy/__init__.py
  7. +6 −6 tragedy/columns.py
  8. +8 −7 tragedy/datastructures.py
  9. +6 −6 tragedy/hierarchy.py
  10. +17 −12 tragedy/models.py
  11. +3 −3 tragedy/rows.py
View
99 README.md
@@ -1,13 +1,13 @@
# Tragedy
+Tragedy 0.7-trunk by Paul Bohm <enki@bbq.io> / @enkido on twitter.
-Tragedy is a high-level Cassandra Object Abstraction for Python.
+A high-level Cassandra Object Abstraction for Python.
-The current newindex branch is a refactor to make tragedy indexes more powerful.
-Don't rely on the API too much tho, because it will change. Some of this documentation is also outdated.
+## In Development Warning
-Also this branch only works with the latest Cassandra trunk (0.7) checkouts.
+Tragedy currently only works with the latest Cassandra trunk checkouts (0.7). This code is already used in production, but still a moving target and expected to have bugs.
-## Tragedy's Data Model
+## Understanding Tragedy's Data Model
In Tragedy you build your data model from Models and Indexes. An abstract *Model* specifies the kind data that can be stored in a Model-Instance. We also call a Model-Instance a Row, since specific Model-Instances are uniquely identified by their unique RowKey. Knowing the Model and RowKey is all you need to store and retrieve data from Cassandra. The attributes of the Model correspond to the Columns of a Row. Each Column has a Field-Type like StringField or IntegerField. The RowKey decides which specific Row/Model-Instance the user is referring to and on which physical machine the data is stored. If you lose a RowKey, you can never store or retrieve that data again. Any Unicode string can be used as RowKey as long as it is unique among all Rows of a Model. If there's no naturally unique identifier for the data in a Row, you can ask Tragedy to generate a UUID-RowKey for you.
@@ -41,15 +41,15 @@ TweetsSent is an abstract Index over Tweets sorted by Cassandra's TimeUUIDType.
tweets_by_user = TweetsSent(by_username='merlin').load()
print tweets_by_user
-The main difference between Indexes and Models is that Indexes keep track of an unlimited amount of ordered data of the same kind (normally ForeignKeys), whereas a Model keeps track of a limited number of data that can be any mixture of types. Indexes are most often used to to help us find Data whose RowKey we've forgotten. Models can refer to Indexes using ForeignKeys, and Indexes can refer to both Models and (less often) other Indexes. The call above gives us a list of Tweets previously posted by user 'merlin' with their RowKeys correctly set. However, since the Index only contains references the actual tweet data hasn't been loaded yet at this point. If we tried to work with those tweets, we'd see #MISSING# fields all over the place:
-
- [<Tweet 8649a1ca4ab843b9afa6cc954908ac04: {'message': '#MISSING#', 'author': '#MISSING#'}, ...]
+The main difference between Indexes and Models is that Indexes keep track of an unlimited amount of ordered data of the same kind (normally ForeignKeys), whereas a Model keeps track of a limited number of data that can be any mixture of types. Indexes are most often used to to help us find Data whose RowKey we've forgotten. Models can refer to Indexes using ForeignKeys, and Indexes can refer to both Models and (less often) other Indexes. The call above gives us a list of Tweets previously posted by user 'merlin' with their RowKeys correctly set. However, since the Index only contains references the actual tweet data hasn't been loaded yet at this point. If we tried to work with those tweets, we'd see only empty tweets:
+ <TweetsSent merlin: O({'Sat Jun 26 04:18:14 2010': <Tweet 7e991c64732b4f8194d7c857f9522101: {}>})>
+
To actually load the tweets we need to resolve them (retrieve them using their RowKeys). Luckily Indexes have the .resolve() helper to make this easy:
tweets_by_user.resolve()
print tweets_by_user
- [<Tweet ced314748d574379a817e1a1c9149789: {'message': "some message", 'author': <User merlin: {'password': '#MISSING#'}>}>
+ [<Tweet 7e991c64732b4f8194d7c857f9522101: {'message': 'tweeting from tragedy', 'author': <User 20336bbf91d5407283dd553593c38e03: {}>}>]
Behind the scenes Index.resolve() almost works like calling Model.load() on all Tweets in the list. It's more efficient though, since this combines all required queries into one multiquery for faster processing. Now we've seen how to create tweets, store them, and find them again. If you want to see how you can distribute them to Followers, scroll down for a full example of a twitter-like application.
@@ -58,8 +58,8 @@ That's about it for the basics. There's more stuff Tragedy can do for you, like
## Installation
$ setup.py install (optionally --cassandra to install the compiled cassandra thrift bindings)
-## IRC and Contact
-Come hang out on #cassandra on irc.freenode.net. Email: enki@bbq.io. Twitter: [@enkido](http://twitter.com/enkido).
+## IRC
+Come hang out on #cassandra on irc.freenode.net.
## Example (full twitter-demo)
@@ -79,72 +79,33 @@ Come hang out on #cassandra on irc.freenode.net. Email: enki@bbq.io. Twitter: [@
lastname = UnicodeField(mandatory=False) # normally fields are mandatory
password = UnicodeField()
- allusers = AllIndex()
- by_lastname = SecondaryIndex(lastname)
- by_firstname = SecondaryIndex(firstname)
-
- following = ObjectIndex(target_model='User')
- followed_by = ObjectIndex(target_model='User')
-
- tweets_sent = ObjectIndex(target_model='Tweet')
- tweets_received = ObjectIndex(target_model='Tweet')
-
- def follow(self, *one_or_more):
- fol = self.following()
- for other in one_or_more:
- fol.append(other)
- other.followed_by().append(self).save()
- fol.save()
- # print "FOLLOW", fol, self.followed_by(user=other).load()
-
- def tweet(self, message):
- new_tweet = Tweet(author=self, message=message[:140]).save()
- # print 'wtf', new_tweet
- a = self.tweets_sent()
- # print 'TWOP', a, a._row_key_name
- a.append( new_tweet ).save()
- # print 'FROB', a
-
- for follower in self.followed_by().load():
- # print 'FOLLOWER', follower
- follower.receive(new_tweet)
-
- def receive(self, tweet):
- # print self, 'RECEIVING', tweet
- self.tweets_received().append(tweet).save()
-
class Tweet(Model):
uuid = RowKey(autogenerate=True) # generate a UUID for us.
message = UnicodeField()
author = ForeignKey(foreign_class=User, mandatory=True)
alltweets = AllIndex()
-
- twitty_keyspace.connect(servers=['localhost:9160'], auto_create_models=True, auto_drop_keyspace=True)
-
- dave = User(username='dave', firstname='dave', password='test').save()
-
- bood = User(username='dave', firstname='dave', lastname='Bood', password='super').save()
- merlin = User(username='merlin', firstname='merlin', lastname='Bood', password='sunshine').save()
- peter = User(username='peter', firstname='Peter', password='secret').save()
+ class TweetsSent(Index):
+ by_username = RowKey()
+ targetmodel = ForeignKey(foreign_class=Tweet, compare_with='TimeUUIDType')
- dave.follow(merlin, peter)
- peter.follow(merlin)
- merlin.follow(dave)
+ def run():
+ # Connect to cassandra
+ twitty_keyspace.connect(servers=['localhost:9160'], auto_create_models=True, auto_drop_keyspace=True)
- merlin.tweet("i've just started using twitty. send me a message!")
- dave.tweet('making breakfast')
- peter.tweet('sitting at home being bored')
+ dave = User(username='dave', firstname='dave', password='test').save()
+ merlin = User(username='merlin', firstname='merlin', lastname='Bood', password='sunshine').save()
+ peter = User(username='peter', firstname='Peter', password='secret').save()
- print 'A', User.allusers(), list(User.allusers().load().resolve())
- print 'B', User.by_lastname('Bood'), list(User.by_lastname('Bood').load().resolve())
- print 'C', dave.tweets_received(), list(dave.tweets_received().load().resolve())
+ new_tweet = Tweet(author=dave, message='tweeting from tragedy').save()
+ merlinIndex = TweetsSent(by_username=merlin['username'])
+ merlinIndex.append(new_tweet)
+ merlinIndex.save()
+
+ tweets_by_user = TweetsSent(by_username='merlin').load()
+ print tweets_by_user
+ print list(tweets_by_user.resolve())
- #
- # for dude in (dave,peter,merlin):
- # name = dude['username']
- # print '%s has these followers:' % (name,), dude.get_followed_by().values()
- # print '%s follows' % (name,), dude.get_following().values()
- # print '%s sent' % (name,), [x for x in dude.get_tweets_sent(count=3)]
- # print '%s received' % (name,), [x for x in dude.get_tweets_received(count=3)]
+ if __name__ == '__main__':
+ run()
View
2 cassandra/constants.py
@@ -7,5 +7,5 @@
from thrift.Thrift import *
from ttypes import *
-VERSION = "8.0.0"
+VERSION = "8.1.0"
View
14 cassandra/ttypes.py
@@ -1638,6 +1638,7 @@ class CfDef(object):
- row_cache_size
- preload_row_cache
- key_cache_size
+ - read_repair_chance
"""
thrift_spec = (
@@ -1653,9 +1654,10 @@ class CfDef(object):
(9, TType.DOUBLE, 'row_cache_size', None, 0, ), # 9
(10, TType.BOOL, 'preload_row_cache', None, False, ), # 10
(11, TType.DOUBLE, 'key_cache_size', None, 200000, ), # 11
+ (12, TType.DOUBLE, 'read_repair_chance', None, 1, ), # 12
)
- def __init__(self, table=None, name=None, column_type=thrift_spec[3][4], clock_type=thrift_spec[4][4], comparator_type=thrift_spec[5][4], subcomparator_type=thrift_spec[6][4], reconciler=thrift_spec[7][4], comment=thrift_spec[8][4], row_cache_size=thrift_spec[9][4], preload_row_cache=thrift_spec[10][4], key_cache_size=thrift_spec[11][4],):
+ def __init__(self, table=None, name=None, column_type=thrift_spec[3][4], clock_type=thrift_spec[4][4], comparator_type=thrift_spec[5][4], subcomparator_type=thrift_spec[6][4], reconciler=thrift_spec[7][4], comment=thrift_spec[8][4], row_cache_size=thrift_spec[9][4], preload_row_cache=thrift_spec[10][4], key_cache_size=thrift_spec[11][4], read_repair_chance=thrift_spec[12][4],):
self.table = table
self.name = name
self.column_type = column_type
@@ -1667,6 +1669,7 @@ def __init__(self, table=None, name=None, column_type=thrift_spec[3][4], clock_t
self.row_cache_size = row_cache_size
self.preload_row_cache = preload_row_cache
self.key_cache_size = key_cache_size
+ self.read_repair_chance = read_repair_chance
def read(self, iprot):
if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None:
@@ -1732,6 +1735,11 @@ def read(self, iprot):
self.key_cache_size = iprot.readDouble();
else:
iprot.skip(ftype)
+ elif fid == 12:
+ if ftype == TType.DOUBLE:
+ self.read_repair_chance = iprot.readDouble();
+ else:
+ iprot.skip(ftype)
else:
iprot.skip(ftype)
iprot.readFieldEnd()
@@ -1786,6 +1794,10 @@ def write(self, oprot):
oprot.writeFieldBegin('key_cache_size', TType.DOUBLE, 11)
oprot.writeDouble(self.key_cache_size)
oprot.writeFieldEnd()
+ if self.read_repair_chance != None:
+ oprot.writeFieldBegin('read_repair_chance', TType.DOUBLE, 12)
+ oprot.writeDouble(self.read_repair_chance)
+ oprot.writeFieldEnd()
oprot.writeFieldStop()
oprot.writeStructEnd()
View
22 devtools/README.template.md
@@ -1,13 +1,13 @@
# Tragedy
+Tragedy 0.7-trunk by Paul Bohm <enki@bbq.io> / @enkido on twitter.
-Tragedy is a high-level Cassandra Object Abstraction for Python.
+A high-level Cassandra Object Abstraction for Python.
-The current newindex branch is a refactor to make tragedy indexes more powerful.
-Don't rely on the API too much tho, because it will change. Some of this documentation is also outdated.
+## In Development Warning
-Also this branch only works with the latest Cassandra trunk (0.7) checkouts.
+Tragedy currently only works with the latest Cassandra trunk checkouts (0.7). This code is already used in production, but still a moving target and expected to have bugs.
-## Tragedy's Data Model
+## Understanding Tragedy's Data Model
In Tragedy you build your data model from Models and Indexes. An abstract *Model* specifies the kind data that can be stored in a Model-Instance. We also call a Model-Instance a Row, since specific Model-Instances are uniquely identified by their unique RowKey. Knowing the Model and RowKey is all you need to store and retrieve data from Cassandra. The attributes of the Model correspond to the Columns of a Row. Each Column has a Field-Type like StringField or IntegerField. The RowKey decides which specific Row/Model-Instance the user is referring to and on which physical machine the data is stored. If you lose a RowKey, you can never store or retrieve that data again. Any Unicode string can be used as RowKey as long as it is unique among all Rows of a Model. If there's no naturally unique identifier for the data in a Row, you can ask Tragedy to generate a UUID-RowKey for you.
@@ -41,15 +41,15 @@ TweetsSent is an abstract Index over Tweets sorted by Cassandra's TimeUUIDType.
tweets_by_user = TweetsSent(by_username='merlin').load()
print tweets_by_user
-The main difference between Indexes and Models is that Indexes keep track of an unlimited amount of ordered data of the same kind (normally ForeignKeys), whereas a Model keeps track of a limited number of data that can be any mixture of types. Indexes are most often used to to help us find Data whose RowKey we've forgotten. Models can refer to Indexes using ForeignKeys, and Indexes can refer to both Models and (less often) other Indexes. The call above gives us a list of Tweets previously posted by user 'merlin' with their RowKeys correctly set. However, since the Index only contains references the actual tweet data hasn't been loaded yet at this point. If we tried to work with those tweets, we'd see #MISSING# fields all over the place:
-
- [<Tweet 8649a1ca4ab843b9afa6cc954908ac04: {'message': '#MISSING#', 'author': '#MISSING#'}, ...]
+The main difference between Indexes and Models is that Indexes keep track of an unlimited amount of ordered data of the same kind (normally ForeignKeys), whereas a Model keeps track of a limited number of data that can be any mixture of types. Indexes are most often used to to help us find Data whose RowKey we've forgotten. Models can refer to Indexes using ForeignKeys, and Indexes can refer to both Models and (less often) other Indexes. The call above gives us a list of Tweets previously posted by user 'merlin' with their RowKeys correctly set. However, since the Index only contains references the actual tweet data hasn't been loaded yet at this point. If we tried to work with those tweets, we'd see only empty tweets:
+ <TweetsSent merlin: O({'Sat Jun 26 04:18:14 2010': <Tweet 7e991c64732b4f8194d7c857f9522101: {}>})>
+
To actually load the tweets we need to resolve them (retrieve them using their RowKeys). Luckily Indexes have the .resolve() helper to make this easy:
tweets_by_user.resolve()
print tweets_by_user
- [<Tweet ced314748d574379a817e1a1c9149789: {'message': "some message", 'author': <User merlin: {'password': '#MISSING#'}>}>
+ [<Tweet 7e991c64732b4f8194d7c857f9522101: {'message': 'tweeting from tragedy', 'author': <User 20336bbf91d5407283dd553593c38e03: {}>}>]
Behind the scenes Index.resolve() almost works like calling Model.load() on all Tweets in the list. It's more efficient though, since this combines all required queries into one multiquery for faster processing. Now we've seen how to create tweets, store them, and find them again. If you want to see how you can distribute them to Followers, scroll down for a full example of a twitter-like application.
@@ -58,8 +58,8 @@ That's about it for the basics. There's more stuff Tragedy can do for you, like
## Installation
$ setup.py install (optionally --cassandra to install the compiled cassandra thrift bindings)
-## IRC and Contact
-Come hang out on #cassandra on irc.freenode.net. Email: enki@bbq.io. Twitter: [@enkido](http://twitter.com/enkido).
+## IRC
+Come hang out on #cassandra on irc.freenode.net.
## Example (full twitter-demo)
View
77 examples/twitty.py
@@ -14,72 +14,33 @@ class User(Model):
lastname = UnicodeField(mandatory=False) # normally fields are mandatory
password = UnicodeField()
- allusers = AllIndex()
- by_lastname = SecondaryIndex(lastname)
- by_firstname = SecondaryIndex(firstname)
-
- following = ObjectIndex(target_model='User')
- followed_by = ObjectIndex(target_model='User')
-
- tweets_sent = ObjectIndex(target_model='Tweet')
- tweets_received = ObjectIndex(target_model='Tweet')
-
- def follow(self, *one_or_more):
- fol = self.following()
- for other in one_or_more:
- fol.append(other)
- other.followed_by().append(self).save()
- fol.save()
- # print "FOLLOW", fol, self.followed_by(user=other).load()
-
- def tweet(self, message):
- new_tweet = Tweet(author=self, message=message[:140]).save()
- # print 'wtf', new_tweet
- a = self.tweets_sent()
- # print 'TWOP', a, a._row_key_name
- a.append( new_tweet ).save()
- # print 'FROB', a
-
- for follower in self.followed_by().load():
- # print 'FOLLOWER', follower
- follower.receive(new_tweet)
-
- def receive(self, tweet):
- # print self, 'RECEIVING', tweet
- self.tweets_received().append(tweet).save()
-
class Tweet(Model):
uuid = RowKey(autogenerate=True) # generate a UUID for us.
message = UnicodeField()
author = ForeignKey(foreign_class=User, mandatory=True)
alltweets = AllIndex()
-
-twitty_keyspace.connect(servers=['localhost:9160'], auto_create_models=True, auto_drop_keyspace=True)
-
-dave = User(username='dave', firstname='dave', password='test').save()
-bood = User(username='dave', firstname='dave', lastname='Bood', password='super').save()
+class TweetsSent(Index):
+ by_username = RowKey()
+ targetmodel = ForeignKey(foreign_class=Tweet, compare_with='TimeUUIDType')
-merlin = User(username='merlin', firstname='merlin', lastname='Bood', password='sunshine').save()
-peter = User(username='peter', firstname='Peter', password='secret').save()
+def run():
+ # Connect to cassandra
+ twitty_keyspace.connect(servers=['localhost:9160'], auto_create_models=True, auto_drop_keyspace=True)
-dave.follow(merlin, peter)
-peter.follow(merlin)
-merlin.follow(dave)
+ dave = User(username='dave', firstname='dave', password='test').save()
+ merlin = User(username='merlin', firstname='merlin', lastname='Bood', password='sunshine').save()
+ peter = User(username='peter', firstname='Peter', password='secret').save()
-merlin.tweet("i've just started using twitty. send me a message!")
-dave.tweet('making breakfast')
-peter.tweet('sitting at home being bored')
-
-print 'A', User.allusers(), list(User.allusers().load().resolve())
-print 'B', User.by_lastname('Bood'), list(User.by_lastname('Bood').load().resolve())
-print 'C', dave.tweets_received(), list(dave.tweets_received().load().resolve())
+ new_tweet = Tweet(author=dave, message='tweeting from tragedy').save()
+ merlinIndex = TweetsSent(by_username=merlin['username'])
+ merlinIndex.append(new_tweet)
+ merlinIndex.save()
+
+ tweets_by_user = TweetsSent(by_username='merlin').load()
+ print tweets_by_user
+ print list(tweets_by_user.resolve())
-#
-# for dude in (dave,peter,merlin):
-# name = dude['username']
-# print '%s has these followers:' % (name,), dude.get_followed_by().values()
-# print '%s follows' % (name,), dude.get_following().values()
-# print '%s sent' % (name,), [x for x in dude.get_tweets_sent(count=3)]
-# print '%s received' % (name,), [x for x in dude.get_tweets_received(count=3)]
+if __name__ == '__main__':
+ run()
View
3 tragedy/__init__.py
@@ -19,8 +19,7 @@
DictField,
ListField,
TimestampField,
- ObjectIndex,
- CustomIndex,
+ ManualIndex,
AllIndex,
SecondaryIndex,
JSONField,
View
12 tragedy/columns.py
@@ -148,6 +148,9 @@ def value_to_internal(self, instance):
if hasattr(instance, 'row_key'):
return instance.row_key
return instance
+
+ # def key_to_display(self, key):
+ # return time.ctime(timestamp.fromUUID(uuid.UUID(bytes=key)))
class MissingField(Field):
def key_to_internal(self, column_key):
@@ -186,10 +189,7 @@ def value_to_external(self, value):
DictField = JSONField
ListField = JSONField
-class CustomIndex(BaseField):
- pass
-
-class ObjectIndex(BaseField):
+class ManualIndex(BaseField):
default_key = None
autosetrow = True
def __init__(self, target_model, *args, **kwargs):
@@ -211,7 +211,7 @@ def target_model(self):
self.doresolve()
return self._target_model
-class SecondaryIndex(ObjectIndex):
+class SecondaryIndex(ManualIndex):
autosave = True
autosetrow = False
def __init__(self, target_field, *args, **kwargs):
@@ -222,7 +222,7 @@ def target_model(self):
# print 'OWNER', self.target_field.get_owner()
return self.target_field.get_owner()
-class AllIndex(ObjectIndex):
+class AllIndex(ManualIndex):
autosave = True
default_key = '!ALL!'
def __init__(self, *args, **kwargs):
View
15 tragedy/datastructures.py
@@ -158,9 +158,10 @@ def keys(self):
iteritems = DictMixin.iteritems
def __repr__(self):
- if not self:
- return '%s()' % (self.__class__.__name__,)
- return '%s(%r)' % (self.__class__.__name__, self.items())
+ # if not self:
+ # return '%s()' % (self.__class__.__name__,)
+ # return '%s(%r)' % (self.__class__.__name__, self.items())
+ return 'O({' + ','.join([ "%r: %r" % (key, value) for key, value in self.items()]) + '})'
def copy(self):
return self.__class__(self)
@@ -180,7 +181,7 @@ def __eq__(self, other):
def __ne__(self, other):
return not self == other
-try:
- from collections import OrderedDict
-except:
- OrderedDict = _OrderedDict
+# try:
+# from collections import OrderedDict
+# except:
+OrderedDict = _OrderedDict
View
12 tragedy/hierarchy.py
@@ -79,7 +79,7 @@ def path(self):
return u'%s%s%s' % (self.cluster.name, CASPATHSEP, self.name)
def register_model(self, name, model):
- print 'REGISTER MODEL', name
+ # print 'REGISTER MODEL', name
self.models[name] = model
def __str__(self):
@@ -94,7 +94,7 @@ def register_keyspace_with_cassandra(self):
def verify_datamodel(self, **kwargs):
self._first_iteration_in_this_cycle = True
- print 'VERIFY', kwargs
+ # print 'VERIFY', kwargs
for model in self.models.values():
self.verify_datamodel_for_model(model=model, **kwargs)
@@ -111,15 +111,15 @@ def verify_keyspace_for_model(cls, model, **kwargs):
client = model.getclient()
allkeyspaces = client.describe_keyspaces()
if first_iteration and model._keyspace.name in allkeyspaces and kwargs['auto_drop_keyspace']:
- print 'Autodropping keyspace %s' % (model._keyspace,)
+ print 'Autodropping keyspace %s...' % (model._keyspace,)
client.set_keyspace(model._keyspace.name) # this op requires auth
client.system_drop_keyspace(model._keyspace.name)
allkeyspaces = client.describe_keyspaces()
if not model._keyspace.name in allkeyspaces:
- print "Cassandra doesn't know about keyspace %s (only %s)" % (model._keyspace, allkeyspaces)
+ print "Cassandra doesn't know about keyspace %s (only %s)" % (model._keyspace, repr(tuple(allkeyspaces))[1:-1])
if kwargs['auto_create_models']:
- print 'Creating...', kwargs['auto_create_models']
+ print 'Creating keyspace %s...' % (model._keyspace,)
model._keyspace.register_keyspace_with_cassandra()
@classmethod
@@ -139,7 +139,7 @@ def verify_columnfamilies_for_model(cls, model, **kwargs):
if not model._column_family in mykeyspace.keys():
print "Cassandra doesn't know about ColumnFamily '%s'." % (model._column_family,)
if kwargs['auto_create_models']:
- print 'Creating...'
+ print 'Creating ColumnFamily %s...' % (model._column_family,)
model.register_columnfamiliy_with_cassandra()
mykeyspace = client.describe_keyspace(model._keyspace.name)
mycf = mykeyspace[model._column_family]
View
29 tragedy/models.py
@@ -1,8 +1,7 @@
from .rows import DictRow, RowKey
from .columns import (ByteField,
TimeField,
- ObjectIndex,
- CustomIndex,
+ ManualIndex,
SecondaryIndex,
ForeignKey,
BaseField,
@@ -49,9 +48,7 @@ def _init_stage_two(cls, *args, **kwargs):
@classmethod
def _activate_autoindexes(cls):
for key, value in cls.__dict__.items():
- if isinstance(value, CustomIndex):
- pass
- elif isinstance(value, ObjectIndex):
+ if isinstance(value, ManualIndex):
# print 'SCREAM', cls, key, value, value.target_field, 'Auto_%s_%s' % (value.target_model._column_family, key)
default_field = value.target_model
if value.target_field:
@@ -61,7 +58,7 @@ def _activate_autoindexes(cls):
default_key = getattr(value, 'default_key', None)
autosetrow = getattr(value, 'autosetrow', False)
- class ObjectIndexImplementation(GeneratedIndex):
+ class ManualIndexImplementation(GeneratedIndex):
_column_family = 'Auto_%s_%s' % (cls._column_family, key)
_default_field = ForeignKey(foreign_class=default_field, unique=True)
_index_name = key
@@ -80,7 +77,7 @@ def __init__(self, *args, **kwargs):
@classmethod
def target_saved(cls, instance):
- print 'AUTOSAVE', cls._column_family, cls._index_name, getattr(cls,'_target_fieldname', None), instance.row_key, instance
+ # print 'AUTOSAVE', cls._column_family, cls._index_name, getattr(cls,'_target_fieldname', None), instance.row_key, instance
default_key = cls._default_key
# print 'WORKING WITH', cls._column_family, cls._target_fieldname, default_key
@@ -97,20 +94,28 @@ def target_saved(cls, instance):
pass # not mandatory
# print 'OHAIFUCK TARGETMODEL', cls._column_family, value.target_model
- setattr(ObjectIndexImplementation, cls._column_family.lower(), RowKey())
- # print 'SETTING', cls, key, ObjectIndexImplementation
- setattr(cls, key, ObjectIndexImplementation)
+ setattr(ManualIndexImplementation, cls._column_family.lower(), RowKey())
+ # print 'SETTING', cls, key, ManualIndexImplementation
+ setattr(cls, key, ManualIndexImplementation)
# print getattr(cls, key)
if getattr(value, 'autosave', False):
- cls.save_hooks.add(ObjectIndexImplementation.target_saved)
+ cls.save_hooks.add(ManualIndexImplementation.target_saved)
class Index(DictRow):
"""A row which doesn't care about column names, and that can be appended to."""
__abstract__ = True
- _default_field = ByteField()
+ # _default_field = ByteField()
+ _order_by = 'TimeUUIDType'
_ordered = True
+ @classmethod
+ def _init_class(cls, *args, **kwargs):
+ super(Index, cls)._init_class(*args, **kwargs)
+ if hasattr(cls, 'targetmodel'):
+ cls._default_field = cls.targetmodel
+ del cls.targetmodel
+
def is_unique(self, target):
if self._order_by != 'TimeUUIDType':
return True
View
6 tragedy/rows.py
@@ -202,7 +202,7 @@ def listMissingColumns(self):
if spec.mandatory and (self.column_values.get(column_key) is None):
if spec.default:
default = spec.get_default()
- self.set_value_for_columnkey(column_key, default)
+ # self.set_value_for_columnkey(column_key, default)
else: #if not hasattr(self, '_default_field'): # XXX: i think this was meant to check if self is an index?
missing_cols.add(column_key)
@@ -375,7 +375,7 @@ def load(self, *args, **kwargs):
@classmethod
def multiget_slice(cls, keys=None, consistency_level=None, **kwargs):
assert keys, 'Need a non-null non-empty keys argument.'
- print 'GETTING', cls, keys, kwargs
+ # print 'GETTING', cls, keys, kwargs
predicate = cls.get_slice_predicate(**kwargs)
key_slices = cls.getclient().multiget_slice( # keyspace = str(cls._keyspace),
@@ -425,7 +425,7 @@ def _real_save(self, save_row_key=None, *args, **kwargs):
assert isinstance(value, basestring), 'Not basestring %s:%s (%s)' % (column_key, type(value), type(self))
newtimestamp = self._timestamp_func()
import time
- print 'STORING WITH NEWTIMESTAMP', self.__class__, column_key, newtimestamp #time.ctime( int(newtimestamp) )
+ # print 'STORING WITH NEWTIMESTAMP', self.__class__, column_key, newtimestamp #time.ctime( int(newtimestamp) )
column = Column(name=column_key, value=value, clock=Clock(timestamp=newtimestamp))
save_columns.append( ColumnOrSuperColumn(column=column) )

0 comments on commit a188bd5

Please sign in to comment.