def test_round_trip_with_delete_missing_records_ask_for_confirmation(self): # Load some data cmd = 'kinto-wizard {} --server={} --auth={}' load_cmd = cmd.format("load {}".format(self.file), self.server, self.auth) sys.argv = load_cmd.split(" ") main() # Change something that could make the server to fail. client = Client(server_url=self.server, auth=tuple(self.auth.split(':'))) client.create_record(bucket='build-hub', collection='archives', id='8031d549-0a69-48dd-b240-feef94688d47', data={}) cmd = 'kinto-wizard {} --server={} -D --auth={} --delete-records' load_cmd = cmd.format("load {}".format(self.file), self.server, self.auth) sys.argv = load_cmd.split(" ") with mockInput('yes'): main() with pytest.raises(exceptions.KintoException) as exc: client.get_record(bucket='build-hub', collection='archives', id='8031d549-0a69-48dd-b240-feef94688d47') assert "'Not Found'" in str(exc.value)
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_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_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_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_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_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_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_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_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_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_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 create_booth_with_auth(booth, username): password = accounts_helper.create_user(username) print(f'created user "{username}" with password "{password}"') client = Client(server_url=kinto_url, auth=(username, password), bucket="weihnachtsmarkt", collection="booths") del_none(booth) client.create_record(data=booth) print(f'created booth {booth["name"]} for market {booth["market"]}')
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_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_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_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_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_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_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_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_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_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_delete_request_removes_data(conf, env, fxa_account, fxa_urls, fxa_client): if env == 'prod': pytest.skip('kintowe GDPR tests are not run in production') auth = FxABearerTokenAuth( fxa_account.email, fxa_account.password, scopes=['sync:addon_storage'], client_id=DEFAULT_CLIENT_ID, account_server_url=fxa_urls['authentication'], oauth_server_url=fxa_urls['oauth'], ) # Add some data to chrome.storage (kintowe) we_client = Client(server_url=conf.get(env, 'we_server_url'), auth=auth) we_existing_records = we_client.get_records(collection=conf.get( env, 'qa_collection'), bucket='default') assert len(we_existing_records) == 0 data = {"payload": {"encrypted": "SmluZ28gdGVzdA=="}} we_record = we_client.create_record( data=data, collection=conf.get(env, 'qa_collection'), bucket='default', permissions={"read": ["system.Everyone"]}) we_record_id = we_record['data']['id'] we_updated_records = we_client.get_records(collection=conf.get( env, 'qa_collection'), bucket='default') assert len(we_updated_records) == len(we_existing_records) + 1 # Get the aliases of the bucket we are putting data in and # make sure that an unauthenticated user can see these records # before we delete the account we_bucket_id = we_client.server_info()["user"]["bucket"] anon_we_client = Client(server_url=conf.get(env, 'we_server_url')) resp = anon_we_client.get_record(id=we_record_id, bucket=we_bucket_id, collection=conf.get(env, 'qa_collection')) assert resp['data']['id'] == we_record_id # Delete FxA account fxa_client.destroy_account(fxa_account.email, fxa_account.password) # Wait 1 minute and then make sure the records do not exist because the # Kinto client will throw an exception for non-existent records time.sleep(60) with pytest.raises(KintoException): resp = anon_we_client.get_record(id=we_record_id, bucket=we_bucket_id, collection=conf.get( env, 'qa_collection'))
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_delete_request_removes_data(conf, env, fxa_account, fxa_urls, fxa_client): if env == 'prod': pytest.skip('testpilot GDPR tests are not run in production') auth = FxABearerTokenAuth( fxa_account.email, fxa_account.password, client_id=DEFAULT_CLIENT_ID, scopes=["https://identity.mozilla.com/apps/notes"], account_server_url=fxa_urls['authentication'], oauth_server_url=fxa_urls['oauth'], ) # Add some data to the Notes collection tp_client = Client(server_url=conf.get(env, 'tp_server_url'), auth=auth) tp_existing_records = tp_client.get_records(collection='notes', bucket='default') assert len(tp_existing_records) == 0 data = {"subject": "QA Test", "value": "This stuff should get deleted"} tp_record = tp_client.create_record( data=data, collection='notes', permissions={"read": ["system.Everyone"]}) tp_record_id = tp_record['data']['id'] tp_updated_records = tp_client.get_records(collection='notes', bucket='default') assert len(tp_updated_records) == len(tp_existing_records) + 1 # Get the aliases of the bucket we are putting data in and # make sure that an unauthenticated user can see these records # before we delete the account tp_bucket_id = tp_client.server_info()["user"]["bucket"] anon_tp_client = Client(server_url=conf.get(env, 'tp_server_url')) resp = anon_tp_client.get_record(id=tp_record_id, bucket=tp_bucket_id, collection='notes') assert resp['data']['id'] == tp_record_id # Delete FxA account fxa_client.destroy_account(fxa_account.email, fxa_account.password) # Wait 5 minutes and then make sure the records do not exist because the # Kinto client will throw an exception for non-existent records time.sleep(120) with pytest.raises(KintoException): resp = anon_tp_client.get_record(id=tp_record_id, bucket=tp_bucket_id, collection='notes')
def test_add_content(env, conf): # Grab a bearer token that we can use to talk to the webextensions endpoint acct = TestEmailAccount() email = acct.email passwd = str(uuid.uuid4()) fxaclient = FxaClient("https://api.accounts.firefox.com") session = fxaclient.create_account(email, passwd) m = acct.wait_for_email(lambda m: "x-verify-code" in m["headers"]) if m is None: raise RuntimeErrors("Verification email did not arrive") session.verify_email_code(m["headers"]["x-verify-code"]) auth = FxABearerTokenAuth( email, passwd, scopes=['sync:addon_storage'], client_id=DEFAULT_CLIENT_ID, account_server_url=conf.get(env, 'account_server_url'), oauth_server_url=conf.get(env, 'oauth_server_url'), ) client = Client(server_url=conf.get(env, 'we_server_url'), auth=auth) # Add a record to our QA collection and make sure we have N+1 records existing_records = client.get_records(collection=conf.get( env, 'qa_collection'), bucket='default') assert len(existing_records) == 0 data = {"payload": {"encrypted": "SmluZ28gdGVzdA=="}} resp = client.create_record(data=data, collection=conf.get(env, 'qa_collection'), bucket='default') new_record_id = resp['data']['id'] updated_records = client.get_records(collection=conf.get( env, 'qa_collection'), bucket='default') assert len(updated_records) == len(existing_records) + 1 client.delete_record(id=new_record_id, collection=conf.get(env, 'qa_collection')) updated_records = client.get_records(collection=conf.get( env, 'qa_collection'), bucket='default') assert len(updated_records) == len(existing_records) # Clean up the account that we created for the test acct.clear() fxaclient.destroy_account(email, passwd)
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']
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_add_content(env, conf, fxa_account, fxa_urls): if env == 'prod': pytest.skip('qa cannot create records in production') auth = FxABearerTokenAuth( fxa_account.email, fxa_account.password, scopes=['sync:addon_storage'], client_id=DEFAULT_CLIENT_ID, account_server_url=fxa_urls['authentication'], oauth_server_url=fxa_urls['oauth'], ) client = Client(server_url=conf.get(env, 'we_server_url'), auth=auth) # Add a record to our QA collection and make sure we have N+1 records existing_records = client.get_records(collection=conf.get( env, 'qa_collection'), bucket='default') assert len(existing_records) == 0 data = {"payload": {"encrypted": "SmluZ28gdGVzdA=="}} resp = client.create_record(data=data, collection=conf.get(env, 'qa_collection'), bucket='default') new_record_id = resp['data']['id'] updated_records = client.get_records(collection=conf.get( env, 'qa_collection'), bucket='default') assert len(updated_records) == len(existing_records) + 1 client.delete_record(id=new_record_id, collection=conf.get(env, 'qa_collection')) updated_records = client.get_records(collection=conf.get( env, 'qa_collection'), bucket='default') assert len(updated_records) == len(existing_records)
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'")
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 RecordTest(unittest.TestCase): def setUp(self): self.session = mock.MagicMock() self.client = Client( session=self.session, bucket='mybucket', collection='mycollection') def test_record_id_is_given_after_creation(self): mock_response(self.session, data={'id': 5678}) record = self.client.create_record({'foo': 'bar'}) assert 'id' in record['data'].keys() def test_generated_record_id_is_an_uuid(self): mock_response(self.session) self.client.create_record({'foo': 'bar'}) id = self.session.request.mock_calls[0][1][1].split('/')[-1] uuid_regexp = r'[\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12}' self.assertRegexpMatches(id, uuid_regexp) def test_records_handles_permissions(self): mock_response(self.session) self.client.create_record( {'id': '1234', 'foo': 'bar'}, permissions=mock.sentinel.permissions) self.session.request.assert_called_with( 'put', '/buckets/mybucket/collections/mycollection/records/1234', data={'foo': 'bar', 'id': '1234'}, permissions=mock.sentinel.permissions, headers=DO_NOT_OVERWRITE) def test_collection_argument_takes_precedence(self): mock_response(self.session) # Specify a different collection name for the client and the operation. client = Client(session=self.session, bucket='mybucket', collection='wrong_collection') client.update_record(data={'id': '1234'}, collection='good_collection', permissions=mock.sentinel.permissions) self.session.request.assert_called_with( 'put', '/buckets/mybucket/collections/good_collection/records/1234', data={'id': '1234'}, headers=None, permissions=mock.sentinel.permissions) def test_record_id_is_derived_from_data_if_present(self): mock_response(self.session) self.client.create_record(data={'id': '1234', 'foo': 'bar'}, permissions=mock.sentinel.permissions) self.session.request.assert_called_with( 'put', '/buckets/mybucket/collections/mycollection/records/1234', data={'id': '1234', 'foo': 'bar'}, permissions=mock.sentinel.permissions, headers=DO_NOT_OVERWRITE) def test_data_and_permissions_are_added_on_create(self): mock_response(self.session) data = {'foo': 'bar'} permissions = {'read': ['mle']} self.client.create_record( id='1234', data=data, permissions=permissions) url = '/buckets/mybucket/collections/mycollection/records/1234' self.session.request.assert_called_with( 'put', url, data=data, permissions=permissions, headers=DO_NOT_OVERWRITE) def test_creation_sends_if_none_match_by_default(self): mock_response(self.session) data = {'foo': 'bar'} self.client.create_record( id='1234', data=data) url = '/buckets/mybucket/collections/mycollection/records/1234' self.session.request.assert_called_with( 'put', url, data=data, permissions=None, headers=DO_NOT_OVERWRITE) def test_creation_doesnt_add_if_none_match_when_overwrite(self): mock_response(self.session) data = {'foo': 'bar'} self.client.create_record(id='1234', data=data, safe=False) url = '/buckets/mybucket/collections/mycollection/records/1234' self.session.request.assert_called_with( 'put', url, data=data, permissions=None, headers=None) def test_records_issues_a_request_on_delete(self): mock_response(self.session) self.client.delete_record('1234') url = '/buckets/mybucket/collections/mycollection/records/1234' self.session.request.assert_called_with('delete', url, headers=None) def test_record_issues_a_request_on_retrieval(self): mock_response(self.session, data={'foo': 'bar'}) record = self.client.get_record('1234') self.assertEquals(record['data'], {'foo': 'bar'}) url = '/buckets/mybucket/collections/mycollection/records/1234' self.session.request.assert_called_with('get', url) def test_collection_can_retrieve_all_records(self): mock_response(self.session, data=[{'id': 'foo'}, {'id': 'bar'}]) records = self.client.get_records() assert list(records) == [{'id': 'foo'}, {'id': 'bar'}] def test_collection_can_retrieve_records_timestamp(self): mock_response(self.session, data=[{'id': 'foo'}, {'id': 'bar'}], headers={"ETag": '"12345"'}) timestamp = self.client.get_records_timestamp() assert timestamp == '12345' def test_records_timestamp_is_cached(self): mock_response(self.session, data=[{'id': 'foo'}, {'id': 'bar'}], headers={"ETag": '"12345"'}) self.client.get_records() timestamp = self.client.get_records_timestamp() assert timestamp == '12345' assert self.session.request.call_count == 1 def test_records_timestamp_is_cached_per_collection(self): mock_response(self.session, data=[{'id': 'foo'}, {'id': 'bar'}], headers={"ETag": '"12345"'}) self.client.get_records(collection="foo") mock_response(self.session, data=[{'id': 'foo'}, {'id': 'bar'}], headers={"ETag": '"67890"'}) self.client.get_records(collection="bar") timestamp = self.client.get_records_timestamp("foo") assert timestamp == '12345' timestamp = self.client.get_records_timestamp("bar") assert timestamp == '67890' def test_pagination_is_followed(self): # Mock the calls to request. link = ('http://example.org/buckets/buck/collections/coll/records/' '?token=1234') self.session.request.side_effect = [ # First one returns a list of items with a pagination token. build_response( [{'id': '1', 'value': 'item1'}, {'id': '2', 'value': 'item2'}, ], {'Next-Page': link}), # Second one returns a list of items without a pagination token. build_response( [{'id': '3', 'value': 'item3'}, {'id': '4', 'value': 'item4'}, ], ), ] records = self.client.get_records('bucket', 'collection') assert list(records) == [ {'id': '1', 'value': 'item1'}, {'id': '2', 'value': 'item2'}, {'id': '3', 'value': 'item3'}, {'id': '4', 'value': 'item4'}, ] def test_pagination_supports_if_none_match(self): link = ('http://example.org/buckets/buck/collections/coll/records/' '?token=1234') self.session.request.side_effect = [ # First one returns a list of items with a pagination token. build_response( [{'id': '1', 'value': 'item1'}, {'id': '2', 'value': 'item2'}, ], {'Next-Page': link}), # Second one returns a list of items without a pagination token. build_response( [{'id': '3', 'value': 'item3'}, {'id': '4', 'value': 'item4'}, ], ), ] self.client.get_records('bucket', 'collection', if_none_match="1234") # Check that the If-None-Match header is present in the requests. self.session.request.assert_any_call( 'get', '/buckets/collection/collections/bucket/records', headers={'If-None-Match': '"1234"'}, params={}) self.session.request.assert_any_call( 'get', link, headers={'If-None-Match': '"1234"'}, params={}) def test_collection_can_delete_a_record(self): mock_response(self.session, data={'id': 1234}) resp = self.client.delete_record(id=1234) assert resp == {'id': 1234} url = '/buckets/mybucket/collections/mycollection/records/1234' self.session.request.assert_called_with('delete', url, headers=None) def test_record_delete_if_match(self): data = {} mock_response(self.session, data=data) deleted = self.client.delete_record( collection='mycollection', bucket='mybucket', id='1', if_match=1234) assert deleted == data url = '/buckets/mybucket/collections/mycollection/records/1' self.session.request.assert_called_with( 'delete', url, headers={'If-Match': '"1234"'}) def test_record_delete_if_match_not_included_if_not_safe(self): data = {} mock_response(self.session, data=data) deleted = self.client.delete_record( collection='mycollection', bucket='mybucket', id='1', if_match=1234, safe=False) assert deleted == data url = '/buckets/mybucket/collections/mycollection/records/1' self.session.request.assert_called_with( 'delete', url, headers=None) def test_update_record_gets_the_id_from_data_if_exists(self): mock_response(self.session) self.client.update_record( bucket='mybucket', collection='mycollection', data={'id': 1, 'foo': 'bar'}) self.session.request.assert_called_with( 'put', '/buckets/mybucket/collections/mycollection/records/1', data={'id': 1, 'foo': 'bar'}, headers=None, permissions=None) def test_update_record_handles_if_match(self): mock_response(self.session) self.client.update_record( bucket='mybucket', collection='mycollection', data={'id': 1, 'foo': 'bar'}, if_match=1234) headers = {'If-Match': '"1234"'} self.session.request.assert_called_with( 'put', '/buckets/mybucket/collections/mycollection/records/1', data={'id': 1, 'foo': 'bar'}, headers=headers, permissions=None) def test_patch_record_uses_the_patch_method(self): mock_response(self.session) self.client.patch_record( bucket='mybucket', collection='mycollection', data={'id': 1, 'foo': 'bar'}) self.session.request.assert_called_with( 'patch', '/buckets/mybucket/collections/mycollection/records/1', data={'id': 1, 'foo': 'bar'}, headers=None, permissions=None) def test_update_record_raises_if_no_id_is_given(self): with self.assertRaises(KeyError) as cm: self.client.update_record( data={'foo': 'bar'}, # Omit the id on purpose here. bucket='mybucket', collection='mycollection' ) assert text_type(cm.exception) == ( "'Unable to update a record, need an id.'") 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_record( bucket="buck", collection="coll", data={'id': 1234, 'foo': 'bar'}, 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_record( bucket="buck", collection="coll", data={'foo': 'bar'}, if_not_exists=True) def test_create_record_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_record( bucket="buck", collection="coll", data={'foo': 'bar'}) expected_msg = ("Unauthorized. Please check that the collection exists" " and that you have the permission to create or write " "on this collection record.") assert e.exception.message == expected_msg
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