class OAuth2Client(db.Datetimed, db.Document): secret = db.StringField(default=lambda: gen_salt(50), required=True) type = db.StringField(choices=CLIENT_TYPES.keys(), default='public', required=True) profile = db.StringField(choices=CLIENT_PROFILES.keys(), default='web', required=True) grant_type = db.StringField(choices=GRANT_TYPES.keys(), default='code', required=True) name = db.StringField(required=True) description = db.StringField() owner = db.ReferenceField('User') organization = db.ReferenceField('Organization') image = db.ImageField(fs=images, basename=default_image_basename, thumbnails=[150, 25]) redirect_uris = db.ListField(db.StringField()) default_scopes = db.ListField(db.StringField(), default=SCOPES.keys()) meta = { 'collection': 'oauth2_client' } @property def client_id(self): return str(self.id) @property def client_secret(self): return self.secret @property def default_redirect_uri(self): return self.redirect_uris[0]
class Post(db.Datetimed, db.Document): name = db.StringField(max_length=255, required=True) slug = db.SlugField(max_length=255, required=True, populate_from='name', update=True) headline = db.StringField() content = db.StringField(required=True) image_url = db.StringField() image = db.ImageField(fs=images, basename=default_image_basename, thumbnails=IMAGE_SIZES) credit_to = db.StringField() credit_url = db.URLField() tags = db.ListField(db.StringField()) datasets = db.ListField( db.ReferenceField('Dataset', reverse_delete_rule=db.PULL)) reuses = db.ListField( db.ReferenceField('Reuse', reverse_delete_rule=db.PULL)) owner = db.ReferenceField('User') private = db.BooleanField() meta = { 'ordering': ['-created_at'], } def __unicode__(self): return self.name or '' @property def display_url(self): return url_for('posts.show', post=self)
class Topic(db.Document): name = db.StringField(max_length=255, required=True) slug = db.SlugField(max_length=255, required=True, populate_from='name', update=True) description = db.StringField() tags = db.ListField(db.StringField()) color = db.IntField() tags = db.ListField(db.StringField()) datasets = db.ListField( db.ReferenceField('Dataset', reverse_delete_rule=db.PULL)) reuses = db.ListField( db.ReferenceField('Reuse', reverse_delete_rule=db.PULL)) owner = db.ReferenceField('User') featured = db.BooleanField() private = db.BooleanField() def __unicode__(self): return self.name @property def display_url(self): return url_for('topics.display', topic=self)
class Fake(db.Document): title = db.StringField() description = db.StringField() tags = db.ListField(db.StringField()) other = db.ListField(db.StringField()) def __unicode__(self): return 'fake'
class Fake(db.Document): title = db.StringField() description = db.StringField() tags = db.ListField(db.StringField()) other = db.ListField(db.StringField()) meta = {'allow_inheritance': True} def __unicode__(self): return self.title
class Fake(db.Document): title = db.StringField() description = db.StringField() tags = db.ListField(db.StringField()) other = db.ListField(db.StringField()) nested = db.ListField(db.EmbeddedDocumentField(NestedFake)) metrics = db.DictField() def __unicode__(self): return 'fake'
class HarvestJob(db.Document): '''Keep track of harvestings''' created = db.DateTimeField(default=datetime.now, required=True) started = db.DateTimeField() ended = db.DateTimeField() status = db.StringField(choices=HARVEST_JOB_STATUS.keys(), default=DEFAULT_HARVEST_JOB_STATUS, required=True) errors = db.ListField(db.EmbeddedDocumentField(HarvestError)) items = db.ListField(db.EmbeddedDocumentField(HarvestItem)) source = db.ReferenceField(HarvestSource, reverse_delete_rule=db.NULLIFY)
class HarvestItem(db.EmbeddedDocument): remote_id = db.StringField() dataset = db.ReferenceField(Dataset) status = db.StringField(choices=HARVEST_ITEM_STATUS.keys(), default=DEFAULT_HARVEST_ITEM_STATUS, required=True) created = db.DateTimeField(default=datetime.now, required=True) started = db.DateTimeField() ended = db.DateTimeField() errors = db.ListField(db.EmbeddedDocumentField(HarvestError)) args = db.ListField(db.StringField()) kwargs = db.DictField()
class Post(db.Datetimed, db.Document): name = db.StringField(max_length=255, required=True) slug = db.SlugField(max_length=255, required=True, populate_from='name', update=True, follow=True) headline = db.StringField() content = db.StringField(required=True) image_url = db.StringField() image = db.ImageField(fs=images, basename=default_image_basename, thumbnails=IMAGE_SIZES) credit_to = db.StringField() credit_url = db.URLField() tags = db.ListField(db.StringField()) datasets = db.ListField( db.ReferenceField('Dataset', reverse_delete_rule=db.PULL)) reuses = db.ListField( db.ReferenceField('Reuse', reverse_delete_rule=db.PULL)) owner = db.ReferenceField('User') published = db.DateTimeField() meta = { 'ordering': ['-created_at'], 'indexes': [ '-created_at', '-published', ], 'queryset_class': PostQuerySet, } verbose_name = _('post') def __str__(self): return self.name or '' def url_for(self, *args, **kwargs): return url_for('posts.show', post=self, *args, **kwargs) @property def display_url(self): return self.url_for() @property def external_url(self): return self.url_for(_external=True) def count_discussions(self): # There are no metrics on Post to store discussions count pass
class GeoLevel(db.Document): id = db.StringField(primary_key=True) name = db.StringField(required=True) admin_level = db.IntField(min_value=ADMIN_LEVEL_MIN, max_value=ADMIN_LEVEL_MAX, default=100) parents = db.ListField(db.ReferenceField('self'))
class OAuth2Grant(db.Document): user = db.ReferenceField('User', required=True) client = db.ReferenceField('OAuth2Client', required=True) code = db.StringField(required=True) redirect_uri = db.StringField() expires = db.DateTimeField() scopes = db.ListField(db.StringField()) meta = { 'collection': 'oauth2_grant' } def __str__(self): return '<OAuth2Grant({0.client.name}, {0.user.fullname})>'.format(self) def is_expired(self): return self.expires < datetime.utcnow() def get_redirect_uri(self): return self.redirect_uri def get_scope(self): return ' '.join(self.scopes)
class SpatialCoverage(db.EmbeddedDocument): """Represent a spatial coverage as a list of territories and/or a geometry. """ geom = db.MultiPolygonField() zones = db.ListField(db.ReferenceField(GeoZone)) granularity = db.StringField(default='other') @property def granularity_label(self): return _(dict(spatial_granularities)[self.granularity or 'other']) @property def top_label(self): if not self.zones: return None top = None for zone in self.zones: if not top: top = zone continue if zone.id in top.parents: top = zone return _(top.name) @property def handled_zones(self): """Return only zones with a dedicated page.""" return [zone for zone in self.zones if zone.handled_level]
class OAuth2Token(db.Document): client = db.ReferenceField('OAuth2Client', required=True) user = db.ReferenceField('User') # currently only bearer is supported token_type = db.StringField(choices=TOKEN_TYPES.keys(), default='Bearer') access_token = db.StringField(unique=True) refresh_token = db.StringField(unique=True, sparse=True) created_at = db.DateTimeField(default=datetime.utcnow, required=True) expires_in = db.IntField(required=True, default=TOKEN_EXPIRATION) scopes = db.ListField(db.StringField()) meta = {'collection': 'oauth2_token'} def __unicode__(self): return '<OAuth2Token({0.client.name})>'.format(self) def get_scope(self): return ' '.join(self.scopes) def get_expires_in(self): return self.expires_in def get_expires_at(self): return (self.created_at - EPOCH).total_seconds() + self.expires_in def is_refresh_token_expired(self): expired_at = datetime.fromtimestamp(self.get_expires_at()) expired_at += timedelta(days=REFRESH_EXPIRATION) return expired_at < datetime.utcnow()
class Discussion(db.Document): user = db.ReferenceField('User') subject = db.GenericReferenceField() title = db.StringField(required=True) discussion = db.ListField(db.EmbeddedDocumentField(Message)) created = db.DateTimeField(default=datetime.now, required=True) closed = db.DateTimeField() closed_by = db.ReferenceField('User') extras = db.ExtrasField() meta = { 'indexes': [ 'user', 'subject', '-created' ], 'ordering': ['-created'], } def person_involved(self, person): """Return True if the given person has been involved in the discussion, False otherwise. """ return any(message.posted_by == person for message in self.discussion) @property def external_url(self): return self.subject.url_for( _anchor='discussion-{id}'.format(id=self.id), _external=True)
class Fake(db.Document): title = db.StringField() description = db.StringField() tags = db.ListField(db.StringField()) other = db.ListField(db.StringField()) meta = {'allow_inheritance': True} def __unicode__(self): return self.title def __str__(self): return self.title def __html__(self): return '<span>{0}</span>'.format(self.title)
class Site(WithMetrics, db.Document): id = db.StringField(primary_key=True) title = db.StringField(required=True) keywords = db.ListField(db.StringField()) feed_size = db.IntField(required=True, default=DEFAULT_FEED_SIZE) configs = db.DictField() themes = db.DictField() settings = db.EmbeddedDocumentField(SiteSettings, default=SiteSettings)
class Team(db.EmbeddedDocument): name = db.StringField(required=True) slug = db.SlugField( max_length=255, required=True, populate_from='name', update=True, unique=False) description = db.StringField() members = db.ListField(db.ReferenceField('User'))
class HarvestJob(db.Document): '''Keep track of harvestings''' created = db.DateTimeField(default=datetime.now, required=True) started = db.DateTimeField() ended = db.DateTimeField() status = db.StringField(choices=HARVEST_JOB_STATUS.keys(), default=DEFAULT_HARVEST_JOB_STATUS, required=True) errors = db.ListField(db.EmbeddedDocumentField(HarvestError)) items = db.ListField(db.EmbeddedDocumentField(HarvestItem)) source = db.ReferenceField(HarvestSource, reverse_delete_rule=db.CASCADE) data = db.DictField() meta = { 'indexes': ['-created', 'source', ('source', '-created')], 'ordering': ['-created'], }
class License(db.Document): # We need to declare id explicitly since we do not use the default # value set by Mongo. id = db.StringField(primary_key=True) created_at = db.DateTimeField(default=datetime.now, required=True) title = db.StringField(required=True) slug = db.SlugField(required=True, populate_from='title') url = db.URLField() maintainer = db.StringField() flags = db.ListField(db.StringField()) active = db.BooleanField() def __unicode__(self): return self.title @classmethod def guess(cls, *strings, **kwargs): ''' Try to guess a license from a list of strings. Accept a `default` keyword argument which will be the default fallback license. ''' license = None for string in strings: license = cls.guess_one(string) if license: break return license or kwargs.get('default') @classmethod def guess_one(cls, text): ''' Try to guess license from a string. Try to exact match on identifier then slugified title and fallback on edit distance ranking (after slugification) ''' if not text: return qs = cls.objects text = text.strip().lower() # Stored identifiers are lower case slug = cls.slug.slugify(text) # Use slug as it normalize string license = qs(db.Q(id=text) | db.Q(slug=slug) | db.Q(url=text)).first() if license is None: # Try to single match with a low Damerau-Levenshtein distance computed = ((l, rdlevenshtein(l.slug, slug)) for l in cls.objects) candidates = [l for l, d in computed if d <= MAX_DISTANCE] # If there is more that one match, we cannot determinate # which one is closer to safely choose between candidates if len(candidates) == 1: license = candidates[0] return license @classmethod def default(cls): return cls.objects(id=DEFAULT_LICENSE['id']).first()
class Fake(db.Document): title = db.StringField() description = db.StringField() tags = db.ListField(db.StringField()) other = db.ListField(db.StringField()) nested = db.ListField(db.EmbeddedDocumentField(NestedFake)) sub = db.EmbeddedDocumentField(NestedFake) metrics = db.DictField() __metrics_keys__ = [ 'fake-metric-int', 'fake-metric-float', ] def __str__(self): return 'fake' def get_metrics(self): return self.metrics
class OAuth2Grant(db.Document): user = db.ReferenceField('User', required=True) client = db.ReferenceField('OAuth2Client', required=True) code = db.StringField(required=True) redirect_uri = db.StringField() expires = db.DateTimeField() scopes = db.ListField(db.StringField()) meta = {'collection': 'oauth2_grant'}
class GeoZone(db.Document): id = db.StringField(primary_key=True) name = db.StringField(required=True) level = db.StringField(required=True) code = db.StringField(unique_with='level') geom = db.MultiPolygonField(required=True) parents = db.ListField() keys = db.DictField() population = db.IntField() area = db.FloatField() meta = { 'indexes': [ 'name', 'parents', ('level', 'code'), ] } def __unicode__(self): return self.id __str__ = __unicode__ def __html__(self): return gettext(self.name) + ' <i>(' + self.code + ')</i>' @property def keys_values(self): """Key values might be a list or not, always return a list.""" keys_values = [] for value in self.keys.values(): if isinstance(value, list): keys_values += value elif not str(value).startswith('-'): # Avoid -99. keys_values.append(value) return keys_values def toGeoJSON(self): return { 'id': self.id, 'type': 'Feature', 'geometry': self.geom, 'properties': { 'name': self.name, 'level': self.level, 'code': self.code, 'parents': self.parents, 'keys': self.keys, 'population': self.population, 'area': self.area, } }
class License(db.Document): id = db.StringField(primary_key=True) created_at = db.DateTimeField(default=datetime.datetime.now, required=True) title = db.StringField(required=True) slug = db.SlugField(required=True, populate_from='title') url = db.URLField() maintainer = db.StringField() flags = db.ListField(db.StringField()) active = db.BooleanField() def __unicode__(self): return self.title
class Issue(db.Document): user = db.ReferenceField('User') subject = db.GenericReferenceField() title = db.StringField(required=True) discussion = db.ListField(db.EmbeddedDocumentField(Message)) created = db.DateTimeField(default=datetime.now, required=True) closed = db.DateTimeField() closed_by = db.ReferenceField('User') meta = { 'indexes': ['user', 'subject', '-created'], 'ordering': ['-created'], }
class OAuth2Token(db.Document): client = db.ReferenceField('OAuth2Client', required=True) user = db.ReferenceField('User') # currently only bearer is supported token_type = db.StringField(choices=TOKEN_TYPES.keys(), default='Bearer') access_token = db.StringField(unique=True) refresh_token = db.StringField(unique=True) expires = db.DateTimeField( default=lambda: datetime.utcnow() + timedelta(hours=TOKEN_EXPIRATION)) scopes = db.ListField(db.StringField()) meta = {'collection': 'oauth2_token'}
class Discussion(db.Document): user = db.ReferenceField('User') subject = db.ReferenceField(db.DomainModel) title = db.StringField(required=True) discussion = db.ListField(db.EmbeddedDocumentField(Message)) created = db.DateTimeField(default=datetime.now, required=True) closed = db.DateTimeField() closed_by = db.ReferenceField('User') meta = { 'indexes': ['user', 'subject', 'created'], 'allow_inheritance': True, 'ordering': ['created'], }
class License(db.Document): # We need to declare id explicitly since we do not use the default # value set by Mongo. id = db.StringField(primary_key=True) created_at = db.DateTimeField(default=datetime.now, required=True) title = db.StringField(required=True) slug = db.SlugField(required=True, populate_from='title') url = db.URLField() maintainer = db.StringField() flags = db.ListField(db.StringField()) active = db.BooleanField() def __unicode__(self): return self.title
class GeoZone(db.Document): id = db.StringField(primary_key=True) name = db.StringField(required=True) level = db.StringField(required=True) code = db.StringField(unique_with='level') geom = db.MultiPolygonField(required=True) parents = db.ListField() keys = db.DictField() population = db.IntField() area = db.FloatField() meta = { 'indexes': [ 'name', 'parents', ('level', 'code'), ] } def __unicode__(self): return self.id __str__ = __unicode__ def __html__(self): return gettext(self.name) + ' <i>(' + self.code + ')</i>' def toGeoJSON(self): return { 'id': self.id, 'type': 'Feature', 'geometry': self.geom, 'properties': { 'name': self.name, 'level': self.level, 'code': self.code, 'parents': self.parents, 'keys': self.keys, 'population': self.population, 'area': self.area, } }
class Discussion(db.Document): user = db.ReferenceField('User') subject = db.ReferenceField(db.DomainModel) title = db.StringField(required=True) discussion = db.ListField(db.EmbeddedDocumentField(Message)) created = db.DateTimeField(default=datetime.now, required=True) closed = db.DateTimeField() closed_by = db.ReferenceField('User') meta = { 'indexes': ['user', 'subject', 'created'], 'allow_inheritance': True, 'ordering': ['created'], } def person_involved(self, person): """Return True if the given person has been involved in the discussion, False otherwise. """ return any(message.posted_by == person for message in self.discussion)
class SpatialCoverage(db.EmbeddedDocument): """Represent a spatial coverage as a list of territories and/or a geometry. """ geom = db.MultiPolygonField() zones = db.ListField(db.ReferenceField(GeoZone)) granularity = db.StringField(default='other') @property def granularity_label(self): return dict(spatial_granularities).get(self.granularity or 'other', 'other') @property def top_label(self): if not self.zones: return None top = None for zone in self.zones: if not top: top = zone continue if zone.id in top.parents: top = zone return _(top.name) @property def handled_zones(self): """Return only zones with a dedicated page.""" return [zone for zone in self.zones if zone.handled_level] def clean(self): if 'geom' in self._get_changed_fields(): if self.zones: raise db.ValidationError( 'The spatial coverage already has a Geozone') if 'zones' in self._get_changed_fields(): if self.geom: raise db.ValidationError( 'The spatial coverage already has a Geometry')