class Token(Base): __acl__ = ( Allow(Everyone, Create, Fields()), Allow(Everyone, Read, Fields( 'id', 'claimed' )), Allow(Everyone, Update, Fields( 'claimed', 'account_id', 'account_provider_id' )) ) __table_args__ = ( sql.PrimaryKeyConstraint( 'id'), sql.ForeignKeyConstraint( ['account_id', 'account_provider_id'], ['account.id', 'account.provider_id']) ) id = sql.Column(sql.String(16), default=functools.partial(gen_token, 6)) claimed = sql.Column(sql.Boolean, default=False) account_provider_id = sql.Column(sql.String(16)) account_id = sql.Column(sql.String(32)) account = orm.relation( 'Account', single_parent=True) parent = orm.synonym('account')
def fields(self, value): """Fields can be a set of column names and include dotted syntax. A dotted field notation like `foo.bar` instructs the model to look up its `foo` relation and render its `bar` attribute. {'foo': {'bar': 42}} If the `foo` relation is one to many, the `bar` attribute is rendered from all the members in `foo`. {'foo': [{'bar': 73}, {'bar': 89}]} """ tree = {} flat = [] for field in value: key, *path = field.split('.', 1) flat.append(key) if path: tree[key] = tree.get(key, []) + list(path) for field, paths in tree.items(): should_expand, is_list = self._inspect_field(field) if should_expand: relations = getattr(self, field) if not is_list: relations = [relations] for relation in relations: if isinstance(relation, Base): relation.fields = Fields(*paths) self._fields = Fields(*flat)
class FavouriteItem(TracklistItemMixin, Base): __acl__ = (Allow( Parent, Create, Fields('favourite_id', 'favourite_provider_id', 'account_id', 'account_provider_id', 'track_id', 'track_provider_id')), Allow(Owner, Read, Fields('id', 'track_id', 'track_provider_id')), Allow(Owner, Delete), Allow(Parent, Query, Fields('favourite'))) __table_args__ = (sql.PrimaryKeyConstraint('id'), sql.ForeignKeyConstraint( ['favourite_provider_id', 'favourite_id'], ['favourite.provider_id', 'favourite.id']), sql.ForeignKeyConstraint( ['account_id', 'account_provider_id'], ['account.id', 'account.provider_id']), sql.ForeignKeyConstraint(['track_provider_id'], ['provider.id'])) provider_id = orm.synonym('favourite_provider_id') favourite_id = sql.Column(sql.String(96), nullable=False) favourite_provider_id = sql.Column(sql.String(16), nullable=False) favourite = orm.relation('Favourite', back_populates='items') parent = orm.synonym('favourite')
class Session(Base): __acl__ = ( Allow(Owner, Create, Fields( 'account_id', 'account_provider_id', 'system', 'browser', 'screen' )), Allow(Owner, Read, Fields()), Deny() ) __table_args__ = ( sql.PrimaryKeyConstraint( 'id'), sql.ForeignKeyConstraint( ['account_id', 'account_provider_id'], ['account.id', 'account.provider_id']) ) id = sql.Column(sql.String(64), default=functools.partial(gen_token, 64)) account_id = sql.Column(sql.String(32), nullable=False) account_provider_id = sql.Column(sql.String(16), nullable=False) account = orm.relation( 'Account', back_populates='sessions', uselist=False, single_parent=True) parent = orm.synonym('account') system = sql.Column(sql.String(64), nullable=False) browser = sql.Column(sql.String(64), nullable=False) screen = sql.Column(sql.String(32), nullable=False)
def test_available_fields_are_always_contained_in_specific_fields(): target = mock.Mock() f1 = Available(target) f2 = Fields('ten', 'six', 'two') assert f1 in f2 f1 = Available(target) f2 = Fields() assert f1 in f2
def test_fields_should_check_field_containment_against_values(): fields = Fields('one', 'two', 'six') assert 'one' in fields assert 'zero' not in fields f1 = Fields('one', 'five') assert f1 not in fields f2 = Fields('one', 'two', 'six', 'nine') assert f2 not in fields f3 = Fields('one', 'six') assert f3 in fields
class Provider(Base): __acl__ = (Allow(Everyone, Read, Fields('id', 'client_id')), Allow(Everyone, Query, Fields('id'))) __table_args__ = (sql.PrimaryKeyConstraint('id'), ) id = sql.Column(sql.String(12)) provider_id = orm.synonym('id') @property def client_id(self): if self.id in opt.options['providers']: return opt.options[self.id]['api_key']
class TrackComment(Transient): __acl__ = ( Allow(Everyone, Read, Fields( 'id', 'provider_id', 'account.id', 'account.provider_id', 'account.title', 'account.image.small', 'account.image.medium', 'account.image.large', 'body', 'timestamp', 'track_id', 'track_provider_id', 'created' )), ) id = None provider_id = None account = None body = None timestamp = None track_id = None track_provider_id = None
def event_hook(redis_pool, method, mapper, connection, target): target.fields = Fields(*target.__fields__) cache = redis.Redis(connection_pool=redis_pool) for pattern in target.__channel__: channel = pattern.format(**target.__dict__) message = json.dumps( { 'channel': channel, 'method': method, 'body': target }, cls=Encoder) start = time.time() try: cache.publish(channel, message) except redis.exceptions.ConnectionError: status_code = 503 host = '::1' else: status_code = 200 host = cache.connection_pool.connection_kwargs['host'] pub_time = 1000.0 * (time.time() - start) app_log.info('{} REDIS {} {} ({}) {:.2f}ms'.format( status_code, method.upper(), channel, host, pub_time))
class Image(Base): __acl__ = (Allow( Everyone, Read, Fields('id', 'small', 'medium', 'large', 'created', 'updated')), Deny()) __table_args__ = (sql.PrimaryKeyConstraint('id'), ) id = sql.Column(sql.Integer) small = sql.Column(sql.String(256)) medium = sql.Column(sql.String(256)) large = sql.Column(sql.String(256), nullable=False) def copy(self): return Image(small=self.small, medium=self.medium, large=self.large) @classmethod def from_soundcloud(cls, url): if isinstance(url, str): return cls(small=url, medium=url.replace('large', 't300x300'), large=url.replace('large', 't500x500')) @classmethod def from_youtube(cls, thumbnails): if isinstance(thumbnails, dict): return cls(small=thumbnails.get('default', {}).get('url'), medium=thumbnails.get('medium', {}).get('url'), large=thumbnails.get('high', {}).get('url'))
def test_controller_should_raise_not_found_on_failed_update(db, current_user): controller = MyController(db, current_user, Account, mock.Mock()) ids = {'id': 'does-not-exist', 'provider_id': 'unheard-of'} kw = {'title': 'foo', 'refresh_token': 'bar'} with pytest.raises(ControllerException) as error: yield controller.update(ids, kw, Fields('user_id', 'title')) assert error.value.status_code == 404
def test_fields_should_be_eager_with_values_and_lazy_with_targets(): fields = Fields('one', 'two', 'six') assert fields._target is None assert fields._values == {'one', 'two', 'six'} target = object() assert fields in fields(target) assert fields(target)._target is target assert set(fields) == {'one', 'two', 'six'}
def test_controller_should_search_using_query_and_read_all_entities( db, current_user, account): controller = MyController(db, current_user, Account, mock.Mock()) ids = {'id': account.id, 'provider_id': account.provider_id} entities = yield controller.search(ids, {}, Fields('id')) assert controller.policy.grant_read.call_args[0][:-1] == (account, entities) assert set(controller.policy.grant_read.call_args[0][-1]) == {'id'}
def test_controller_should_read_entity_by_the_books(db, current_user, account): controller = MyController(db, current_user, Account, mock.Mock()) ids = {'id': account.id, 'provider_id': account.provider_id} entity = yield controller.read(ids, Fields('title', 'provider_id')) assert entity is account assert controller.policy.grant_read.call_args[0][:-1] == (account, entity) assert set(controller.policy.grant_read.call_args[0][-1]) == { 'provider_id', 'title' }
class Favourite(TracklistMixin, Base): __acl__ = (Allow( Owner, Read, Fields('id', 'provider_id', 'account_id', 'account_provider_id')), ) account = orm.relation('Account', back_populates='favourite', viewonly=True) items = orm.relation('FavouriteItem', cascade='all, delete-orphan', order_by='FavouriteItem.created', single_parent=True)
class Image(Base): __acl__ = (Allow( Everyone, Read, Fields('id', 'small', 'medium', 'large', 'created', 'updated')), Deny()) __table_args__ = (sql.PrimaryKeyConstraint('id'), ) id = sql.Column(sql.Integer) small = sql.Column(sql.String(256)) medium = sql.Column(sql.String(256)) large = sql.Column(sql.String(256), nullable=False) def copy(self): return Image(small=self.small, medium=self.medium, large=self.large)
def test_controller_should_update_entity_and_read_result( db, current_user, account): controller = MyController(db, current_user, Account, mock.Mock()) ids = {'id': account.id, 'provider_id': account.provider_id} kw = {'title': 'foo', 'refresh_token': 'bar'} entity = yield controller.update(ids, kw, Fields('user_id', 'title')) assert entity is account assert sqlalchemy.orm.util.object_state(entity).persistent assert controller.policy.grant_update.call_args[0][:-1] == (account, entity) assert set(controller.policy.grant_update.call_args[0][-1]) == { 'title', 'refresh_token' } assert controller.policy.grant_read.call_args[0][:-1] == (account, entity) assert set( controller.policy.grant_read.call_args[0][-1]) == {'user_id', 'title'}
class User(Base): __acl__ = (Allow( Child, Read, Fields('id', 'provider_id', 'accounts.id', 'accounts.provider_id', 'accounts.connected', 'accounts.favourite_id', 'accounts.image.id', 'accounts.image.small', 'accounts.image.medium', 'accounts.image.large', 'accounts.title', 'created', 'updated')), ) __table_args__ = (sql.PrimaryKeyConstraint('id'), ) id = sql.Column(sql.Integer) provider_id = 'cloudplayer' accounts = orm.relation('Account', back_populates='user', uselist=True, single_parent=True, cascade='all, delete-orphan') children = orm.synonym('accounts')
def test_controller_should_create_entity_and_read_result( db, current_user, account, user): controller = MyController(db, current_user, Account, mock.Mock()) ids = {'id': '1234', 'provider_id': 'cloudplayer'} kw = {'title': 'foo', 'access_token': 'bar', 'user_id': user.id} entity = yield controller.create(ids, kw, Fields('id', 'title')) assert entity.id == '1234' assert entity.provider_id == 'cloudplayer' assert entity.title == 'foo' assert entity.access_token == 'bar' assert sqlalchemy.orm.util.object_state(entity).persistent assert controller.policy.grant_create.call_args[0][:-1] == (account, entity) assert set(controller.policy.grant_create.call_args[0][-1]) == { 'provider_id', 'title', 'title', 'access_token', 'id', 'user_id' } assert controller.policy.grant_read.call_args[0][:-1] == (account, entity) assert set( controller.policy.grant_read.call_args[0][-1]) == {'id', 'title'}
class Track(Transient): __acl__ = (Allow( Everyone, Read, Fields('id', 'provider_id', 'account.id', 'account.provider_id', 'account.title', 'account.image.small', 'account.image.medium', 'account.image.large', 'aspect_ratio', 'duration', 'favourite_count', 'image.small', 'image.medium', 'image.large', 'play_count', 'title', 'created')), ) id = None provider_id = None account = None aspect_ratio = None duration = None favourite_count = None image = None play_count = None title = None
class Playlist(TracklistMixin, Base): __acl__ = ( Allow(Owner, Create, Fields( 'provider_id', 'account_id', 'account_provider_id', 'description', 'public', 'title' )), Allow(Owner, Read, Fields( 'id', 'provider_id', 'account_id', 'account_provider_id', 'description', 'follower_count', 'image.id', 'image.small', 'image.medium', 'image.large', 'public', 'title', 'created', 'updated' )), Allow(Owner, Update, Fields( 'description', 'public', 'title' )), Allow(Owner, Delete), Allow(Owner, Query, Fields( 'id', 'provider_id', 'account_id', 'account_provider_id' )), Deny() ) __channel__ = ( 'playlist.{provider_id}.{id}', ) __fields__ = ( 'id', 'provider_id', 'account_id', 'account_provider_id', 'description', 'follower_count', 'image.id', 'image.small', 'image.medium', 'image.large', 'public', 'title', 'created', 'updated' ) @declared_attr def __table_args__(cls): return super().__table_args__ + ( sql.ForeignKeyConstraint( ['image_id'], ['image.id']), ) account = orm.relation( 'Account', back_populates='playlists', cascade='all', viewonly=True) parent = orm.synonym('account') items = orm.relation( 'PlaylistItem', cascade='all, delete-orphan', order_by='PlaylistItem.rank', single_parent=True) description = sql.Column(sql.Unicode(5120), nullable=True) follower_count = sql.Column(sql.Integer, default=0) public = sql.Column(sql.Boolean, default=False) title = sql.Column(sql.Unicode(256), nullable=False) image_id = sql.Column(sql.Integer) image = orm.relation( 'Image', cascade='all, delete-orphan', single_parent=True, uselist=False)
def fields(self): return getattr(self, '_fields', Fields())
class Track(Transient): __acl__ = ( Allow(Everyone, Read, Fields( 'id', 'provider_id', 'account.id', 'account.provider_id', 'account.title', 'account.image.small', 'account.image.medium', 'account.image.large', 'aspect_ratio', 'duration', 'favourite_count', 'image.small', 'image.medium', 'image.large', 'play_count', 'title', 'created' )), ) id = None provider_id = None account = None aspect_ratio = None duration = None favourite_count = None image = None play_count = None title = None @classmethod def from_provider(cls, provider_id, track): if provider_id == 'soundcloud': return cls.from_soundcloud(track) elif provider_id == 'youtube': return cls.from_youtube(track) else: raise ValueError('unsupported provider') @classmethod def from_soundcloud(cls, track): user = track['user'] artist = Account( id=user['id'], provider_id='soundcloud', title=user['username'], image=Image.from_soundcloud(user.get('avatar_url'))) return cls( id=track['id'], provider_id='soundcloud', account=artist, aspect_ratio=1.0, duration=int(track['duration'] / 1000.0), favourite_count=track.get('favoritings_count', 0), image=Image.from_soundcloud(track.get('artwork_url')), play_count=track.get('playback_count', 0), title=track['title'], created=datetime.datetime.strptime( track['created_at'], '%Y/%m/%d %H:%M:%S %z')) @classmethod def from_youtube(cls, track): snippet = track['snippet'] player = track['player'] statistics = track['statistics'] duration = isodate.parse_duration(track['contentDetails']['duration']) artist = Account( id=snippet['channelId'], provider_id='youtube', image=None, title=snippet['channelTitle']) return cls( id=track['id'], provider_id='youtube', account=artist, aspect_ratio=( float(player['embedHeight']) / float(player['embedWidth'])), duration=int(duration.total_seconds()), favourite_count=statistics.get('likeCount', 0), image=Image.from_youtube(snippet.get('thumbnails')), play_count=statistics.get('viewCount', 0), title=snippet['title'], created=datetime.datetime.strptime( snippet['publishedAt'], '%Y-%m-%dT%H:%M:%S.%fZ'))
class Account(Base): __acl__ = (Allow( Owner, Read, Fields('id', 'provider_id', 'user_id', 'connected', 'favourite_id', 'image.id', 'image.small', 'image.medium', 'image.large', 'title', 'created', 'updated')), Allow(Owner, Update, Fields('image', 'title')), Allow( Everyone, Read, Fields('id', 'provider_id', 'image.id', 'image.small', 'image.medium', 'image.large', 'title')), Allow(Everyone, Query, Fields('id', 'provider_id', 'title')), Deny()) __fields__ = ('id', 'provider_id', 'user_id', 'connected', 'favourite_id', 'image_id', 'title', 'created', 'updated') __channel__ = ('account.{provider_id}.{id}', ) __table_args__ = (sql.PrimaryKeyConstraint('id', 'provider_id'), sql.ForeignKeyConstraint(['provider_id'], ['provider.id']), sql.ForeignKeyConstraint(['user_id'], ['user.id']), sql.ForeignKeyConstraint(['image_id'], ['image.id'])) id = sql.Column(sql.String(32)) account_id = orm.synonym('id') provider_id = sql.Column(sql.String(16), nullable=False) provider = orm.relation('Provider', cascade=None, uselist=False, viewonly=True) account_provider_id = orm.synonym('provider_id') user_id = sql.Column(sql.Integer, nullable=False) user = orm.relation('User', back_populates='accounts', uselist=False, viewonly=True) parent = orm.synonym('user') sessions = orm.relation('Session', back_populates='account', cascade='all, delete-orphan', single_parent=True, uselist=True) image_id = sql.Column(sql.Integer) image = orm.relation('Image', cascade='all, delete-orphan', single_parent=True, uselist=False) @property def favourite_id(self): if self.favourite: return self.favourite.id favourite = orm.relation('Favourite', back_populates='account', cascade='all, delete-orphan', single_parent=True, uselist=False) playlists = orm.relation('Playlist', back_populates='account', cascade='all, delete-orphan', single_parent=True, uselist=True) title = sql.Column('title', sql.Unicode(64)) access_token = sql.Column(sql.String(256)) refresh_token = sql.Column(sql.String(256)) token_expiration = sql.Column(sql.DateTime()) @property def connected(self): return self.provider_id == 'cloudplayer' or all( [self.access_token, self.refresh_token])