class BaseStormOpenIDAssociation: """Database representation of a stored OpenID association.""" __storm_primary__ = ('server_url', 'handle') server_url = Unicode() handle = Unicode() secret = RawStr() issued = Int() lifetime = Int() assoc_type = Unicode() def __init__(self, server_url, association): super(BaseStormOpenIDAssociation, self).__init__() self.server_url = server_url.decode('UTF-8') self.handle = association.handle.decode('ASCII') self.update(association) def update(self, association): assert self.handle == association.handle.decode('ASCII'), ( "Association handle does not match (expected %r, got %r" % (self.handle, association.handle)) self.secret = association.secret self.issued = association.issued self.lifetime = association.lifetime self.assoc_type = association.assoc_type.decode('ASCII') def as_association(self): """Return an equivalent openid-python `Association` object.""" return Association( self.handle.encode('ASCII'), self.secret, self.issued, self.lifetime, self.assoc_type.encode('ASCII'))
class FakeStormCompoundPrimaryKeyClass(Storm): __storm_table__ = 'FakeTableWithCompoundPrimaryKey' __storm_primary__ = 'id1', 'id2' id1 = Int() id2 = Int()
class BugSubscriptionFilterMute(StormBase): """Bug subscription filters a person has decided to block emails from.""" implements(IBugSubscriptionFilterMute) __storm_table__ = "BugSubscriptionFilterMute" def __init__(self, person=None, filter=None): if person is not None: self.person = person if filter is not None: self.filter = filter.id person_id = Int("person", allow_none=False, validator=validate_person) person = Reference(person_id, "Person.id") filter_id = Int("filter", allow_none=False) filter = Reference(filter_id, "BugSubscriptionFilter.id") __storm_primary__ = 'person_id', 'filter_id' date_created = DateTime("date_created", allow_none=False, default=UTC_NOW, tzinfo=pytz.UTC)
class MusicAlbum(BaseModel): '''A music file container Music can be categorized many ways. Albums are found in the music file's ID3 tags ''' __storm_table__ = 'musicalbum' id = Int(primary=True) artist = Unicode() title = Unicode() year = Int() genre = Unicode() tracks = ReferenceSet('MusicAlbum.id', 'MusicTrack.album_id') def to_dict(self, recurse=True): '''See BaseModel.to_dict.''' ret = { 'id': self.id, 'artist': self.artist, 'title': self.title, 'year': self.year, 'genre': self.genre, } if recurse: ret['tracks'] = [ track.to_dict(recurse=False) for track in self.tracks ] return ret
class PhotoImage(BaseModel): '''Image file references and metadata''' __storm_table__ = 'photoimage' id = Int(primary=True) filename = Unicode() thumbnail = Unicode() title = Unicode() description = Unicode() creation_date = DateTime() album_id = Int() album = Reference(album_id, 'PhotoAlbum.id') def to_dict(self, recurse=True): '''See BaseModel.to_dict''' ret = { 'id': self.id, 'filename': self.filename, 'thumbnail': self.thumbnail, 'title': self.title, 'description': self.description, 'creation_date': self.creation_date, } if recurse: ret['album_id'] = self.album_id ret['album'] = self.album.to_dict(recurse=False) return ret
class MusicPlaylistTrack(BaseModel): '''Join table between MusicTrack and MusicPlaylist''' __storm_table__ = 'musicplaylisttrack' __storm_primary__ = 'track_id', 'playlist_id' track_id = Int(primary=True) playlist_id = Int()
class Egg(object): """ Test table. """ __storm_table__ = "egg" id = Int(primary=True) value = Int()
class XRef(StormBase): """Cross-reference between two objects. For references to local objects (there is currently no other kind), another reference in the opposite direction exists. The to_id_int and from_id_int columns exist for efficient SQL joins. They are set automatically when the ID looks like an integer. NOTE: This should rarely be used directly. Prefer IXRefSet unless porting an old query. """ __storm_table__ = 'XRef' __storm_primary__ = "from_type", "from_id", "to_type", "to_id" to_type = Unicode(allow_none=False) to_id = Unicode(allow_none=False) to_id_int = Int() # For efficient joins. from_type = Unicode(allow_none=False) from_id = Unicode(allow_none=False) from_id_int = Int() # For efficient joins. creator_id = Int(name="creator") creator = Reference(creator_id, "Person.id") date_created = DateTime(name='date_created', tzinfo=pytz.UTC) metadata = JSON()
class BuilderProcessor(StormBase): __storm_table__ = 'BuilderProcessor' __storm_primary__ = ('builder_id', 'processor_id') builder_id = Int(name='builder', allow_none=False) builder = Reference(builder_id, Builder.id) processor_id = Int(name='processor', allow_none=False) processor = Reference(processor_id, Processor.id)
class CategoryProduct(Storm): __storm_table__ = "sfec_category_product" __storm_primary__ = "category_id", "product_id" category_id = Int() product_id = Int()
class Bar(object): """ Test table referencing to C{Foo} """ __storm_table__ = "bar" id = Int(primary=True) title = Unicode() foo_id = Int() foo = DeferredReference(foo_id, Foo.id)
class Cart(BaseModel): __storm_table__ = "sfec_cart" order_id = Int() order = Reference(order_id, 'Order.id') user_id = Int() user = Reference(user_id, User.id) def __init__(self, user): self.order = Order() self.order.user_id = user.id self.user_id = user.id
class AccessPolicyArtifact(StormBase): implements(IAccessPolicyArtifact) __storm_table__ = 'AccessPolicyArtifact' __storm_primary__ = 'abstract_artifact_id', 'policy_id' abstract_artifact_id = Int(name='artifact') abstract_artifact = Reference(abstract_artifact_id, 'AccessArtifact.id') policy_id = Int(name='policy') policy = Reference(policy_id, 'AccessPolicy.id') @classmethod def create(cls, links): """See `IAccessPolicyArtifactSource`.""" return create((cls.abstract_artifact, cls.policy), links, get_objects=True) @classmethod def find(cls, links): """See `IAccessArtifactGrantSource`.""" links = list(links) if len(links) == 0: return EmptyResultSet() return IStore(cls).find( cls, Or(*(And(cls.abstract_artifact == artifact, cls.policy == policy) for (artifact, policy) in links))) @classmethod def delete(cls, links): cls.find(links).remove() @classmethod def findByArtifact(cls, artifacts): """See `IAccessPolicyArtifactSource`.""" ids = [artifact.id for artifact in artifacts] return IStore(cls).find(cls, cls.abstract_artifact_id.is_in(ids)) @classmethod def findByPolicy(cls, policies): """See `IAccessPolicyArtifactSource`.""" ids = [policy.id for policy in policies] return IStore(cls).find(cls, cls.policy_id.is_in(ids)) @classmethod def deleteByArtifact(cls, artifacts): """See `IAccessPolicyArtifactSource`.""" cls.findByArtifact(artifacts).remove()
class OrderProduct(BaseModel): __storm_table__ = "sfec_order_product" quantity = Int() order_id = Int() product_id = Int() order = Reference(order_id, 'Order.id') product = Reference(product_id, 'Product.id') def __init__(self, order, product, quantity): self.order = order self.product = product self.quantity = quantity
class Category(Storm): __storm_table__ = 'category' id = Int(primary=True, default=AutoReload) short_name = Unicode() name = Unicode() total_laps = Int() race_id = Int() race = Reference(race_id, 'Race.id') def update(self): self._complete_laps = None self._total_racers = None @property def total_racers(self): if hasattr(self, '_total_racers') and self._total_racers is not None: return self._total_racers store = Store.of(self) query = And(Racer.id == RacerLap.racer_id, Racer.category_id == self.id) data = store.using(RacerLap, Racer).find((Count(1)), query) data = list(data.group_by(Racer.category_id, Racer.id)) complete_racers = len([i for i in data if i == self.total_laps]) total_racers = Store.of(self).find(Racer, Racer.category == self).count() self._total_racers = '%s / %s' % (complete_racers, total_racers) return self._total_racers @property def is_last_lap(self): return self.completed_laps == (self.total_laps - 1) @property def completed_laps(self): if hasattr(self, '_complete_laps') and self._complete_laps is not None: return self._complete_laps store = Store.of(self) query = And(Racer.id == RacerLap.racer_id, Racer.category_id == self.id) data = store.using(RacerLap, Racer).find((Count(1)), query) data = data.group_by(Racer.category_id, Racer.id) self._complete_laps = max(list(data) or [0]) return self._complete_laps
class AccessArtifactGrant(StormBase): implements(IAccessArtifactGrant) __storm_table__ = 'AccessArtifactGrant' __storm_primary__ = 'abstract_artifact_id', 'grantee_id' abstract_artifact_id = Int(name='artifact') abstract_artifact = Reference(abstract_artifact_id, 'AccessArtifact.id') grantee_id = Int(name='grantee') grantee = Reference(grantee_id, 'Person.id') grantor_id = Int(name='grantor') grantor = Reference(grantor_id, 'Person.id') date_created = DateTime(tzinfo=pytz.UTC) @property def concrete_artifact(self): if self.abstract_artifact is not None: return self.abstract_artifact.concrete_artifact @classmethod def grant(cls, grants): """See `IAccessArtifactGrantSource`.""" return create((cls.abstract_artifact, cls.grantee, cls.grantor), grants, get_objects=True) @classmethod def find(cls, grants): """See `IAccessArtifactGrantSource`.""" return IStore(cls).find( cls, Or(*(And(cls.abstract_artifact == artifact, cls.grantee == grantee) for (artifact, grantee) in grants))) @classmethod def findByArtifact(cls, artifacts, grantees=None): """See `IAccessArtifactGrantSource`.""" artifact_ids = [artifact.id for artifact in artifacts] constraints = [cls.abstract_artifact_id.is_in(artifact_ids)] if grantees: grantee_ids = [grantee.id for grantee in grantees] constraints.append(cls.grantee_id.is_in(grantee_ids)) return IStore(cls).find(cls, *constraints) @classmethod def revokeByArtifact(cls, artifacts, grantees=None): """See `IAccessArtifactGrantSource`.""" cls.findByArtifact(artifacts, grantees).remove()
class Product(BaseModel): __storm_table__ = "sfec_product" name = Unicode() stock = Int(default=0) description = Unicode() price = Decimal() is_available = Bool(default=False) categories = ReferenceSet('Product.id', 'CategoryProduct.product_id', 'CategoryProduct.category_id', 'Category.id') # # Implicit Properties # @property def category_list(self): return [c.name for c in self.categories] def dict(self): pdict = super(Product, self).dict() pdict['price'] = float(pdict['price']) # price is decimal return pdict
class Race(Storm): __storm_table__ = 'race' id = Int(primary=True, default=AutoReload) name = Unicode() start_time = DateTime() end_time = DateTime() def start(self): now = datetime.datetime.now().replace(microsecond=0) self.start_time = now def get_categories(self): return Store.of(self).find(Category, race=self) @cached_property def start_hour(self): return self.start_time.time() @property def time_elapsed(self): if not self.start_time: return None delta = datetime.datetime.now() - self.start_time return datetime.timedelta(seconds=delta.seconds)
class CustomerService(BaseModel): __storm_table__ = "sfec_customer_service" order_id = Int() customer_id = Int() vendor_id = Int() customer = Reference(customer_id, Customer.id) vendor = Reference(vendor_id, Vendor.id) order = Reference(order_id, Order.id) def __init__(self, order, customer, vendor): self.order_id = order.id self.customer_id = customer.id self.vendor_id = vendor.id
class Foo(object): """ Test table. """ __storm_table__ = "foo" id = Int(primary=True) title = Unicode()
class RacerLap(Storm): __storm_table__ = 'racer_lap' id = Int(primary=True, default=AutoReload) event_time = DateTime() race_id = Int() race = Reference(race_id, 'Race.id') racer_id = Int() racer = Reference(racer_id, 'Racer.id') @property def previous_lap(self): laps = self.racer.get_laps(before=self.event_time) return laps.last() @cached_property def number(self): return self.racer.number @cached_property def name(self): return self.racer.name @cached_property def category(self): return self.racer.category.short_name @cached_property def remaining_laps(self): return self.racer.category.total_laps - self.lap_number @cached_property def lap_time(self): previous = self.previous_lap if previous: delta = self.event_time - previous.event_time else: # This is the first lap. Calculate it using the race start. delta = self.event_time - self.race.start_time # Create a new timedelta without the microseconds return datetime.timedelta(seconds=delta.seconds) @cached_property def lap_number(self): laps = self.racer.get_laps(before=self.event_time) return laps.count() + 1
class BaseModel(Storm): """Provides utilities for most of the SFEC database models""" __storm_primary__ = 'id' id = Int(default=AutoReload) # # Static API # @classmethod def find(cls, store, id): return store.find(cls, id=id).one() @classmethod def exists(cls, store, id): relation = cls.find(store, id) return relation is not None # # Public API # def dict(self): """Returns this object as a dictionary""" dictionary = {} for cls in self.__class__.__mro__: for key, value in cls.__dict__.iteritems(): if isinstance(value, Property): dictionary[key] = getattr(self, key) return dictionary def json(self): """Returns this object in JSON""" dictionary = {} for key, value in self.dict().iteritems(): dictionary[key] = value if isinstance(value, datetime): # Transforms the datetime into a JSON representation dictionary[key] = mktime(value.timetuple()) * 1000 return json.dumps(dictionary) # # Hooks # def __storm_pre_flush__(self): """Escape any string into a html escaped string""" attributes = self.__class__.__dict__.iteritems() attributes = { key: value for key, value in attributes if type(value) == Unicode } for key, value in attributes.iteritems(): value = getattr(self, key) or u'' setattr(self, key, escape(value))
class AccessPolicyGrant(StormBase): implements(IAccessPolicyGrant) __storm_table__ = 'AccessPolicyGrant' __storm_primary__ = 'policy_id', 'grantee_id' policy_id = Int(name='policy') policy = Reference(policy_id, 'AccessPolicy.id') grantee_id = Int(name='grantee') grantee = Reference(grantee_id, 'Person.id') grantor_id = Int(name='grantor') grantor = Reference(grantor_id, 'Person.id') date_created = DateTime(tzinfo=pytz.UTC) @classmethod def grant(cls, grants): """See `IAccessPolicyGrantSource`.""" return create((cls.policy, cls.grantee, cls.grantor), grants, get_objects=True) @classmethod def find(cls, grants): """See `IAccessPolicyGrantSource`.""" return IStore(cls).find( cls, Or(*(And(cls.policy == policy, cls.grantee == grantee) for (policy, grantee) in grants))) @classmethod def findByPolicy(cls, policies): """See `IAccessPolicyGrantSource`.""" ids = [policy.id for policy in policies] return IStore(cls).find(cls, cls.policy_id.is_in(ids)) @classmethod def revoke(cls, grants): """See `IAccessPolicyGrantSource`.""" cls.find(grants).remove() @classmethod def revokeByPolicy(cls, policies): """See `IAccessPolicyGrantSource`.""" cls.findByPolicy(policies).remove()
class BugSubscriptionFilterInformationType(StormBase): """Information types to filter.""" __storm_table__ = "BugSubscriptionFilterInformationType" __storm_primary__ = ('filter_id', 'information_type') filter_id = Int("filter", allow_none=False) filter = Reference(filter_id, "BugSubscriptionFilter.id") information_type = DBEnum(enum=InformationType, allow_none=False)
class BugSubscriptionFilterStatus(StormBase): """Statuses to filter.""" __storm_table__ = "BugSubscriptionFilterStatus" __storm_primary__ = ('filter_id', 'status') filter_id = Int("filter", allow_none=False) filter = Reference(filter_id, "BugSubscriptionFilter.id") status = DBEnum(enum=BugTaskStatus, allow_none=False)
class MilestoneTag(object): """A tag belonging to a milestone.""" __storm_table__ = 'milestonetag' id = Int(primary=True) milestone_id = Int(name='milestone', allow_none=False) milestone = Reference(milestone_id, 'milestone.id') tag = Unicode(allow_none=False) created_by_id = Int(name='created_by', allow_none=False) created_by = Reference(created_by_id, 'person.id') date_created = DateTime(allow_none=False) def __init__(self, milestone, tag, created_by, date_created=None): self.milestone_id = milestone.id self.tag = tag self.created_by_id = created_by.id if date_created is not None: self.date_created = date_created
class BugSubscriptionFilterImportance(StormBase): """Importances to filter.""" __storm_table__ = "BugSubscriptionFilterImportance" __storm_primary__ = ('filter_id', 'importance') filter_id = Int("filter", allow_none=False) filter = Reference(filter_id, "BugSubscriptionFilter.id") importance = DBEnum(enum=BugTaskImportance, allow_none=False)
class MusicPlaylist(BaseModel): '''A music file container Users can create and add music tracks to a playlist ''' __storm_table__ = 'musicplaylist' id = Int(primary=True) title = Unicode() tracks = ReferenceSet('MusicPlaylist.id', 'MusicPlaylistTrack.playlist_id', 'MusicPlaylistTrack.track_id', 'MusicTrack.id')
class BugSubscriptionFilterTag(StormBase): """Tags to filter.""" __storm_table__ = "BugSubscriptionFilterTag" id = Int(primary=True) filter_id = Int("filter", allow_none=False) filter = Reference(filter_id, "BugSubscriptionFilter.id") include = Bool(allow_none=False) tag = Unicode(allow_none=False) @property def qualified_tag(self): """The tag qualified with a hyphen if it is to be omitted.""" if self.include: return self.tag else: return u"-" + self.tag
class BugSummary(Storm): """BugSummary Storm database class.""" implements(IBugSummary) __storm_table__ = 'combinedbugsummary' id = Int(primary=True) count = Int() product_id = Int(name='product') product = Reference(product_id, Product.id) productseries_id = Int(name='productseries') productseries = Reference(productseries_id, ProductSeries.id) distribution_id = Int(name='distribution') distribution = Reference(distribution_id, Distribution.id) distroseries_id = Int(name='distroseries') distroseries = Reference(distroseries_id, DistroSeries.id) sourcepackagename_id = Int(name='sourcepackagename') sourcepackagename = Reference(sourcepackagename_id, SourcePackageName.id) milestone_id = Int(name='milestone') milestone = Reference(milestone_id, Milestone.id) status = EnumCol(dbName='status', schema=(BugTaskStatus, BugTaskStatusSearch)) importance = EnumCol(dbName='importance', schema=BugTaskImportance) tag = Unicode() viewed_by_id = Int(name='viewed_by') viewed_by = Reference(viewed_by_id, Person.id) access_policy_id = Int(name='access_policy') access_policy = Reference(access_policy_id, AccessPolicy.id) has_patch = Bool()