def test_records_deletion_when_no_records_exist(self): client = Client(server_url=self.server_url, auth=self.auth, bucket='mozilla', collection='payments') client.create_bucket() client.create_collection() deleted_records = client.delete_records() assert len(deleted_records) == 0
def test_multiple_record_deletion(self): client = Client(server_url=self.server_url, auth=self.auth, bucket='mozilla', collection='payments') client.create_bucket() client.create_collection() client.create_record({'foo': 'bar'}) client.delete_records() assert len(client.get_records()) == 0
def test_multiple_record_deletion(self): client = Client(server_url=self.server_url, auth=self.auth, bucket='mozilla', collection='payments') client.create_bucket() client.create_collection() client.create_record(data={'foo': 'bar'}) client.delete_records() assert len(client.get_records()) == 0
def test_single_record_creation_if_not_exists(self): client = Client(server_url=self.server_url, auth=self.auth, bucket='mozilla', collection='payments') client.create_bucket() client.create_collection() created = client.create_record(data={'foo': 'bar'}) client.create_record(data={'id': created['data']['id'], 'bar': 'baz'}, if_not_exists=True)
def test_one_record_deletion(self): client = Client(server_url=self.server_url, auth=self.auth, bucket='mozilla', collection='payments') client.create_bucket() client.create_collection() record = client.create_record({'foo': 'bar'}) deleted = client.delete_record(record['data']['id']) assert deleted['deleted'] is True assert len(client.get_records()) == 0
def test_records_list_retrieval(self): client = Client(server_url=self.server_url, auth=self.auth, bucket='mozilla', collection='payments') client.create_bucket() client.create_collection() client.create_record(data={'foo': 'bar'}, permissions={'read': ['account:alexis']}) records = client.get_records() assert len(records) == 1
def test_records_timestamp_retrieval(self): client = Client(server_url=self.server_url, auth=self.auth, bucket='mozilla', collection='payments') client.create_bucket() client.create_collection() record = client.create_record(data={'foo': 'bar'}, permissions={'read': ['account:alexis']}) etag = client.get_records_timestamp() assert str(etag) == str(record["data"]["last_modified"])
def test_records_list_retrieval(self): client = Client(server_url=self.server_url, auth=self.auth, bucket='mozilla', collection='payments') client.create_bucket() client.create_collection() client.create_record(data={'foo': 'bar'}, permissions={'read': ['alexis']}) records = client.get_records() assert len(records) == 1
def test_record_creation_and_retrieval(self): client = Client(server_url=self.server_url, auth=self.auth, bucket='mozilla', collection='payments') client.create_bucket() client.create_collection() created = client.create_record(data={'foo': 'bar'}, permissions={'read': ['alexis']}) record = client.get_record(created['data']['id']) assert 'alexis' in record['permissions']['read']
def test_updating_data_on_a_collection(self): client = Client(server_url=self.server_url, auth=self.auth, bucket='mozilla', collection='payments') client.create_bucket() client.create_collection() client.patch_collection(data={'secret': 'psssssst!'}) collection = client.get_collection() assert collection['data']['secret'] == 'psssssst!'
class CollectionLoggingTest(unittest.TestCase): def setUp(self): self.session = mock.MagicMock() self.client = Client(session=self.session) mock_response(self.session) def test_create_collection_logs_info_message(self): with mock.patch('kinto_http.logger') as mocked_logger: self.client.create_collection(id='mozilla', bucket="buck", data={'foo': 'bar'}, permissions={'write': [ 'blah', ]}) mocked_logger.info.assert_called_with( "Create collection 'mozilla' in bucket 'buck'") def test_update_collection_logs_info_message(self): with mock.patch('kinto_http.logger') as mocked_logger: self.client.update_collection( data={'foo': 'bar'}, id='mozilla', bucket='buck', permissions={'write': [ 'blahblah', ]}) mocked_logger.info.assert_called_with( "Update collection 'mozilla' in bucket 'buck'") def test_patch_collection_logs_info_message(self): with mock.patch('kinto_http.logger') as mocked_logger: self.client.patch_collection(data={'foo': 'bar'}, id='mozilla', bucket='buck', permissions={'write': [ 'blahblah', ]}) mocked_logger.info.assert_called_with( "Patch collection 'mozilla' in bucket 'buck'") def test_get_collection_logs_info_message(self): with mock.patch('kinto_http.logger') as mocked_logger: self.client.get_collection(id='mozilla', bucket='buck') mocked_logger.info.assert_called_with( "Get collection 'mozilla' in bucket 'buck'") def test_delete_collection_logs_info_message(self): with mock.patch('kinto_http.logger') as mocked_logger: self.client.delete_collection(id='mozilla', bucket="buck") mocked_logger.info.assert_called_with( "Delete collection 'mozilla' in bucket 'buck'") def test_delete_collections_logs_info_message(self): with mock.patch('kinto_http.logger') as mocked_logger: self.client.delete_collections(bucket="buck") mocked_logger.info.assert_called_with( "Delete collections in bucket 'buck'")
def test_record_creation_and_retrieval(self): client = Client(server_url=self.server_url, auth=self.auth, bucket='mozilla', collection='payments') client.create_bucket() client.create_collection() created = client.create_record(data={'foo': 'bar'}, permissions={'read': ['account:alexis']}) record = client.get_record(id=created['data']['id']) assert 'account:alexis' in record['permissions']['read']
def test_records_timestamp_retrieval(self): client = Client(server_url=self.server_url, auth=self.auth, bucket='mozilla', collection='payments') client.create_bucket() client.create_collection() record = client.create_record(data={'foo': 'bar'}, permissions={'read': ['alexis']}) etag = client.get_records_timestamp() assert str(etag) == str(record["data"]["last_modified"])
def test_one_record_deletion(self): client = Client(server_url=self.server_url, auth=self.auth, bucket='mozilla', collection='payments') client.create_bucket() client.create_collection() record = client.create_record(data={'foo': 'bar'}) deleted = client.delete_record(id=record['data']['id']) assert deleted['deleted'] is True assert len(client.get_records()) == 0
def test_single_record_can_overwrite(self): client = Client(server_url=self.server_url, auth=self.auth, bucket='mozilla', collection='payments') client.create_bucket() client.create_collection() created = client.create_record(data={'foo': 'bar'}, permissions={'read': ['alexis']}) client.create_record(data={'id': created['data']['id'], 'bar': 'baz'}, safe=False)
def test_record_deletion_if_exists(self): client = Client(server_url=self.server_url, auth=self.auth, bucket='mozilla', collection='payments') client.create_bucket() client.create_collection() record = client.create_record(data={'foo': 'bar'}) deleted = client.delete_record(id=record['data']['id']) deleted_if_exists = client.delete_record(id=record['data']['id'], if_exists=True) assert deleted['deleted'] is True assert deleted_if_exists is None
def test_multiple_record_deletion(self): client = Client(server_url=self.server_url, auth=self.auth, bucket="mozilla", collection="payments") client.create_bucket() client.create_collection() client.create_record(data={"foo": "bar"}) client.delete_records() assert len(client.get_records()) == 0
def test_record_deletion_if_exists(self): client = Client(server_url=self.server_url, auth=self.auth, bucket='mozilla', collection='payments') client.create_bucket() client.create_collection() record = client.create_record({'foo': 'bar'}) deleted = client.delete_record(record['data']['id']) deleted_if_exists = client.delete_record(record['data']['id'], if_exists=True) assert deleted['deleted'] is True assert deleted_if_exists is None
def test_single_record_can_overwrite(self): client = Client(server_url=self.server_url, auth=self.auth, bucket='mozilla', collection='payments') client.create_bucket() client.create_collection() created = client.create_record(data={'foo': 'bar'}, permissions={'read': ['account:alexis']}) client.create_record(data={'id': created['data']['id'], 'bar': 'baz'}, safe=False)
def test_single_record_doesnt_overwrite(self): client = Client(server_url=self.server_url, auth=self.auth, bucket='mozilla', collection='payments') client.create_bucket() client.create_collection() created = client.create_record(data={'foo': 'bar'}, permissions={'read': ['alexis']}) with self.assertRaises(KintoException): # Create a second record with the ID of the first one. client.create_record(data={'id': created['data']['id'], 'bar': 'baz'})
def test_records_paginated_list_retrieval(self): client = Client(server_url=self.server_url, auth=self.auth, bucket='mozilla', collection='payments') client.create_bucket() client.create_collection() for i in range(10): client.create_record(data={'foo': 'bar'}, permissions={'read': ['account:alexis']}) # Kinto is running with kinto.paginate_by = 5 records = client.get_records() assert len(records) == 10
def test_records_paginated_list_retrieval(self): client = Client(server_url=self.server_url, auth=self.auth, bucket='mozilla', collection='payments') client.create_bucket() client.create_collection() for i in range(10): client.create_record(data={'foo': 'bar'}, permissions={'read': ['alexis']}) # Kinto is running with kinto.paginate_by = 5 records = client.get_records() assert len(records) == 10
def test_single_record_doesnt_overwrite(self): client = Client(server_url=self.server_url, auth=self.auth, bucket='mozilla', collection='payments') client.create_bucket() client.create_collection() created = client.create_record(data={'foo': 'bar'}, permissions={'read': ['account:alexis']}) with self.assertRaises(KintoException): # Create a second record with the ID of the first one. client.create_record(data={'id': created['data']['id'], 'bar': 'baz'})
def test_records_timestamp_retrieval(self): client = Client(server_url=self.server_url, auth=self.auth, bucket="mozilla", collection="payments") client.create_bucket() client.create_collection() record = client.create_record(data={"foo": "bar"}, permissions={"read": ["account:alexis"]}) etag = client.get_records_timestamp() assert str(etag) == str(record["data"]["last_modified"])
def test_record_creation_and_retrieval(self): client = Client(server_url=self.server_url, auth=self.auth, bucket="mozilla", collection="payments") client.create_bucket() client.create_collection() created = client.create_record( data={"foo": "bar"}, permissions={"read": ["account:alexis"]}) record = client.get_record(id=created["data"]["id"]) assert "account:alexis" in record["permissions"]["read"]
def test_records_list_retrieval(self): client = Client(server_url=self.server_url, auth=self.auth, bucket="mozilla", collection="payments") client.create_bucket() client.create_collection() client.create_record(data={"foo": "bar"}, permissions={"read": ["account:alexis"]}) records = client.get_records() assert len(records) == 1
def test_one_record_deletion(self): client = Client(server_url=self.server_url, auth=self.auth, bucket="mozilla", collection="payments") client.create_bucket() client.create_collection() record = client.create_record(data={"foo": "bar"}) deleted = client.delete_record(id=record["data"]["id"]) assert deleted["deleted"] is True assert len(client.get_records()) == 0
def test_updating_data_on_a_collection(self): client = Client(server_url=self.server_url, auth=self.auth, bucket="mozilla", collection="payments") client.create_bucket() client.create_collection() client.patch_collection(data={"secret": "psssssst!"}) collection = client.get_collection() assert collection["data"]["secret"] == "psssssst!"
def test_single_record_creation_if_not_exists(self): client = Client(server_url=self.server_url, auth=self.auth, bucket="mozilla", collection="payments") client.create_bucket() client.create_collection() created = client.create_record(data={"foo": "bar"}) client.create_record(data={ "id": created["data"]["id"], "bar": "baz" }, if_not_exists=True)
def test_records_paginated_list_retrieval(self): client = Client(server_url=self.server_url, auth=self.auth, bucket="mozilla", collection="payments") client.create_bucket() client.create_collection() for i in range(10): client.create_record(data={"foo": "bar"}, permissions={"read": ["account:alexis"]}) # Kinto is running with kinto.paginate_by = 5 records = client.get_records() assert len(records) == 10
def test_record_deletion_if_exists(self): client = Client(server_url=self.server_url, auth=self.auth, bucket="mozilla", collection="payments") client.create_bucket() client.create_collection() record = client.create_record(data={"foo": "bar"}) deleted = client.delete_record(id=record["data"]["id"]) deleted_if_exists = client.delete_record(id=record["data"]["id"], if_exists=True) assert deleted["deleted"] is True assert deleted_if_exists is None
def test_records_generator_retrieval(self): client = Client(server_url=self.server_url, auth=self.auth, bucket="mozilla", collection="payments") client.create_bucket() client.create_collection() for i in range(10): client.create_record(data={"foo": "bar"}, permissions={"read": ["account:alexis"]}) pages = list(client.get_paginated_records()) assert len(pages) == 2
def test_single_record_can_overwrite(self): client = Client(server_url=self.server_url, auth=self.auth, bucket="mozilla", collection="payments") client.create_bucket() client.create_collection() created = client.create_record( data={"foo": "bar"}, permissions={"read": ["account:alexis"]}) client.create_record(data={ "id": created["data"]["id"], "bar": "baz" }, safe=False)
def test_single_record_doesnt_overwrite(self): client = Client(server_url=self.server_url, auth=self.auth, bucket="mozilla", collection="payments") client.create_bucket() client.create_collection() created = client.create_record( data={"foo": "bar"}, permissions={"read": ["account:alexis"]}) with self.assertRaises(KintoException): # Create a second record with the ID of the first one. client.create_record(data={ "id": created["data"]["id"], "bar": "baz" })
def test_single_record_save(self): client = Client(server_url=self.server_url, auth=self.auth, bucket='mozilla', collection='payments') client.create_bucket() client.create_collection() created = client.create_record(data={'foo': 'bar'}, permissions={'read': ['alexis']}) created['data']['bar'] = 'baz' # XXX enhance this in order to have to pass only one argument, created. client.update_record(id=created['data']['id'], data=created['data']) retrieved = client.get_record(created['data']['id']) assert 'alexis' in retrieved['permissions']['read'] assert retrieved['data']['foo'] == u'bar' assert retrieved['data']['bar'] == u'baz' assert created['data']['id'] == retrieved['data']['id']
def test_single_record_save(self): client = Client(server_url=self.server_url, auth=self.auth, bucket='mozilla', collection='payments') client.create_bucket() client.create_collection() created = client.create_record(data={'foo': 'bar'}, permissions={'read': ['account:alexis']}) created['data']['bar'] = 'baz' # XXX enhance this in order to have to pass only one argument, created. client.update_record(id=created['data']['id'], data=created['data']) retrieved = client.get_record(id=created['data']['id']) assert 'account:alexis' in retrieved['permissions']['read'] assert retrieved['data']['foo'] == u'bar' assert retrieved['data']['bar'] == u'baz' assert created['data']['id'] == retrieved['data']['id']
class CollectionLoggingTest(unittest.TestCase): def setUp(self): self.session = mock.MagicMock() self.client = Client(session=self.session) mock_response(self.session) def test_create_collection_logs_info_message(self): with mock.patch('kinto_http.logger') as mocked_logger: self.client.create_collection( 'mozilla', bucket="buck", data={'foo': 'bar'}, permissions={'write': ['blah', ]}) mocked_logger.info.assert_called_with( "Create collection 'mozilla' in bucket 'buck'") def test_update_collection_logs_info_message(self): with mock.patch('kinto_http.logger') as mocked_logger: self.client.update_collection( data={'foo': 'bar'}, collection='mozilla', bucket='buck', permissions={'write': ['blahblah', ]}) mocked_logger.info.assert_called_with( "Update collection 'mozilla' in bucket 'buck'") def test_get_collection_logs_info_message(self): with mock.patch('kinto_http.logger') as mocked_logger: self.client.get_collection( 'mozilla', bucket='buck') mocked_logger.info.assert_called_with( "Get collection 'mozilla' in bucket 'buck'") def test_delete_collection_logs_info_message(self): with mock.patch('kinto_http.logger') as mocked_logger: self.client.delete_collection( 'mozilla', bucket="buck") mocked_logger.info.assert_called_with( "Delete collection 'mozilla' in bucket 'buck'") def test_delete_collections_logs_info_message(self): with mock.patch('kinto_http.logger') as mocked_logger: self.client.delete_collections( bucket="buck") mocked_logger.info.assert_called_with( "Delete collections in bucket 'buck'")
def test_single_record_save(self): client = Client(server_url=self.server_url, auth=self.auth, bucket="mozilla", collection="payments") client.create_bucket() client.create_collection() created = client.create_record( data={"foo": "bar"}, permissions={"read": ["account:alexis"]}) created["data"]["bar"] = "baz" # XXX enhance this in order to have to pass only one argument, created. client.update_record(id=created["data"]["id"], data=created["data"]) retrieved = client.get_record(id=created["data"]["id"]) assert "account:alexis" in retrieved["permissions"]["read"] assert retrieved["data"]["foo"] == u"bar" assert retrieved["data"]["bar"] == u"baz" assert created["data"]["id"] == retrieved["data"]["id"]
# print(item) #record = client.delete_record(id='8c3b1c8c-ed5b-46d9-a9f0-681f3debb68c',collection=collection, bucket=bucket) # F10 vim本地运行python代码,或者分屏,在jupyter里做吧 # http://localhost:8888/v1/buckets/default/collections/tasks/records # http://localhost:8888/v1/buckets/paperweekly/collections/forum2wechat_todo/records 有记录 # kinto-admin本地有问题 if __name__ == '__main__': # 只运行一次 client.create_bucket(bucket) client.create_collection(collection, bucket=bucket) # 创建记录 数据单元 #client.create_record(data={'status': 'todo', 'title': 'Todo #2'}, # collection=collection, bucket=bucket) # 获取 ''' for i in range(3): #push_thread('thread_id2','username','title','content') get_threads() time.sleep(2) push_thread('thread_id','username','title','content') ''' #records = client.get_records(collection=collection, bucket=bucket) #client.delete_records(collection=collection,bucket=bucket) #获取即焚
from kinto_http import Client # Login credentials = ('paco', '123456') client = Client(server_url="http://localhost:8888/v1", auth=credentials) # Create bucket client.create_collection(id='Tasks', bucket='default') client.create_collection(id='Test', bucket='default') # Add records client.create_record(data={ 'title': 'Create Documentation', 'description': 'Create docs using Markdown', 'status': 'Done' }, collection='Test', bucket='default') client.create_record(data={ 'title': 'Create Dockerfile', 'description': 'Create Parse Dockerfile', 'status': 'Done' }, collection='Test', bucket='default') client.create_record(data={ 'title': 'Update Computer', 'description': 'Update Solus Distro', 'status': 'Doing'
class RecordLoggingTest(unittest.TestCase): def setUp(self): self.session = mock.MagicMock() self.client = Client(session=self.session) mock_response(self.session) def test_create_record_logs_info_message(self): with mock.patch('kinto_http.logger') as mocked_logger: self.client.create_bucket(id='buck') self.client.create_collection(id='mozilla', bucket='buck') self.client.create_record( id='fake-record', data={'foo': 'bar'}, permissions={'write': ['blah', ]}, bucket='buck', collection='mozilla') mocked_logger.info.assert_called_with( "Create record with id 'fake-record' in collection 'mozilla' in bucket 'buck'") def test_update_record_logs_info_message(self): with mock.patch('kinto_http.logger') as mocked_logger: self.client.create_bucket(id='buck') self.client.create_collection(bucket='buck', id='mozilla') self.client.update_record( id='fake-record', data={'ss': 'aa'}, bucket='buck', collection='mozilla') mocked_logger.info.assert_called_with( "Update record with id 'fake-record' in collection 'mozilla' in bucket 'buck'") def test_get_record_logs_info_message(self): with mock.patch('kinto_http.logger') as mocked_logger: self.client.create_bucket(id='buck') self.client.create_collection(id='mozilla', bucket='buck') self.client.get_record( id='fake-record', bucket='buck', collection='mozilla') mocked_logger.info.assert_called_with( "Get record with id 'fake-record' from collection 'mozilla' in bucket 'buck'") def test_delete_record_logs_info_message(self): with mock.patch('kinto_http.logger') as mocked_logger: self.client.create_bucket(id='buck') self.client.create_collection(id='mozilla', bucket='buck') self.client.delete_record( id='fake-record', bucket='buck', collection='mozilla') mocked_logger.info.assert_called_with( "Delete record with id 'fake-record' from collection 'mozilla' in bucket 'buck'") def test_delete_records_logs_info_message(self): with mock.patch('kinto_http.logger') as mocked_logger: self.client.create_bucket(id='buck') self.client.create_collection(id='mozilla', bucket='buck') self.client.delete_records( bucket='buck', collection='mozilla') mocked_logger.info.assert_called_with( "Delete records from collection 'mozilla' in bucket 'buck'")
def main(): args = _get_args() client = Client(server_url=args.server, auth=tuple(args.auth.split(':')), bucket=args.source_bucket, collection=args.source_col) if args.editor_auth is None: args.editor_auth = args.auth if args.reviewer_auth is None: args.reviewer_auth = args.auth editor_client = Client(server_url=args.server, auth=tuple(args.editor_auth.split(':')), bucket=args.source_bucket, collection=args.source_col) reviewer_client = Client(server_url=args.server, auth=tuple(args.reviewer_auth.split(':')), bucket=args.source_bucket, collection=args.source_col) # 0. initialize source bucket/collection (if necessary) server_info = client.server_info() editor_id = editor_client.server_info()['user']['id'] reviewer_id = reviewer_client.server_info()['user']['id'] print('Server: {0}'.format(args.server)) print('Author: {user[id]}'.format(**server_info)) print('Editor: {0}'.format(editor_id)) print('Reviewer: {0}'.format(reviewer_id)) # 0. check that this collection is well configured. signer_capabilities = server_info['capabilities']['signer'] resources = [r for r in signer_capabilities['resources'] if (args.source_bucket, args.source_col) == (r['source']['bucket'], r['source']['collection']) or (args.source_bucket, None) == (r['source']['bucket'], r['source']['collection'])] assert len(resources) > 0, 'Specified source not configured to be signed' resource = resources[0] if 'preview' in resource: print('Signoff: {source[bucket]}/{source[collection]} => {preview[bucket]}/{preview[collection]} => {destination[bucket]}/{destination[collection]}'.format(**resource)) else: print('Signoff: {source[bucket]}/{source[collection]} => {destination[bucket]}/{destination[collection]}'.format(**resource)) print('_' * 80) bucket = client.create_bucket(if_not_exists=True) client.create_collection(permissions={'write': [editor_id, reviewer_id] + bucket['permissions']['write']}, if_not_exists=True) editors_group = resource.get('editors_group') or signer_capabilities['editors_group'] editors_group = editors_group.format(collection_id=args.source_col) client.patch_group(id=editors_group, data={'members': [editor_id]}) reviewers_group = resource.get('reviewers_group') or signer_capabilities['reviewers_group'] reviewers_group = reviewers_group.format(collection_id=args.source_col) client.patch_group(id=reviewers_group, data={'members': [reviewer_id]}) if args.reset: client.delete_records() existing = 0 else: existing_records = client.get_records() existing = len(existing_records) dest_col = resource['destination'].get('collection') or args.source_col dest_client = Client(server_url=args.server, bucket=resource['destination']['bucket'], collection=dest_col) preview_client = None if 'preview' in resource: preview_bucket = resource['preview']['bucket'] preview_collection = resource['preview'].get('collection') or args.source_col preview_client = Client(server_url=args.server, bucket=preview_bucket, collection=preview_collection) # 1. upload data print('Author uploads 20 random records') records = upload_records(client, 20) # 2. ask for a signature # 2.1 ask for review (noop on old versions) print('Editor asks for review') data = {"status": "to-review"} editor_client.patch_collection(data=data) # 2.2 check the preview collection (if enabled) if preview_client: print('Check preview collection') preview_records = preview_client.get_records() expected = existing + 20 assert len(preview_records) == expected, '%s != %s records' % (len(preview_records), expected) metadata = preview_client.get_collection()['data'] preview_signature = metadata.get('signature') assert preview_signature, 'Preview collection not signed' preview_timestamp = preview_client.get_records_timestamp() # 2.3 approve the review print('Reviewer approves and triggers signature') data = {"status": "to-sign"} reviewer_client.patch_collection(data=data) # 3. upload more data print('Author creates 20 others records') upload_records(client, 20) print('Editor updates 5 random records') for toupdate in random.sample(records, 5): editor_client.patch_record(data=dict(newkey=_rand(10), **toupdate)) print('Author deletes 5 random records') for todelete in random.sample(records, 5): client.delete_record(id=todelete['id']) expected = existing + 20 + 20 - 5 # 4. ask again for a signature # 2.1 ask for review (noop on old versions) print('Editor asks for review') data = {"status": "to-review"} editor_client.patch_collection(data=data) # 2.2 check the preview collection (if enabled) if preview_client: print('Check preview collection') preview_records = preview_client.get_records() assert len(preview_records) == expected, '%s != %s records' % (len(preview_records), expected) # Diff size is 20 + 5 if updated records are also all deleted, # or 30 if deletions and updates apply to different records. diff_since_last = preview_client.get_records(_since=preview_timestamp) assert 25 <= len(diff_since_last) <= 30, 'Changes since last signature are not consistent' metadata = preview_client.get_collection()['data'] assert preview_signature != metadata['signature'], 'Preview collection not updated' # 2.3 approve the review print('Reviewer approves and triggers signature') data = {"status": "to-sign"} reviewer_client.patch_collection(data=data) # 5. wait for the result # 6. obtain the destination records and serialize canonically. records = list(dest_client.get_records()) assert len(records) == expected, '%s != %s records' % (len(records), expected) timestamp = dest_client.get_records_timestamp() serialized = canonical_json(records, timestamp) print('Hash is %r' % compute_hash(serialized)) # 7. get back the signed hash signature = dest_client.get_collection()['data']['signature'] with open('pub', 'w') as f: f.write(signature['public_key']) # 8. verify the signature matches the hash signer = ECDSASigner(public_key='pub') try: signer.verify(serialized, signature) print('Signature OK') except Exception: print('Signature KO') raise
class AppWindow(QtWidgets.QMainWindow,Ui_MainWindow): def __init__(self, parent = None): QtWidgets.QMainWindow.__init__(self, parent) self.setAttribute(QtCore.Qt.WA_DeleteOnClose) self.setupUi(self) ###################################################################################### ###################################################################################### self.settings = Settings() self.initRep() self.initKintoClient() self.syncRecipes() self.dlgEditG = Dialog(self) self.dlgEditH = DialogH(self) self.dlgEditD = DialogD(self) self.dlgEditY = DialogL(self) self.dlgPref = DialogPref(self) self.dlgStep = DialogStep(self) self.dlgMash = DialogMash(self) self.base = ImportBase() self.mashProfileExport = ExportMash() # self.base.importBeerXML() self.s=0 self.recipe = None #Les connexions self.actionEnregistrer.triggered.connect(self.enregistrer) self.actionQuitter.triggered.connect(app.quit) # self.connect(self.actionQuitter, QtCore.SIGNAL("triggered()"), app, QtCore.SLOT("quit()")) self.actionShowJournal.triggered.connect(self.showJournal) self.actionEditGrains.triggered.connect(self.editGrains) self.actionEditHoublons.triggered.connect(self.editHoublons) self.actionEditDivers.triggered.connect(self.editDivers) self.actionEditLevures.triggered.connect(self.editLevures) self.actionRestaurerIngredients.triggered.connect(self.restoreDataBase) self.actionImportIng.triggered.connect(self.importIng) self.actionManageProfiles.triggered.connect(self.seeMash) self.actionAbout.triggered.connect(self.about) self.actionAllTools.triggered.connect(self.showTools) self.actionPreferences.triggered.connect(self.dialogPreferences) ####################################################################################################### # Profil de brassage ######################################################################################################### self.listWidgetSteps.itemSelectionChanged.connect (self.stepDetails) self.listWidgetMashProfiles.itemSelectionChanged.connect (self.mashClicked) self.buttonBoxMashDetails.rejected.connect(self.mashRejected) # self.comboBoxStepType.addItems(["Infusion", "Température", "Décoction"]) self.pushButtonStepEdit.clicked.connect(self.stepEdit) self.dlgStep.stepChanged.connect(self.stepReload) self.pushButtonStepRemove.clicked.connect(self.removeStep) self.pushButtonNewStep.clicked.connect(self.addStep) self.pushButtonMashEdit.clicked.connect(self.mashEdit) self.dlgMash.mashChanged.connect(self.mashReload) self.pushButtonNewProfile.clicked.connect(self.addMash) self.pushButtonRemoveProfile.clicked.connect(self.removeMash) self.pushButtonSaveProfile.clicked.connect(self.saveProfile) #La bibliotheque ################################################################################################################### ################################################################################################################### # self.listdir(recettes_dir) self.showLib() ################################################################################################### ######## gestion des arguments au lancement du programme ######################################### argumentsList=QtWidgets.QApplication.arguments() if len(argumentsList) > 1 : logger.debug("la liste d'arguments: %s",argumentsList) logger.debug("le chemin: %s",argumentsList[1]) # for part in argumentsList : # recipePath=recipePath + " " + part try: recipePath= argumentsList[1] for part in argumentsList[2:] : recipePath= recipePath +" " + part self.openRecipeFile(recipePath) except : pass else: pass ######################################################################################################################## #################################################################################################################### # le signal émit à la fermeture de la fenêtre de préférences self.dlgPref.prefAccepted.connect(self.prefReload) ########################################################### ############### Journal ############################## ###################################################### def loadJournal(self): self.journal=Journal() self.journal.loadJournal() # self.actionEditJournal.setEnabled(True) @QtCore.pyqtSlot() def showJournal(self,entry=" '' ") : self.stackedWidget.setCurrentIndex(0) self.loadJournal() pyDir = os.path.abspath(os.path.dirname(__file__)) baseUrl = QtCore.QUrl.fromLocalFile(os.path.join(pyDir, "static/")) self.webViewBiblio.setHtml(self.journal.export("html",entry), baseUrl) self.webViewBiblio.page().mainFrame().addToJavaScriptWindowObject("main", self) # self.webViewBiblio.page().settings().setAttribute(QtWebKit.QWebSettings.DeveloperExtrasEnabled, True) # self.webInspector = QtWebKit.QWebInspector(self) # self.webInspector.setPage(self.webViewBiblio.page()) # self.webInspector.setVisible(True) # self.verticalLayout_13.addWidget(self.webInspector) @QtCore.pyqtSlot(str, str) def addToJournal(self,event, recipeName) : self.loadJournal() entry = '''{recipe:%s,date:%s,event:%s,editing:'True'} ''' %( "'" + recipeName + "'", "'" + str(int(time.time())) + "'" , "'" + self.journal.eventsLabels[event] + "'") self.showJournal(entry) @QtCore.pyqtSlot(str) def dumpJournal(self,journalJson) : journalJson= '{"name":"journal","items": %s }' %journalJson d=json.loads(journalJson) with open(journal_file, mode="w", encoding="utf-8") as f : json.dump(d,f,indent=2) ############## Bibliothèque ############################## ########################################################## @QtCore.pyqtSlot() def showLib(self) : # data = json.dumps(self.recipesSummary) # data = data.replace("'","'") self.stackedWidget.setCurrentIndex(0) self.brewdayLock = 0 self.webSettings = self.webViewBiblio.settings() self.webSettings.setAttribute(QtWebKit.QWebSettings.LocalContentCanAccessRemoteUrls, True) pyDir = os.path.abspath(os.path.dirname(__file__)) baseUrl = QtCore.QUrl.fromLocalFile(os.path.join(pyDir, "static/html/")) self.webViewBiblio.setHtml(LibExporterRepository['html'](), baseUrl) self.webViewBiblio.page().mainFrame().addToJavaScriptWindowObject("main", self) self.webViewBiblio.page().settings().setAttribute(QtWebKit.QWebSettings.DeveloperExtrasEnabled, True) self.webViewBiblio.page().action(QtWebKitWidgets.QWebPage.Reload).setVisible(False) @QtCore.pyqtSlot(str) def deleteLib(self,path) : confirmation = QtWidgets.QMessageBox.question(self, self.tr("Supprimer"), self.tr("La recette sera définitivement supprimée <br/> Continuer ?"), QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No) if (confirmation == QtWidgets.QMessageBox.Yes): os.remove(path) self.listdir(recettes_dir) self.showLib() else : self.showLib() @QtCore.pyqtSlot() def backWebViewBiblio(self) : self.stackedWidget.setCurrentIndex(0) @QtCore.pyqtSlot(str, str) def saveRecipe(self, recipe, path) : logger.debug(path) recipeFile = QtCore.QFile(path) if recipeFile.open(QtCore.QIODevice.WriteOnly): try: stream = QtCore.QTextStream(recipeFile) stream.setCodec("UTF-8") stream << recipe finally: recipeFile.close() else: # TODO : Prévenir l'utilisateur en cas d'échec de l'enregistrement pass @QtCore.pyqtSlot(result=str) def createPath(self, file_id=None) : if file_id is None: file_id = str(int(time.time()*10)) path = recettes_dir + "/" + file_id + ".xml" logger.debug(path) return path @QtCore.pyqtSlot() def resetLock(self): self.brewdayLock = 0; ############# Mode Brassage ################################ ############################################################ @QtCore.pyqtSlot(str) def showBrewdayMode(self, data): if self.brewdayLock == 0 : self.stackedWidget.setCurrentIndex(1) self.brewdayLock = 1 data = data.replace("'","'") pyDir = os.path.abspath(os.path.dirname(__file__)) baseUrl = QtCore.QUrl.fromLocalFile(os.path.join(pyDir, "static/")) self.webViewBrewday.setHtml(BrewdayExporterRepository['html'](data), baseUrl) self.webViewBrewday.page().mainFrame().addToJavaScriptWindowObject("main", self) self.webViewBrewday.page().settings().setAttribute(QtWebKit.QWebSettings.DeveloperExtrasEnabled, True) self.webViewBrewday.page().action(QtWebKitWidgets.QWebPage.Reload).setVisible(False) else : self.stackedWidget.setCurrentIndex(1) ###### Outils ############################################ ########################################################## @QtCore.pyqtSlot() def showTools(self): self.stackedWidget.setCurrentIndex(0) pyDir = os.path.abspath(os.path.dirname(__file__)) baseUrl = QtCore.QUrl.fromLocalFile(os.path.join(pyDir, "static/")) self.webViewBiblio.setHtml(ToolExporterRepository["html"](), baseUrl) self.webViewBiblio.page().mainFrame().addToJavaScriptWindowObject("main", self) # self.webViewBiblio.page().settings().setAttribute(QtWebKit.QWebSettings.DeveloperExtrasEnabled, True) # self.webInspector = QtWebKit.QWebInspector(self) # self.webInspector.setPage(self.webViewBiblio.page()) # self.webInspector.setVisible(True) # self.verticalLayout_13.addWidget(self.webInspector) @QtCore.pyqtSlot(result=str) def dataRecipes(self) : # f = open(recipeData_file, 'w') # f.write(self.recipesSummary) self.listdir(recettes_dir) return self.recipesSummary @QtCore.pyqtSlot(result=str) def dataProfiles(self) : return self.mashProfileExport.exportJson(ImportBase().listeMashes) @QtCore.pyqtSlot(result=str) def dataIngredients(self) : return ImportBase().exportjson() @QtCore.pyqtSlot(result=str) def dataPref(self) : dic = {} dic["boilOffRate"] = settings.conf.value("BoilOffRate") dic["coolingLossRate"] = settings.conf.value("CoolingLoss") dic["grainTemp"] = settings.conf.value("GrainTemp") dic["fudgeFactor"] = settings.conf.value("FudgeFactor") dic["grainRetention"] = settings.conf.value("GrainRetention") dic = json.dumps(dic) return dic #Une fonction qui gère l'aperçu des couleurs. #Contient un tupple avec plusieurs références de couleurs, classées par rang selon la valeur SRM. ################################################################################################# # def colorPreview (self) : # self.colorTuppleSrm = ('FFE699', 'FFD878', 'FFCA5A', 'FFBF42', 'FBB123', 'F8A600', 'F39C00', 'EA8F00', 'E58500', 'DE7C00', 'D77200', 'CF6900', 'CB6200', 'C35900','BB5100', 'B54C00', 'B04500', 'A63E00', 'A13700', '9B3200', '952D00', '8E2900', '882300', '821E00', '7B1A00', '771900', '701400', '6A0E00', '660D00','5E0B00','5A0A02','600903', '520907', '4C0505', '470606', '440607', '3F0708', '3B0607', '3A070B', '36080A') # colorRef= round(self.recipe.compute_EBC()/1.97) # if colorRef >= 30 : # color = "#" + self.colorTuppleSrm[30] # elif colorRef <= 1 : # color = "#" + self.colorTuppleSrm[0] # else : # color = "#" + self.colorTuppleSrm[colorRef-1] # self.widgetColor.setStyleSheet("background-color :" + color) def liste_fichiers_recettes(self, rootdir): for root, subFolders, files in os.walk(rootdir): for file2 in files: yield (file2, os.path.join(root,file2)) def listdir(self, rootdir) : summaries=[] for filename, recipe in self.liste_fichiers_recettes(rootdir): try : summaries.append(self.jsonRecipeLib(recipe)) except : logger.debug("le fichier %s n'est pas une recette" %(recipe)) self.recipesSummary = "[" + ",".join(summaries) + "]" logger.debug("%s recettes détectées" %(len(summaries))) def jsonRecipeLib(self,recipe) : self.s = recipe self.recipe = Recipe.parse(recipe) data = self.recipe.export("json") data = data[1:-1] return data def initRep(self) : home = QtCore.QDir(home_dir) config = QtCore.QDir(config_dir) logger.debug (config) if not config.exists() : home.mkpath (config_dir) else : pass database = QtCore.QFile(database_file) if not database.exists() : database.copy(database_root, database_file) else : pass recettes = QtCore.QFile(recettes_dir) if not recettes.exists() : try : shutil.copytree(samples_dir, samples_target) except : home.mkpath(recettes_dir) mash = QtCore.QFile(mash_file) if not mash.exists() : mash.copy(mash_root, mash_file) else : pass journal = QtCore.QFile(journal_file) if not journal.exists() : journal.copy(journal_root, journal_file) else : pass # on configure des valeurs par défaut if not settings.conf.contains("BoilOffRate") : settings.conf.setValue("BoilOffRate", 10) if not settings.conf.contains("CoolingLoss") : settings.conf.setValue("CoolingLoss", 5) if not settings.conf.contains("GrainTemp") : settings.conf.setValue("GrainTemp", 20) if not settings.conf.contains("FudgeFactor") : settings.conf.setValue("FudgeFactor", 1.7) if not settings.conf.contains("GrainRetention") : settings.conf.setValue("GrainRetention", 1) if not settings.conf.contains("Menus") : settings.conf.setValue("Menus", "button") def prefReload(self) : if platform == 'win32': recettes_dir = settings.conf.value("pathWin32") else : recettes_dir = settings.conf.value("pathUnix") self.initRep() self.initKintoClient() self.listdir(recettes_dir) self.showLib() def initKintoClient(self): self.kinto_client = None kinto_url = settings.conf.value("KintoServerUrl") if kinto_url is not None and kinto_url != "": kinto_bucket = settings.conf.value("KintoDefaultBucket") kinto_credentials=(settings.conf.value("KintoBasicUserCred"), settings.conf.value("KintoBasicPasswordCred")) logger.debug(kinto_credentials) if kinto_bucket is None or kinto_bucket == "": kinto_bucket = "joliebulle" logger.debug("using default bucket 'joliebulle'") try: tmp_client = Client(server_url=kinto_url, auth = kinto_credentials) tmp_client.create_bucket(id=kinto_bucket, if_not_exists=True) self.kinto_client = Client(server_url=kinto_url, bucket=kinto_bucket, auth = kinto_credentials) # Création des collections self.kinto_client.create_collection(id='recipes', if_not_exists=True) self.kinto_client.create_collection(id='ingredients', if_not_exists=True) logger.info("Synchronize with kinto server at :" + repr(self.kinto_client)) except Exception as e: logger.warn("Failed to initialize Kinto synchronisation: " + repr(e)) def syncRecipes(self): recipes_collection = 'recipes' if self.kinto_client is None: return # Sync local recipes id_recettes_locales=[] for filename, full_filename in self.liste_fichiers_recettes(recettes_dir): recipe_id = filename.replace('.xml', '') id_recettes_locales.append(recipe_id) try: remote_recipe = self.kinto_client.get_record(id=recipe_id, collection=recipes_collection) logger.debug("recipe " + recipe_id + " already exists on server, update if needed") remote_timestamp = int(remote_recipe['data']['last_modified']/1000) local_timestamp = int(os.path.getmtime(full_filename)) logger.debug(str(remote_timestamp) + " " + str(local_timestamp)) if remote_timestamp < local_timestamp: logger.info("Mise à jour de la recette distante " + recipe_id) # La recette distant doit être mise à jour local_recipe = Recipe.parse(full_filename) data = local_recipe.export("dict") ret = self.kinto_client.update_record(id=recipe_id, collection=recipes_collection, data=data) new_timestamp = ret['data']['last_modified'] #MAJ du mtime du fichier pour marquer la synchronisation os.utime(full_filename, times=(int(new_timestamp/1000), int(new_timestamp/1000))) if remote_timestamp > local_timestamp: # La recette distante doit être mise à jour logger.info("Mise à jour de la recette locale " + recipe_id) new_recipe = Recipe.parse(remote_recipe['data'], "dict") self.doEnregistrerRecette(new_recipe, full_filename) os.utime(full_filename, times=(int(remote_timestamp), int(remote_timestamp))) except KintoException: logger.debug("recipe " + recipe_id + " doesn't exists on server, sending it") new_recipe = Recipe.parse(full_filename) data = new_recipe.export("dict") ret = self.kinto_client.create_record(id=recipe_id, collection=recipes_collection, data=data) new_timestamp = ret['data']['last_modified'] #MAJ du mtime du fichier pour marquer la synchronisation os.utime(full_filename, times=(int(new_timestamp/1000), int(new_timestamp/1000))) recipes = self.kinto_client.get_records(collection='recipes') for recipe in recipes: if recipe['id'] not in id_recettes_locales: #Recette distante non présente localement new_recipe = Recipe.parse(recipe, "dict") fullname = recipe['id'] + ".xml" logger.debug("Création de la recette " + fullname) self.doEnregistrerRecette(new_recipe, os.path.join(recettes_dir, fullname)) os.utime(full_filename, times=(int(remote_timestamp), int(remote_timestamp))) @QtCore.pyqtSlot() def switchToLibrary(self) : self.stackedWidget.setCurrentIndex(0) # self.viewRecipeLib(self.s) def switchToMash(self) : self.stackedWidget.setCurrentIndex(2) def restoreDataBase(self) : home = QtCore.QDir(home_dir) config = QtCore.QDir(config_dir) database = QtCore.QFile(database_file) confirmation = QtWidgets.QMessageBox.question(self, self.tr("Remplacer la base ?"), self.tr("La base des ingrédients actuelle va être effacée et remplacée par la base originale. Toutes vos modifications vont être effacées. Un redémarrage de l'application sera nécessaire.<br> Continuer ?"), QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No) if (confirmation == QtWidgets.QMessageBox.Yes): database.remove(database_file) database.copy(database_root, database_file) else : pass def editGrains(self) : self.dlgEditG.setModal(True) self.dlgEditG.setModel() self.dlgEditG.show() def editHoublons(self) : self.dlgEditH.setModal(True) self.dlgEditH.setModel() self.dlgEditH.show() def editDivers(self) : self.dlgEditD.setModal(True) self.dlgEditD.setModel() self.dlgEditD.show() def editLevures(self) : self.dlgEditY.setModal(True) self.dlgEditY.setModel() self.dlgEditY.show() @QtCore.pyqtSlot(float, float, float, float) def preBoilCheck(self,volPreBoil,preBoilSg,GU,volume) : self.dlgPreBoil = DialogPreBoil(self) self.dlgPreBoil.setData(volPreBoil,preBoilSg,GU,volume) self.dlgPreBoil.setModal(True) self.dlgPreBoil.show() def dialogPreferences (self) : self.dlgPref.setModal(True) self.dlgPref.show() def importBeerXML(self) : fichierBeerXML = self.s try: self.recipe = Recipe.parse(fichierBeerXML) self.currentRecipeMash = self.recipe.mash except : errors = Errors() errors.warningXml() def about(self) : about = DialogAbout(self) about.show() def doEnregistrerRecette(self, recipe, destination): recipeFile = QtCore.QFile(destination) if recipeFile.open(QtCore.QIODevice.WriteOnly): try: stream = QtCore.QTextStream(recipeFile) stream.setCodec("UTF-8") stream << recipe.export("beerxml") finally: recipeFile.close() else: # TODO : Prévenir l'utilisateur en cas d'échec de l'enregistrement pass def enregistrerRecette(self, destination): self.doEnregistrerRecette(self.recipe, destination) self.fileSaved = True def enregistrer (self) : if self.recipe.name != self.lineEditRecette.text() : self.nameChanged = True else : self.nameChanged = False self.recipe.name = self.lineEditRecette.text() self.recipe.style = self.lineEditGenre.text() self.recipe.brewer = self.lineEditBrewer.text() self.recipe.boil = self.spinBoxBoil.value() if not self.s: destination = recettes_dir + "/" + self.recipe.name.replace('/', ' ') + ".xml" if os.path.exists(destination) : errors=Errors() errors.warningExistingPath() self.fileSaved = False else : self.s = destination self.enregistrerRecette(destination) else : self.enregistrerRecette(self.s) def enregistrerSous (self) : self.s = QtGui.QFileDialog.getSaveFileName (self, self.tr("Enregistrer dans un fichier"), recettes_dir + "/" + self.recipe.name.replace('/', ' ') + ".xml", "BeerXML (*.xml)") self.enregistrerRecette(self.s) @QtCore.pyqtSlot(str) def copyBbcode (self, bbcode): app.clipboard().setText(bbcode) def importIng(self): s = QtWidgets.QFileDialog.getOpenFileName(self, self.tr("Ouvrir un fichier"), home_dir, ) if not s : pass else : self.importIngList = ImportIng() self.importIngList.parseFile(s) def mashComboChanged (self) : #on remet le verrou à 0, il va falloir recalculer en repassant en brewday mode self.brewdayLock = 0 try : i =self.comboBoxMashProfiles.currentIndex() self.currentMash = ImportBase().listeMashes[i] except : self.currentMash = self.currentRecipeMash if i == -1 : self.currentMash = Mash() self.recipe.mash = self.currentMash def seeMash(self) : self.switchToMash() index = self.listWidgetMashProfiles.currentRow() i = self.listWidgetSteps.currentRow() self.listWidgetMashProfiles.clear() self.listWidgetSteps.clear() self.numMash = len(ImportBase().listeMashes) #self.numSteps = self.mashProfilesBase.numSteps self.popMashList() self.pushButtonMashEdit.setEnabled(False) self.pushButtonRemoveProfile.setEnabled(False) self.pushButtonStepRemove.setEnabled(False) self.pushButtonStepEdit.setEnabled(False) self.listWidgetMashProfiles.setCurrentRow(index) self.listWidgetSteps.setCurrentRow(i) def popMashList(self) : self.listWidgetMashProfiles.clear() for mash in ImportBase().listeMashes : self.listWidgetMashProfiles.addItem(mash.name) def mashClicked(self) : self.listWidgetSteps.clear() index = self.listWidgetMashProfiles.currentRow() if index > -1: mash = ImportBase().listeMashes[index] for step in mash.listeSteps : self.listWidgetSteps.addItem(step.name) self.labelStepName.setTextFormat(QtCore.Qt.RichText) self.labelMashName.setText("<b>" + mash.name + "</b>") self.labelMashPh.setText("%.1f" %float(mash.ph)) # self.labelMashGrainTemp.setText("%.1f" %float(self.dicMashDetail['grainTemp'])) # self.labelMashTunTemp.setText("%.1f" %float(self.dicMashDetail['tunTemp'])) try : self.labelMashSpargeTemp.setText("%.1f" %float(mash.spargeTemp)) except : pass try : self.listWidgetSteps.setCurrentRow(0) except : pass # print(self.dicMashDetail) self.pushButtonMashEdit.setEnabled(True) self.pushButtonRemoveProfile.setEnabled(True) def mashDetails(self) : self.dlgMashDetail = DialogMashDetail(self) self.dlgMashDetail.setModal(True) self.dlgMashDetail.show() self.dlgMashDetail.setFields(self.currentMash) self.dlgMashDetail.setAttribute( QtCore.Qt.WA_DeleteOnClose, True ) def stepDetails(self) : index = self.listWidgetMashProfiles.currentRow() if index > -1: selected_mash = ImportBase().listeMashes[index] i = self.listWidgetSteps.currentRow() if i > -1: try: selected_step = selected_mash.listeSteps[i] self.labelStepName.setTextFormat(QtCore.Qt.RichText) self.labelStepName.setText("<b>" + selected_step.name +"</b>") self.labelStepType.setText(selected_step.type) self.labelStepTemp.setText(MashStepView.temp_to_display(selected_step.temp)) self.labelStepTime.setText(MashStepView.time_to_display(selected_step.time)) self.pushButtonStepRemove.setEnabled(True) self.pushButtonStepEdit.setEnabled(True) except: pass def stepEdit(self) : index = self.listWidgetMashProfiles.currentRow() if index > -1: selected_mash = ImportBase().listeMashes[index] i = self.listWidgetSteps.currentRow() if i > -1: selected_step = selected_mash.listeSteps[i] self.dlgStep.show() self.dlgStep.fields (selected_step) def stepReload(self, step) : index = self.listWidgetMashProfiles.currentRow() if index > -1: selected_mash = ImportBase().listeMashes[index] i = self.listWidgetSteps.currentRow() if i > -1: selected_step = selected_mash.listeSteps[i] selected_step.name = step.name selected_step.type = step.type selected_step.temp = step.temp selected_step.time = step.time self.seeMash() self.stepDetails() self.listWidgetMashProfiles.setCurrentRow(index) self.listWidgetSteps.setCurrentRow(i) def removeStep(self) : index = self.listWidgetMashProfiles.currentRow() if index > -1: selected_mash = ImportBase().listeMashes[index] i = self.listWidgetSteps.currentRow() if i > -1: item = self.listWidgetSteps.currentItem() del selected_mash.listeSteps[i] # self.listWidgetSteps.clearSelection() #self.listWidgetSteps.takeItem(item) #On force la sélection sur la ligne précédente self.listWidgetSteps.setCurrentRow(i-1) self.seeMash() def addStep(self) : index = self.listWidgetMashProfiles.currentRow() selected_mash = ImportBase().listeMashes[index] i = self.listWidgetSteps.currentRow() step = MashStep() step.name = 'Nouveau palier' step.type = 'Infusion' step.time = '0' step.temp = '0' step.vol = '0' selected_mash.listeSteps.append(step) self.listWidgetMashProfiles.setCurrentRow(index) self.seeMash() self.stepDetails() self.listWidgetMashProfiles.setCurrentRow(index) # self.listWidgetSteps.setCurrentRow(i-1) # self.stepEdit() def mashEdit(self) : index = self.listWidgetMashProfiles.currentRow() selected_mash = ImportBase().listeMashes[index] self.dlgMash.show() self.dlgMash.fields(selected_mash) def mashReload(self,mash) : #on remet le verrou à 0, il va falloir recalculer en repassant en brewday mode self.brewdayLock = 0 f = self.listWidgetMashProfiles.currentRow() selected_mash = ImportBase().listeMashes[f] selected_mash.name = mash.name selected_mash.ph = mash.ph selected_mash.grainTemp = 20 selected_mash.tunTemp = 20 selected_mash.spargeTemp = mash.spargeTemp self.popMashList() self.listWidgetMashProfiles.setCurrentRow(f) def addMash(self) : new_mash = Mash() new_mash.name = 'Nouveau profil' new_mash.grainTemp = '0' new_mash.tunTemp = '0' new_mash.spargeTemp = '78' new_mash.ph = 5.4 new_step = MashStep() new_step.name = 'Nouveau Palier' new_step.type = 'Infusion' new_step.time = '0' new_step.temp = '0' new_mash.listeSteps.append(new_step) ImportBase().listeMashes.append(new_mash) self.seeMash() self.listWidgetMashProfiles.setCurrentRow(len(ImportBase().listeMashes)-1) def removeMash(self) : i = self.listWidgetMashProfiles.currentRow() del ImportBase().listeMashes[i] self.seeMash() self.listWidgetSteps.clear() def mashRejected (self) : self.showLib() def saveProfile(self) : self.mashProfileExport.export(ImportBase().listeMashes) self.mashProfileExport.enregistrer(mash_file) @QtCore.pyqtSlot() def printRecipe (self) : printer=QtPrintSupport.QPrinter() dialog = QtPrintSupport.QPrintDialog(printer) dialog.setModal(True) dialog.setWindowTitle("Print Document" ) if dialog.exec_() == True: self.webViewBiblio.print(printer) # document=QtGui.QTextDocument() # stringHtml=self.recipe.export("print") # document.setHtml(stringHtml) # document.print(printer) @QtCore.pyqtSlot() def printBrewday(self) : printer=QtPrintSupport.QPrinter() dialog = QtPrintSupport.QPrintDialog(printer) dialog.setModal(True) dialog.setWindowTitle("Print Document" ) if dialog.exec_() == True: self.webViewBrewday.print(printer)
class FunctionalTest(unittest2.TestCase): def __init__(self, *args, **kwargs): super(FunctionalTest, self).__init__(*args, **kwargs) # XXX Read the configuration from env variables. self.server_url = SERVER_URL self.auth = DEFAULT_AUTH # Read the configuration. self.config = configparser.RawConfigParser() self.config.read(os.path.join(__HERE__, 'config/kinto.ini')) self.client = Client(server_url=self.server_url, auth=self.auth) def tearDown(self): # Delete all the created objects flush_url = urljoin(self.server_url, '/__flush__') resp = requests.post(flush_url) resp.raise_for_status() def get_user_id(self, credentials): hmac_secret = self.config.get('app:main', 'kinto.userid_hmac_secret') credentials = '%s:%s' % credentials digest = kinto_core_utils.hmac_digest(hmac_secret, credentials) return 'basicauth:%s' % digest def test_bucket_creation(self): bucket = self.client.create_bucket('mozilla') user_id = self.get_user_id(self.auth) assert user_id in bucket['permissions']['write'] def test_bucket_creation_if_not_exists(self): self.client.create_bucket('mozilla') # Should not raise. self.client.create_bucket('mozilla', if_not_exists=True) def test_buckets_retrieval(self): self.client.create_bucket('mozilla') buckets = self.client.get_buckets() assert len(buckets) == 1 def test_bucket_retrieval(self): self.client.create_bucket('mozilla') self.client.get_bucket('mozilla') # XXX Add permissions handling during creation and check they are # present during retrieval. def test_bucket_modification(self): bucket = self.client.create_bucket('mozilla', data={'version': 1}) assert bucket['data']['version'] == 1 bucket = self.client.patch_bucket('mozilla', data={'author': 'you'}) assert bucket['data']['version'] == 1 assert bucket['data']['author'] == 'you' bucket = self.client.update_bucket('mozilla', data={'date': 'today'}) assert bucket['data']['date'] == 'today' assert 'version' not in bucket['data'] def test_bucket_retrieval_fails_when_not_created(self): self.assertRaises(BucketNotFound, self.client.get_bucket, 'non-existent') def test_bucket_deletion(self): self.client.create_bucket('mozilla') self.client.delete_bucket('mozilla') self.assertRaises(BucketNotFound, self.client.get_bucket, 'mozilla') def test_bucket_deletion_if_exists(self): self.client.create_bucket('mozilla') self.client.delete_bucket('mozilla') self.client.delete_bucket('mozilla', if_exists=True) def test_buckets_deletion(self): self.client.create_bucket('mozilla') buckets = self.client.delete_buckets() assert buckets[0]['id'] == 'mozilla' self.assertRaises(BucketNotFound, self.client.get_bucket, 'mozilla') def test_buckets_deletion_when_no_buckets_exist(self): deleted_buckets = self.client.delete_buckets() assert len(deleted_buckets) == 0 def test_bucket_save(self): self.client.create_bucket('mozilla', permissions={'write': ['alexis']}) bucket = self.client.get_bucket('mozilla') assert 'alexis' in bucket['permissions']['write'] def test_group_creation(self): self.client.create_bucket('mozilla') self.client.create_group( 'payments', bucket='mozilla', data={'members': ['blah', ]}, permissions={'write': ['blah', ]}) # Test retrieval of a group gets the permissions as well. group = self.client.get_group('payments', bucket='mozilla') assert 'blah' in group['permissions']['write'] def test_group_creation_if_not_exists(self): self.client.create_bucket('mozilla') self.client.create_group('payments', bucket='mozilla', data={'members': ['blah', ]}) self.client.create_group( 'payments', bucket='mozilla', data={'members': ['blah', ]}, permissions={'write': ['blah', ]}, if_not_exists=True) def test_group_creation_if_bucket_does_not_exist(self): with pytest.raises(KintoException): self.client.create_group( 'payments', bucket='mozilla', data={'members': ['blah', ]}) self.client.create_group( 'payments', bucket='mozilla', data={'members': ['blah', ]}, if_not_exists=True) def test_group_update(self): self.client.create_bucket('mozilla') group = self.client.create_group( 'payments', bucket='mozilla', data={'members': ['blah', ]}, if_not_exists=True) assert group['data']['members'][0] == 'blah' group = self.client.update_group( data={'members': ['blah', 'foo']}, group='payments', bucket='mozilla') self.assertEquals(group['data']['members'][1], 'foo') def test_group_list(self): self.client.create_bucket('mozilla') self.client.create_group('receipts', bucket='mozilla', data={'members': ['blah', ]}) self.client.create_group('assets', bucket='mozilla', data={'members': ['blah', ]}) # The returned groups should be strings. groups = self.client.get_groups('mozilla') self.assertEquals(2, len(groups)) self.assertEquals(set([coll['id'] for coll in groups]), set(['receipts', 'assets'])) def test_group_deletion(self): self.client.create_bucket('mozilla') self.client.create_group('payments', bucket='mozilla', data={'members': ['blah', ]}) self.client.delete_group('payments', bucket='mozilla') assert len(self.client.get_groups(bucket='mozilla')) == 0 def test_group_deletion_if_exists(self): self.client.create_bucket('mozilla') self.client.create_group('payments', bucket='mozilla', data={'members': ['blah', ]}) self.client.delete_group('payments', bucket='mozilla') self.client.delete_group('payments', bucket='mozilla', if_exists=True) def test_group_deletion_can_still_raise_errors(self): error = KintoException("An error occured") with mock.patch.object(self.client.session, 'request', side_effect=error): with pytest.raises(KintoException): self.client.delete_group('payments', bucket='mozilla', if_exists=True) def test_groups_deletion(self): self.client.create_bucket('mozilla') self.client.create_group('amo', bucket='mozilla', data={'members': ['blah', ]}) self.client.create_group('blocklist', bucket='mozilla', data={'members': ['blah', ]}) self.client.delete_groups(bucket='mozilla') assert len(self.client.get_groups(bucket='mozilla')) == 0 def test_groups_deletion_when_no_groups_exist(self): self.client.create_bucket('mozilla') deleted_groups = self.client.delete_groups(bucket='mozilla') assert len(deleted_groups) == 0 def test_collection_creation(self): self.client.create_bucket('mozilla') self.client.create_collection( 'payments', bucket='mozilla', permissions={'write': ['alexis', ]} ) # Test retrieval of a collection gets the permissions as well. collection = self.client.get_collection('payments', bucket='mozilla') assert 'alexis' in collection['permissions']['write'] def test_collection_creation_if_not_exists(self): self.client.create_bucket('mozilla') self.client.create_collection('payments', bucket='mozilla') # Should not raise. self.client.create_collection('payments', bucket='mozilla', if_not_exists=True) def test_collection_list(self): self.client.create_bucket('mozilla') self.client.create_collection('receipts', bucket='mozilla') self.client.create_collection('assets', bucket='mozilla') # The returned collections should be strings. collections = self.client.get_collections('mozilla') self.assertEquals(2, len(collections)) self.assertEquals(set([coll['id'] for coll in collections]), set(['receipts', 'assets'])) def test_collection_deletion(self): self.client.create_bucket('mozilla') self.client.create_collection('payments', bucket='mozilla') self.client.delete_collection('payments', bucket='mozilla') assert len(self.client.get_collections(bucket='mozilla')) == 0 def test_collection_deletion_if_exists(self): self.client.create_bucket('mozilla') self.client.create_collection('payments', bucket='mozilla') self.client.delete_collection('payments', bucket='mozilla') self.client.delete_collection('payments', bucket='mozilla', if_exists=True) def test_collection_deletion_can_still_raise_errors(self): error = KintoException("An error occured") with mock.patch.object(self.client.session, 'request', side_effect=error): with pytest.raises(KintoException): self.client.delete_collection('payments', bucket='mozilla', if_exists=True) def test_collections_deletion(self): self.client.create_bucket('mozilla') self.client.create_collection('amo', bucket='mozilla') self.client.create_collection('blocklist', bucket='mozilla') self.client.delete_collections(bucket='mozilla') assert len(self.client.get_collections(bucket='mozilla')) == 0 def test_collections_deletion_when_no_collections_exist(self): self.client.create_bucket('mozilla') deleted_collections = self.client.delete_collections(bucket='mozilla') assert len(deleted_collections) == 0 def test_record_creation_and_retrieval(self): client = Client(server_url=self.server_url, auth=self.auth, bucket='mozilla', collection='payments') client.create_bucket() client.create_collection() created = client.create_record(data={'foo': 'bar'}, permissions={'read': ['alexis']}) record = client.get_record(created['data']['id']) assert 'alexis' in record['permissions']['read'] def test_records_list_retrieval(self): client = Client(server_url=self.server_url, auth=self.auth, bucket='mozilla', collection='payments') client.create_bucket() client.create_collection() client.create_record(data={'foo': 'bar'}, permissions={'read': ['alexis']}) records = client.get_records() assert len(records) == 1 def test_records_paginated_list_retrieval(self): client = Client(server_url=self.server_url, auth=self.auth, bucket='mozilla', collection='payments') client.create_bucket() client.create_collection() for i in range(10): client.create_record(data={'foo': 'bar'}, permissions={'read': ['alexis']}) # Kinto is running with kinto.paginate_by = 5 records = client.get_records() assert len(records) == 10 def test_single_record_save(self): client = Client(server_url=self.server_url, auth=self.auth, bucket='mozilla', collection='payments') client.create_bucket() client.create_collection() created = client.create_record(data={'foo': 'bar'}, permissions={'read': ['alexis']}) created['data']['bar'] = 'baz' # XXX enhance this in order to have to pass only one argument, created. client.update_record(id=created['data']['id'], data=created['data']) retrieved = client.get_record(created['data']['id']) assert 'alexis' in retrieved['permissions']['read'] assert retrieved['data']['foo'] == u'bar' assert retrieved['data']['bar'] == u'baz' assert created['data']['id'] == retrieved['data']['id'] def test_single_record_doesnt_overwrite(self): client = Client(server_url=self.server_url, auth=self.auth, bucket='mozilla', collection='payments') client.create_bucket() client.create_collection() created = client.create_record(data={'foo': 'bar'}, permissions={'read': ['alexis']}) with self.assertRaises(KintoException): # Create a second record with the ID of the first one. client.create_record(data={'id': created['data']['id'], 'bar': 'baz'}) def test_single_record_creation_if_not_exists(self): client = Client(server_url=self.server_url, auth=self.auth, bucket='mozilla', collection='payments') client.create_bucket() client.create_collection() created = client.create_record(data={'foo': 'bar'}) client.create_record(data={'id': created['data']['id'], 'bar': 'baz'}, if_not_exists=True) def test_single_record_can_overwrite(self): client = Client(server_url=self.server_url, auth=self.auth, bucket='mozilla', collection='payments') client.create_bucket() client.create_collection() created = client.create_record(data={'foo': 'bar'}, permissions={'read': ['alexis']}) client.create_record(data={'id': created['data']['id'], 'bar': 'baz'}, safe=False) def test_one_record_deletion(self): client = Client(server_url=self.server_url, auth=self.auth, bucket='mozilla', collection='payments') client.create_bucket() client.create_collection() record = client.create_record({'foo': 'bar'}) deleted = client.delete_record(record['data']['id']) assert deleted['deleted'] is True assert len(client.get_records()) == 0 def test_record_deletion_if_exists(self): client = Client(server_url=self.server_url, auth=self.auth, bucket='mozilla', collection='payments') client.create_bucket() client.create_collection() record = client.create_record({'foo': 'bar'}) deleted = client.delete_record(record['data']['id']) deleted_if_exists = client.delete_record(record['data']['id'], if_exists=True) assert deleted['deleted'] is True assert deleted_if_exists is None def test_multiple_record_deletion(self): client = Client(server_url=self.server_url, auth=self.auth, bucket='mozilla', collection='payments') client.create_bucket() client.create_collection() client.create_record({'foo': 'bar'}) client.delete_records() assert len(client.get_records()) == 0 def test_records_deletion_when_no_records_exist(self): client = Client(server_url=self.server_url, auth=self.auth, bucket='mozilla', collection='payments') client.create_bucket() client.create_collection() deleted_records = client.delete_records() assert len(deleted_records) == 0 def test_bucket_sharing(self): alice_credentials = ('alice', 'p4ssw0rd') alice_userid = self.get_user_id(alice_credentials) # Create a bucket and share it with alice. self.client.create_bucket('shared-bucket', permissions={'read': [alice_userid, ]}) alice_client = Client(server_url=self.server_url, auth=alice_credentials) alice_client.get_bucket('shared-bucket') def test_updating_data_on_a_group(self): client = Client(server_url=self.server_url, auth=self.auth, bucket='mozilla') client.create_bucket() client.create_group('payments', data={'members': []}) client.patch_group('payments', data={'secret': 'psssssst!'}) group = client.get_group('payments') assert group['data']['secret'] == 'psssssst!' def test_updating_data_on_a_collection(self): client = Client(server_url=self.server_url, auth=self.auth, bucket='mozilla', collection='payments') client.create_bucket() client.create_collection() client.patch_collection(data={'secret': 'psssssst!'}) collection = client.get_collection() assert collection['data']['secret'] == 'psssssst!' def test_collection_sharing(self): alice_credentials = ('alice', 'p4ssw0rd') alice_userid = self.get_user_id(alice_credentials) self.client.create_bucket('bob-bucket') self.client.create_collection( 'shared', bucket='bob-bucket', permissions={'read': [alice_userid, ]}) # Try to read the collection as Alice. alice_client = Client(server_url=self.server_url, auth=alice_credentials) alice_client.get_collection('shared', bucket='bob-bucket') def test_record_sharing(self): alice_credentials = ('alice', 'p4ssw0rd') alice_userid = self.get_user_id(alice_credentials) # Create a record, and share it with Alice. self.client.create_bucket('bob-bucket') self.client.create_collection('bob-personal-collection', bucket='bob-bucket') record = self.client.create_record( data={'foo': 'bar'}, permissions={'read': [alice_userid, ]}, bucket='bob-bucket', collection='bob-personal-collection') # Try to read the record as Alice alice_client = Client(server_url=self.server_url, auth=alice_credentials) record = alice_client.get_record( id=record['data']['id'], bucket='bob-bucket', collection='bob-personal-collection') assert record['data']['foo'] == 'bar' def test_request_batching(self): with self.client.batch(bucket='mozilla', collection='fonts') as batch: batch.create_bucket() batch.create_collection() batch.create_record(data={'foo': 'bar'}, permissions={'read': ['natim']}) batch.create_record(data={'bar': 'baz'}, permissions={'read': ['alexis']}) records = self.client.get_records(bucket='mozilla', collection='fonts') assert len(records) == 2 def test_replication(self): # First, create a few records on the first kinto collection. with self.client.batch(bucket='origin', collection='coll') as batch: batch.create_bucket() batch.create_collection() for n in range(10): batch.create_record(data={'foo': 'bar', 'n': n}) origin = Client( server_url=self.server_url, auth=self.auth, bucket='origin', collection='coll' ) destination = Client( server_url=self.server_url, auth=self.auth, bucket='destination', collection='coll') replication.replicate(origin, destination) records = self.client.get_records(bucket='destination', collection='coll') assert len(records) == 10
class FunctionalTest(unittest.TestCase): def setUp(self): super().setUp() # XXX Read the configuration from env variables. self.server_url = SERVER_URL self.auth = DEFAULT_AUTH # Read the configuration. self.config = configparser.RawConfigParser() self.config.read(os.path.join(__HERE__, "config/kinto.ini")) self.client = Client(server_url=self.server_url, auth=self.auth) self.create_user(self.auth) def tearDown(self): # Delete all the created objects flush_url = urljoin(self.server_url, "/__flush__") resp = requests.post(flush_url) resp.raise_for_status() def create_user(self, credentials): account_url = urljoin(self.server_url, "/accounts/{}".format(credentials[0])) r = requests.put(account_url, json={"data": { "password": credentials[1] }}, auth=DEFAULT_AUTH) r.raise_for_status() return r.json() def get_user_id(self, credentials): r = self.create_user(credentials) return "account:{}".format(r["data"]["id"]) def test_bucket_creation(self): bucket = self.client.create_bucket(id="mozilla") user_id = self.get_user_id(self.auth) assert user_id in bucket["permissions"]["write"] def test_bucket_creation_if_not_exists(self): self.client.create_bucket(id="mozilla") # Should not raise. self.client.create_bucket(id="mozilla", if_not_exists=True) def test_buckets_retrieval(self): self.client.create_bucket(id="mozilla") buckets = self.client.get_buckets() assert len(buckets) == 1 def test_bucket_retrieval(self): self.client.create_bucket(id="mozilla") self.client.get_bucket(id="mozilla") # XXX Add permissions handling during creation and check they are # present during retrieval. def test_bucket_modification(self): bucket = self.client.create_bucket(id="mozilla", data={"version": 1}) assert bucket["data"]["version"] == 1 bucket = self.client.patch_bucket(id="mozilla", data={"author": "you"}) assert bucket["data"]["version"] == 1 assert bucket["data"]["author"] == "you" bucket = self.client.update_bucket(id="mozilla", data={"date": "today"}) assert bucket["data"]["date"] == "today" assert "version" not in bucket["data"] def test_bucket_retrieval_fails_when_not_created(self): self.assertRaises(BucketNotFound, self.client.get_bucket, id="non-existent") def test_bucket_deletion(self): self.client.create_bucket(id="mozilla") self.client.delete_bucket(id="mozilla") self.assertRaises(BucketNotFound, self.client.get_bucket, id="mozilla") def test_bucket_deletion_if_exists(self): self.client.create_bucket(id="mozilla") self.client.delete_bucket(id="mozilla") self.client.delete_bucket(id="mozilla", if_exists=True) def test_buckets_deletion(self): self.client.create_bucket(id="mozilla") buckets = self.client.delete_buckets() assert buckets[0]["id"] == "mozilla" self.assertRaises(BucketNotFound, self.client.get_bucket, id="mozilla") def test_buckets_deletion_when_no_buckets_exist(self): deleted_buckets = self.client.delete_buckets() assert len(deleted_buckets) == 0 def test_bucket_save(self): self.client.create_bucket(id="mozilla", permissions={"write": ["account:alexis"]}) bucket = self.client.get_bucket(id="mozilla") assert "account:alexis" in bucket["permissions"]["write"] def test_group_creation(self): self.client.create_bucket(id="mozilla") self.client.create_group( id="payments", bucket="mozilla", data={"members": ["blah"]}, permissions={"write": ["blah"]}, ) # Test retrieval of a group gets the permissions as well. group = self.client.get_group(id="payments", bucket="mozilla") assert "blah" in group["permissions"]["write"] def test_group_creation_if_not_exists(self): self.client.create_bucket(id="mozilla") self.client.create_group(id="payments", bucket="mozilla", data={"members": ["blah"]}) self.client.create_group( id="payments", bucket="mozilla", data={"members": ["blah"]}, permissions={"write": ["blah"]}, if_not_exists=True, ) def test_group_creation_if_bucket_does_not_exist(self): with pytest.raises(KintoException) as e: self.client.create_group(id="payments", bucket="mozilla", data={"members": ["blah"]}) assert str(e).endswith( "PUT /v1/buckets/mozilla/groups/payments - " "403 Unauthorized. Please check that the " "bucket exists and that you have the permission " "to create or write on this group.") def test_group_update(self): self.client.create_bucket(id="mozilla") group = self.client.create_group(id="payments", bucket="mozilla", data={"members": ["blah"]}, if_not_exists=True) assert group["data"]["members"][0] == "blah" group = self.client.update_group(data={"members": ["blah", "foo"]}, id="payments", bucket="mozilla") self.assertEqual(group["data"]["members"][1], "foo") def test_group_list(self): self.client.create_bucket(id="mozilla") self.client.create_group(id="receipts", bucket="mozilla", data={"members": ["blah"]}) self.client.create_group(id="assets", bucket="mozilla", data={"members": ["blah"]}) # The returned groups should be strings. groups = self.client.get_groups(bucket="mozilla") self.assertEqual(2, len(groups)) self.assertEqual(set([coll["id"] for coll in groups]), set(["receipts", "assets"])) def test_group_deletion(self): self.client.create_bucket(id="mozilla") self.client.create_group(id="payments", bucket="mozilla", data={"members": ["blah"]}) self.client.delete_group(id="payments", bucket="mozilla") assert len(self.client.get_groups(bucket="mozilla")) == 0 def test_group_deletion_if_exists(self): self.client.create_bucket(id="mozilla") self.client.create_group(id="payments", bucket="mozilla", data={"members": ["blah"]}) self.client.delete_group(id="payments", bucket="mozilla") self.client.delete_group(id="payments", bucket="mozilla", if_exists=True) def test_group_deletion_can_still_raise_errors(self): error = KintoException("An error occured") with mock.patch.object(self.client.session, "request", side_effect=error): with pytest.raises(KintoException): self.client.delete_group(id="payments", bucket="mozilla", if_exists=True) def test_groups_deletion(self): self.client.create_bucket(id="mozilla") self.client.create_group(id="amo", bucket="mozilla", data={"members": ["blah"]}) self.client.create_group(id="blocklist", bucket="mozilla", data={"members": ["blah"]}) self.client.delete_groups(bucket="mozilla") assert len(self.client.get_groups(bucket="mozilla")) == 0 def test_groups_deletion_when_no_groups_exist(self): self.client.create_bucket(id="mozilla") deleted_groups = self.client.delete_groups(bucket="mozilla") assert len(deleted_groups) == 0 def test_collection_creation(self): self.client.create_bucket(id="mozilla") self.client.create_collection( id="payments", bucket="mozilla", permissions={"write": ["account:alexis"]}) # Test retrieval of a collection gets the permissions as well. collection = self.client.get_collection(id="payments", bucket="mozilla") assert "account:alexis" in collection["permissions"]["write"] def test_collection_not_found(self): self.client.create_bucket(id="mozilla") with pytest.raises(CollectionNotFound): self.client.get_collection(id="payments", bucket="mozilla") def test_collection_access_forbidden(self): with pytest.raises(KintoException): self.client.get_collection(id="payments", bucket="mozilla") def test_collection_creation_if_not_exists(self): self.client.create_bucket(id="mozilla") self.client.create_collection(id="payments", bucket="mozilla") # Should not raise. self.client.create_collection(id="payments", bucket="mozilla", if_not_exists=True) def test_collection_list(self): self.client.create_bucket(id="mozilla") self.client.create_collection(id="receipts", bucket="mozilla") self.client.create_collection(id="assets", bucket="mozilla") # The returned collections should be strings. collections = self.client.get_collections(bucket="mozilla") self.assertEqual(len(collections), 2) self.assertEqual(set([coll["id"] for coll in collections]), set(["receipts", "assets"])) def test_collection_deletion(self): self.client.create_bucket(id="mozilla") self.client.create_collection(id="payments", bucket="mozilla") self.client.delete_collection(id="payments", bucket="mozilla") assert len(self.client.get_collections(bucket="mozilla")) == 0 def test_collection_deletion_if_exists(self): self.client.create_bucket(id="mozilla") self.client.create_collection(id="payments", bucket="mozilla") self.client.delete_collection(id="payments", bucket="mozilla") self.client.delete_collection(id="payments", bucket="mozilla", if_exists=True) def test_collection_deletion_can_still_raise_errors(self): error = KintoException("An error occured") with mock.patch.object(self.client.session, "request", side_effect=error): with pytest.raises(KintoException): self.client.delete_collection(id="payments", bucket="mozilla", if_exists=True) def test_collections_deletion(self): self.client.create_bucket(id="mozilla") self.client.create_collection(id="amo", bucket="mozilla") self.client.create_collection(id="blocklist", bucket="mozilla") self.client.delete_collections(bucket="mozilla") assert len(self.client.get_collections(bucket="mozilla")) == 0 def test_collections_deletion_when_no_collections_exist(self): self.client.create_bucket(id="mozilla") deleted_collections = self.client.delete_collections(bucket="mozilla") assert len(deleted_collections) == 0 def test_record_creation_and_retrieval(self): client = Client(server_url=self.server_url, auth=self.auth, bucket="mozilla", collection="payments") client.create_bucket() client.create_collection() created = client.create_record( data={"foo": "bar"}, permissions={"read": ["account:alexis"]}) record = client.get_record(id=created["data"]["id"]) assert "account:alexis" in record["permissions"]["read"] def test_records_list_retrieval(self): client = Client(server_url=self.server_url, auth=self.auth, bucket="mozilla", collection="payments") client.create_bucket() client.create_collection() client.create_record(data={"foo": "bar"}, permissions={"read": ["account:alexis"]}) records = client.get_records() assert len(records) == 1 def test_records_timestamp_retrieval(self): client = Client(server_url=self.server_url, auth=self.auth, bucket="mozilla", collection="payments") client.create_bucket() client.create_collection() record = client.create_record(data={"foo": "bar"}, permissions={"read": ["account:alexis"]}) etag = client.get_records_timestamp() assert str(etag) == str(record["data"]["last_modified"]) def test_records_paginated_list_retrieval(self): client = Client(server_url=self.server_url, auth=self.auth, bucket="mozilla", collection="payments") client.create_bucket() client.create_collection() for i in range(10): client.create_record(data={"foo": "bar"}, permissions={"read": ["account:alexis"]}) # Kinto is running with kinto.paginate_by = 5 records = client.get_records() assert len(records) == 10 def test_records_generator_retrieval(self): client = Client(server_url=self.server_url, auth=self.auth, bucket="mozilla", collection="payments") client.create_bucket() client.create_collection() for i in range(10): client.create_record(data={"foo": "bar"}, permissions={"read": ["account:alexis"]}) pages = list(client.get_paginated_records()) assert len(pages) == 2 def test_single_record_save(self): client = Client(server_url=self.server_url, auth=self.auth, bucket="mozilla", collection="payments") client.create_bucket() client.create_collection() created = client.create_record( data={"foo": "bar"}, permissions={"read": ["account:alexis"]}) created["data"]["bar"] = "baz" # XXX enhance this in order to have to pass only one argument, created. client.update_record(id=created["data"]["id"], data=created["data"]) retrieved = client.get_record(id=created["data"]["id"]) assert "account:alexis" in retrieved["permissions"]["read"] assert retrieved["data"]["foo"] == u"bar" assert retrieved["data"]["bar"] == u"baz" assert created["data"]["id"] == retrieved["data"]["id"] def test_single_record_doesnt_overwrite(self): client = Client(server_url=self.server_url, auth=self.auth, bucket="mozilla", collection="payments") client.create_bucket() client.create_collection() created = client.create_record( data={"foo": "bar"}, permissions={"read": ["account:alexis"]}) with self.assertRaises(KintoException): # Create a second record with the ID of the first one. client.create_record(data={ "id": created["data"]["id"], "bar": "baz" }) def test_single_record_creation_if_not_exists(self): client = Client(server_url=self.server_url, auth=self.auth, bucket="mozilla", collection="payments") client.create_bucket() client.create_collection() created = client.create_record(data={"foo": "bar"}) client.create_record(data={ "id": created["data"]["id"], "bar": "baz" }, if_not_exists=True) def test_single_record_can_overwrite(self): client = Client(server_url=self.server_url, auth=self.auth, bucket="mozilla", collection="payments") client.create_bucket() client.create_collection() created = client.create_record( data={"foo": "bar"}, permissions={"read": ["account:alexis"]}) client.create_record(data={ "id": created["data"]["id"], "bar": "baz" }, safe=False) def test_one_record_deletion(self): client = Client(server_url=self.server_url, auth=self.auth, bucket="mozilla", collection="payments") client.create_bucket() client.create_collection() record = client.create_record(data={"foo": "bar"}) deleted = client.delete_record(id=record["data"]["id"]) assert deleted["deleted"] is True assert len(client.get_records()) == 0 def test_record_deletion_if_exists(self): client = Client(server_url=self.server_url, auth=self.auth, bucket="mozilla", collection="payments") client.create_bucket() client.create_collection() record = client.create_record(data={"foo": "bar"}) deleted = client.delete_record(id=record["data"]["id"]) deleted_if_exists = client.delete_record(id=record["data"]["id"], if_exists=True) assert deleted["deleted"] is True assert deleted_if_exists is None def test_multiple_record_deletion(self): client = Client(server_url=self.server_url, auth=self.auth, bucket="mozilla", collection="payments") client.create_bucket() client.create_collection() client.create_record(data={"foo": "bar"}) client.delete_records() assert len(client.get_records()) == 0 def test_records_deletion_when_no_records_exist(self): client = Client(server_url=self.server_url, auth=self.auth, bucket="mozilla", collection="payments") client.create_bucket() client.create_collection() deleted_records = client.delete_records() assert len(deleted_records) == 0 def test_bucket_sharing(self): alice_credentials = ("alice", "p4ssw0rd") alice_userid = self.get_user_id(alice_credentials) # Create a bucket and share it with alice. self.client.create_bucket(id="shared-bucket", permissions={"read": [alice_userid]}) alice_client = Client(server_url=self.server_url, auth=alice_credentials) alice_client.get_bucket(id="shared-bucket") def test_updating_data_on_a_group(self): client = Client(server_url=self.server_url, auth=self.auth, bucket="mozilla") client.create_bucket() client.create_group(id="payments", data={"members": []}) client.patch_group(id="payments", data={"secret": "psssssst!"}) group = client.get_group(id="payments") assert group["data"]["secret"] == "psssssst!" def test_updating_data_on_a_collection(self): client = Client(server_url=self.server_url, auth=self.auth, bucket="mozilla", collection="payments") client.create_bucket() client.create_collection() client.patch_collection(data={"secret": "psssssst!"}) collection = client.get_collection() assert collection["data"]["secret"] == "psssssst!" def test_collection_sharing(self): alice_credentials = ("alice", "p4ssw0rd") alice_userid = self.get_user_id(alice_credentials) self.client.create_bucket(id="bob-bucket") self.client.create_collection(id="shared", bucket="bob-bucket", permissions={"read": [alice_userid]}) # Try to read the collection as Alice. alice_client = Client(server_url=self.server_url, auth=alice_credentials) alice_client.get_collection(id="shared", bucket="bob-bucket") def test_record_sharing(self): alice_credentials = ("alice", "p4ssw0rd") alice_userid = self.get_user_id(alice_credentials) # Create a record, and share it with Alice. self.client.create_bucket(id="bob-bucket") self.client.create_collection(id="bob-personal-collection", bucket="bob-bucket") record = self.client.create_record( data={"foo": "bar"}, permissions={"read": [alice_userid]}, bucket="bob-bucket", collection="bob-personal-collection", ) # Try to read the record as Alice alice_client = Client(server_url=self.server_url, auth=alice_credentials) record = alice_client.get_record(id=record["data"]["id"], bucket="bob-bucket", collection="bob-personal-collection") assert record["data"]["foo"] == "bar" def test_request_batching(self): with self.client.batch(bucket="mozilla", collection="fonts") as batch: batch.create_bucket() batch.create_collection() batch.create_record(data={"foo": "bar"}, permissions={"read": ["natim"]}) batch.create_record(data={"bar": "baz"}, permissions={"read": ["account:alexis"]}) _, _, r1, r2 = batch.results() records = self.client.get_records(bucket="mozilla", collection="fonts") assert len(records) == 2 assert records[0] == r2["data"] assert records[1] == r1["data"] def test_patch_record_jsonpatch(self): self.client.create_bucket(id="b1") self.client.create_collection(id="c1", bucket="b1") self.client.create_record(id="r1", collection="c1", bucket="b1", data={"hello": "world"}) patch = JSONPatch([ { "op": "add", "path": "/data/goodnight", "value": "moon" }, { "op": "add", "path": "/permissions/read/alice" }, ]) self.client.patch_record(id="r1", collection="c1", bucket="b1", changes=patch) record = self.client.get_record(bucket="b1", collection="c1", id="r1") assert record["data"]["hello"] == "world" assert record["data"]["goodnight"] == "moon" assert record["permissions"]["read"] == ["alice"] def test_replication(self): # First, create a few records on the first kinto collection. with self.client.batch(bucket="origin", collection="coll") as batch: batch.create_bucket() batch.create_collection() for n in range(10): batch.create_record(data={"foo": "bar", "n": n}) origin = Client(server_url=self.server_url, auth=self.auth, bucket="origin", collection="coll") destination = Client(server_url=self.server_url, auth=self.auth, bucket="destination", collection="coll") replication.replicate(origin, destination) records = self.client.get_records(bucket="destination", collection="coll") assert len(records) == 10
class CollectionTest(unittest.TestCase): def setUp(self): self.session = mock.MagicMock() mock_response(self.session) self.client = Client(session=self.session, bucket='mybucket') def test_collection_names_are_slugified(self): self.client.get_collection('my collection') url = '/buckets/mybucket/collections/my-collection' self.session.request.assert_called_with('get', url) def test_collection_creation_issues_an_http_put(self): self.client.create_collection( 'mycollection', permissions=mock.sentinel.permissions) url = '/buckets/mybucket/collections/mycollection' self.session.request.assert_called_with( 'put', url, data=None, permissions=mock.sentinel.permissions, headers=DO_NOT_OVERWRITE) def test_data_can_be_sent_on_creation(self): self.client.create_collection( 'mycollection', 'testbucket', data={'foo': 'bar'}) self.session.request.assert_called_with( 'put', '/buckets/testbucket/collections/mycollection', data={'foo': 'bar'}, permissions=None, headers=DO_NOT_OVERWRITE) def test_collection_update_issues_an_http_put(self): self.client.update_collection( {'foo': 'bar'}, collection='mycollection', permissions=mock.sentinel.permissions) url = '/buckets/mybucket/collections/mycollection' self.session.request.assert_called_with( 'put', url, data={'foo': 'bar'}, permissions=mock.sentinel.permissions, headers=None) def test_update_handles_if_match(self): self.client.update_collection( {'foo': 'bar'}, collection='mycollection', if_match=1234) url = '/buckets/mybucket/collections/mycollection' headers = {'If-Match': '"1234"'} self.session.request.assert_called_with( 'put', url, data={'foo': 'bar'}, headers=headers, permissions=None) def test_collection_update_use_an_if_match_header(self): data = {'foo': 'bar', 'last_modified': '1234'} self.client.update_collection( data, collection='mycollection', permissions=mock.sentinel.permissions) url = '/buckets/mybucket/collections/mycollection' self.session.request.assert_called_with( 'put', url, data={'foo': 'bar', 'last_modified': '1234'}, permissions=mock.sentinel.permissions, headers={'If-Match': '"1234"'}) def test_patch_collection_issues_an_http_patch(self): self.client.patch_collection( collection='mycollection', data={'key': 'secret'}) url = '/buckets/mybucket/collections/mycollection' self.session.request.assert_called_with( 'patch', url, data={'key': 'secret'}, headers=None, permissions=None) def test_patch_collection_handles_if_match(self): self.client.patch_collection( collection='mycollection', data={'key': 'secret'}, if_match=1234) url = '/buckets/mybucket/collections/mycollection' headers = {'If-Match': '"1234"'} self.session.request.assert_called_with( 'patch', url, data={'key': 'secret'}, headers=headers, permissions=None) def test_get_collections_returns_the_list_of_collections(self): mock_response( self.session, data=[ {'id': 'foo', 'last_modified': '12345'}, {'id': 'bar', 'last_modified': '59874'}, ]) collections = self.client.get_collections(bucket='default') assert list(collections) == [ {'id': 'foo', 'last_modified': '12345'}, {'id': 'bar', 'last_modified': '59874'}, ] def test_collection_can_delete_all_its_records(self): self.client.delete_records(bucket='abucket', collection='acollection') url = '/buckets/abucket/collections/acollection/records' self.session.request.assert_called_with('delete', url, headers=None) def test_delete_is_issued_on_list_deletion(self): self.client.delete_collections(bucket='mybucket') url = '/buckets/mybucket/collections' self.session.request.assert_called_with('delete', url, headers=None) def test_collection_can_be_deleted(self): data = {} mock_response(self.session, data=data) deleted = self.client.delete_collection('mycollection') assert deleted == data url = '/buckets/mybucket/collections/mycollection' self.session.request.assert_called_with('delete', url, headers=None) def test_collection_delete_if_match(self): data = {} mock_response(self.session, data=data) deleted = self.client.delete_collection( 'mycollection', if_match=1234) assert deleted == data url = '/buckets/mybucket/collections/mycollection' self.session.request.assert_called_with( 'delete', url, headers={'If-Match': '"1234"'}) def test_collection_delete_if_match_not_included_if_not_safe(self): data = {} mock_response(self.session, data=data) deleted = self.client.delete_collection( 'mycollection', if_match=1324, safe=False) assert deleted == data url = '/buckets/mybucket/collections/mycollection' self.session.request.assert_called_with('delete', url, headers=None) def test_get_or_create_doesnt_raise_in_case_of_conflict(self): data = { 'permissions': mock.sentinel.permissions, 'data': {'foo': 'bar'} } self.session.request.side_effect = [ get_http_error(status=412), (data, None) ] returned_data = self.client.create_collection( bucket="buck", collection="coll", if_not_exists=True) # Should not raise. assert returned_data == data def test_get_or_create_raise_in_other_cases(self): self.session.request.side_effect = get_http_error(status=500) with self.assertRaises(KintoException): self.client.create_collection( bucket="buck", collection="coll", if_not_exists=True) def test_create_collection_raises_a_special_error_on_403(self): self.session.request.side_effect = get_http_error(status=403) with self.assertRaises(KintoException) as e: self.client.create_collection( bucket="buck", collection="coll") expected_msg = ("Unauthorized. Please check that the bucket exists " "and that you have the permission to create or write " "on this collection.") assert e.exception.message == expected_msg