def update(dataset_id, dictionary, author_id): # TODO(roman): Make author_id argument optional (keep old author if None). dataset_validator.validate(dictionary) with db.engine.begin() as connection: if "description" not in dictionary: dictionary["description"] = None connection.execute("""UPDATE dataset SET (name, description, public, author, last_edited) = (%s, %s, %s, %s, now()) WHERE id = %s""", (dictionary["name"], dictionary["description"], dictionary["public"], author_id, dataset_id)) # Replacing old classes with new ones connection.execute("""DELETE FROM dataset_class WHERE dataset = %s""", (dataset_id,)) for cls in dictionary["classes"]: if "description" not in cls: cls["description"] = None result = connection.execute("""INSERT INTO dataset_class (name, description, dataset) VALUES (%s, %s, %s) RETURNING id""", (cls["name"], cls["description"], dataset_id)) cls_id = result.fetchone()[0] for recording_mbid in cls["recordings"]: connection.execute("INSERT INTO dataset_class_member (class, mbid) VALUES (%s, %s)", (cls_id, recording_mbid))
def create_from_dict(dictionary, author_id): """Creates a new dataset from a dictionary. Returns: Tuple with two values: new dataset ID and error. If error occurs first will be None and second is an exception. If there are no errors, second value will be None. """ dataset_validator.validate(dictionary) with db.engine.begin() as connection: if "description" not in dictionary: dictionary["description"] = None result = connection.execute("""INSERT INTO dataset (id, name, description, public, author) VALUES (uuid_generate_v4(), %s, %s, %s, %s) RETURNING id""", (dictionary["name"], dictionary["description"], dictionary["public"], author_id)) dataset_id = result.fetchone()[0] for cls in dictionary["classes"]: if "description" not in cls: cls["description"] = None result = connection.execute("""INSERT INTO dataset_class (name, description, dataset) VALUES (%s, %s, %s) RETURNING id""", (cls["name"], cls["description"], dataset_id)) cls_id = result.fetchone()[0] # Removing duplicate recordings cls["recordings"] = list(set(cls["recordings"])) for recording_mbid in cls["recordings"]: connection.execute("INSERT INTO dataset_class_member (class, mbid) VALUES (%s, %s)", (cls_id, recording_mbid)) return dataset_id
def update(dataset_id, dictionary, author_id): # TODO(roman): Make author_id argument optional (keep old author if None). dataset_validator.validate(dictionary) with db.engine.begin() as connection: if "description" not in dictionary or dictionary["description"] is None: dictionary["description"] = "" connection.execute( """UPDATE dataset SET (name, description, public, author, last_edited) = (%s, %s, %s, %s, now()) WHERE id = %s""", (dictionary["name"], dictionary["description"], dictionary["public"], author_id, dataset_id)) # Replacing old classes with new ones connection.execute("""DELETE FROM dataset_class WHERE dataset = %s""", (dataset_id, )) for cls in dictionary["classes"]: if "description" not in cls or cls["description"] is None: cls["description"] = "" result = connection.execute( """INSERT INTO dataset_class (name, description, dataset) VALUES (%s, %s, %s) RETURNING id""", (cls["name"], cls["description"], dataset_id)) cls_id = result.fetchone()[0] for recording_mbid in cls["recordings"]: connection.execute( "INSERT INTO dataset_class_member (class, mbid) VALUES (%s, %s)", (cls_id, recording_mbid))
def test_dataset_item_lengths(self): # Incorrect lengths with self.assertRaises(dataset_validator.ValidationException) as ar: dataset_validator.validate({ "name": "", # Smaller than Min Len "classes": [], "public": False, }) self.assertEqual(str(ar.exception), "Dataset name must be between 1 and 100 characters") with self.assertRaises(dataset_validator.ValidationException) as ar: dataset_validator.validate({ "name": "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuv \ wxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghj", # Greater than Max Len "classes": [], "public": False, }) self.assertEqual(str(ar.exception), "Dataset name must be between 1 and 100 characters") with self.assertRaises(dataset_validator.ValidationException) as ar: dataset_validator.validate({ "name": "this dataset", "classes": [ { "name": "", # Smaller than Min Len "recordings": [], }, ], "public": False, }) self.assertEqual(str(ar.exception), "Length of the `name` field in class number 0 doesn't fit the limits. Class name must be between 1 and 100 characters") with self.assertRaises(dataset_validator.ValidationException) as ar: dataset_validator.validate({ "name": "this dataset", "classes": [ { "name": "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl \ mnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghj", #Greater than Max Len "recordings": [], }, ], "public": False, }) self.assertEqual(str(ar.exception), "Length of the `name` field in class number 0 doesn't fit the limits. Class name must be between 1 and 100 characters") with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "test", "classes": [ { "name": "Not Rock", "why": "Because", # this item shouldn't be there "recordings": [], }, ], "public": False, })
def test_dataset_unexpected_items(self): # Unexpected items with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "i_like": "to test", }) with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "i": "don't", }) with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "Dataset", "surname": "For Testing", # this item shouldn't be there "classes": [ { "name": "Not Rock", "recordings": [], }, ], "public": False, }) with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "Dataset", "classes": [ { "name": "Rock", "why": "Because", # this item shouldn't be there "recordings": [], }, ], "public": True, })
def test_dataset_missing_values(self): # Missing values with self.assertRaises(dataset_validator.ValidationException): # Dataset name is missing dataset_validator.validate({ "classes": [ { "name": "the one and only", "recordings": [], }, ], "public": False, }) with self.assertRaises(dataset_validator.ValidationException): # List of classes is missing dataset_validator.validate({ "name": "test", "public": False, }) with self.assertRaises(dataset_validator.ValidationException): # Publicity value is missing dataset_validator.validate({ "name": "test", "classes": [], }) with self.assertRaises(dataset_validator.ValidationException): # Class name is missing dataset_validator.validate({ "name": "test", "classes": [ { "recordings": [], }, ], "public": False, }) with self.assertRaises(dataset_validator.ValidationException): # List of recordings in a class is missing dataset_validator.validate({ "name": "test", "classes": [ { "name": "this", }, ], "public": False, })
def test_dataset_missing_values(self): # Missing values with self.assertRaises(dataset_validator.ValidationException): # Dataset name is missing dataset_validator.validate({ "classes": [ { "name": "the one and only", "recordings": [], }, ], "public": False, }) with self.assertRaises(dataset_validator.ValidationException): # List of classes is missing dataset_validator.validate({ "name": "test", "public": False, }) with self.assertRaises(dataset_validator.ValidationException): # Publicity value is missing dataset_validator.validate({ "name": "test", "classes": [], }) with self.assertRaises(dataset_validator.ValidationException): # Class name is missing dataset_validator.validate({ "name": "test", "classes": [ { "recordings": [], }, ], "public": False, }) with self.assertRaises(dataset_validator.ValidationException): # List of recordings in a class is missing dataset_validator.validate({ "name": "test", "classes": [ { "name": "this", }, ], "public": False, })
def test_dataset_item_lengths(self): # Incorrect lengths with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "", # incorrect "classes": [], "public": False, }) with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "this dataset", "classes": [ { "name": "", # incorrect "recordings": [], }, ], "public": False, }) with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "test", "classes": [ { "name": "Not Rock", "why": "Because", # this item shouldn't be there "recordings": [], }, ], "public": False, })
def create_from_dict(dictionary, author_id): """Creates a new dataset from a dictionary. Returns: Tuple with two values: new dataset ID and error. If error occurs first will be None and second is an exception. If there are no errors, second value will be None. """ dataset_validator.validate(dictionary) with db.engine.begin() as connection: if "description" not in dictionary: dictionary["description"] = None result = connection.execute("""INSERT INTO dataset (id, name, description, public, author) VALUES (uuid_generate_v4(), %s, %s, %s, %s) RETURNING id""", (dictionary["name"], dictionary["description"], dictionary["public"], author_id)) dataset_id = result.fetchone()[0] for cls in dictionary["classes"]: if "description" not in cls: cls["description"] = None result = connection.execute("""INSERT INTO dataset_class (name, description, dataset) VALUES (%s, %s, %s) RETURNING id""", (cls["name"], cls["description"], dataset_id)) cls_id = result.fetchone()[0] # Remove duplicate recordings, preserving order seen = set() cls["recordings"] = [r for r in cls["recordings"] if not (r in seen or seen.add(r))] for recording_mbid in cls["recordings"]: connection.execute("INSERT INTO dataset_class_member (class, mbid) VALUES (%s, %s)", (cls_id, recording_mbid)) return dataset_id
def test_dataset_unexpected_items(self): # Unexpected items with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "i_like": "to test", }) with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "i": "don't", }) with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "Dataset", "surname": "For Testing", # this item shouldn't be there "classes": [ { "name": "Not Rock", "recordings": [], }, ], "public": False, }) with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "Dataset", "classes": [ { "name": "Rock", "why": "Because", # this item shouldn't be there "recordings": [], }, ], "public": True, })
def test_dataset_incorrect_types(self): # Incorrect types # String, not dict with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate("dataset") # Name should be string with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": ["This", "is", "my", "cool", "dataset"], "classes": [], "public": False, }) # Desc should be string with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "test", "description": False, "classes": [], "public": False, }) # Classes should be list with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "test", "description": "", "classes": None, "public": False, }) # public should be bool with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "test", "description": "", "classes": [], "public": "Nope", }) # class name should be string with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "test", "classes": [ { "name": ("this", "is", "a", "name"), "recordings": [], }, ], "public": False, }) # class elements should be dict with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "test", "classes": [ "first", "second", ], "public": False, }) # Class desc should be string with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "test", "classes": [ { "name": "first", "description": False, "recordings": [], }, ], "public": False, }) # class recordings should be list with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "test", "classes": [ { "name": "first", "recordings": "I don't have any :(", }, ], "public": False, }) # Class recordings should be uuids with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "test", "classes": [ { "name": "first", "recordings": ["my favourite"], }, ], "public": False, })
def test_dataset_item_lengths(self): # Incorrect lengths with self.assertRaises(dataset_validator.ValidationException) as ar: dataset_validator.validate({ "name": "", # Smaller than Min Len "classes": [], "public": False, }) self.assertEqual(six.ensure_text(ar.exception.error), "Dataset name must be between 1 and 100 characters") with self.assertRaises(dataset_validator.ValidationException) as ar: dataset_validator.validate({ "name": "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuv \ wxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghj", # Greater than Max Len "classes": [], "public": False, }) self.assertEqual(six.ensure_text(ar.exception.error), "Dataset name must be between 1 and 100 characters") with self.assertRaises(dataset_validator.ValidationException) as ar: dataset_validator.validate({ "name": "this dataset", "classes": [ { "name": "", # Smaller than Min Len "recordings": [], }, ], "public": False, }) self.assertEqual( six.ensure_text(ar.exception.error), "Length of the `name` field in class number 0 doesn't fit the limits. Class name must be between 1 and 100 characters" ) with self.assertRaises(dataset_validator.ValidationException) as ar: dataset_validator.validate({ "name": "this dataset", "classes": [ { "name": "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl \ mnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghj", #Greater than Max Len "recordings": [], }, ], "public": False, }) self.assertEqual( six.ensure_text(ar.exception.error), "Length of the `name` field in class number 0 doesn't fit the limits. Class name must be between 1 and 100 characters" ) with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "test", "classes": [ { "name": "Not Rock", "why": "Because", # this item shouldn't be there "recordings": [], }, ], "public": False, })
def test_malformed_datasets(self): # Unexpected items with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "i_like": "to test", }) with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "i": "don't", }) with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "Dataset", "surname": "For Testing", # this item shouldn't be there "classes": [ { "name": "Not Rock", "recordings": [], }, ], "public": False, }) with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "Dataset", "classes": [ { "name": "Rock", "why": "Because", # this item shouldn't be there "recordings": [], }, ], "public": True, }) # Missing values with self.assertRaises(dataset_validator.ValidationException): # Dataset name is missing dataset_validator.validate({ "classes": [ { "name": "the one and only", "recordings": [], }, ], "public": False, }) with self.assertRaises(dataset_validator.ValidationException): # List of classes is missing dataset_validator.validate({ "name": "test", "public": False, }) with self.assertRaises(dataset_validator.ValidationException): # Publicity value is missing dataset_validator.validate({ "name": "test", "classes": [], }) with self.assertRaises(dataset_validator.ValidationException): # Class name is missing dataset_validator.validate({ "name": "test", "classes": [ { "recordings": [], }, ], "public": False, }) with self.assertRaises(dataset_validator.ValidationException): # List of recordings in a class is missing dataset_validator.validate({ "name": "test", "classes": [ { "name": "this", }, ], "public": False, }) # Incorrect types with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate("dataset") with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": ["This", "is", "my", "cool", "dataset"], "classes": [], "public": False, }) with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "test", "description": False, "classes": [], "public": False, }) with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "test", "description": "", "classes": None, "public": False, }) with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "test", "description": "", "classes": [], "public": "Nope", }) with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "test", "classes": [ { "name": ("this", "is", "a", "name"), "recordings": [], }, ], "public": False, }) with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "test", "classes": [ "first", "second", ], "public": False, }) with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "test", "classes": [ { "name": "first", "description": False, "recordings": [], }, ], "public": False, }) with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "test", "classes": [ { "name": "first", "recordings": "I don't have any :(", }, ], "public": False, }) with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "test", "classes": [ { "name": "first", "recordings": ["my favourite"], }, ], "public": False, }) # Incorrect lengths with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "", # incorrect "classes": [], "public": False, }) with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "this dataset", "classes": [ { "name": "", # incorrect "recordings": [], }, ], "public": False, }) with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "test", "classes": [ { "name": "Not Rock", "why": "Because", # this item shouldn't be there "recordings": [], }, ], "public": False, })
def test_dataset_incorrect_types(self): # Incorrect types # String, not dict with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate("dataset") # Name should be string with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": ["This", "is", "my", "cool", "dataset"], "classes": [], "public": False, }) # Desc should be string with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "test", "description": False, "classes": [], "public": False, }) # Classes should be list with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "test", "description": "", "classes": None, "public": False, }) # public should be bool with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "test", "description": "", "classes": [], "public": "Nope", }) # class name should be string with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "test", "classes": [ { "name": ("this", "is", "a", "name"), "recordings": [], }, ], "public": False, }) # class elements should be dict with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "test", "classes": [ "first", "second", ], "public": False, }) # Class desc should be string with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "test", "classes": [ { "name": "first", "description": False, "recordings": [], }, ], "public": False, }) # class recordings should be list with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "test", "classes": [ { "name": "first", "recordings": "I don't have any :(", }, ], "public": False, }) # Class recordings should be uuids with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "test", "classes": [ { "name": "first", "recordings": [ "my favourite" ], }, ], "public": False, })
def test_malformed_datasets(self): # Unexpected items with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "i_like": "to test", }) with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "i": "don't", }) with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "Dataset", "surname": "For Testing", # this item shouldn't be there "classes": [ { "name": "Not Rock", "recordings": [], }, ], "public": False, }) with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "Dataset", "classes": [ { "name": "Rock", "why": "Because", # this item shouldn't be there "recordings": [], }, ], "public": True, }) # Missing values with self.assertRaises(dataset_validator.ValidationException): # Dataset name is missing dataset_validator.validate({ "classes": [ { "name": "the one and only", "recordings": [], }, ], "public": False, }) with self.assertRaises(dataset_validator.ValidationException): # List of classes is missing dataset_validator.validate({ "name": "test", "public": False, }) with self.assertRaises(dataset_validator.ValidationException): # Publicity value is missing dataset_validator.validate({ "name": "test", "classes": [], }) with self.assertRaises(dataset_validator.ValidationException): # Class name is missing dataset_validator.validate({ "name": "test", "classes": [ { "recordings": [], }, ], "public": False, }) with self.assertRaises(dataset_validator.ValidationException): # List of recordings in a class is missing dataset_validator.validate({ "name": "test", "classes": [ { "name": "this", }, ], "public": False, }) # Incorrect types with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate("dataset") with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": ["This", "is", "my", "cool", "dataset"], "classes": [], "public": False, }) with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "test", "description": False, "classes": [], "public": False, }) with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "test", "description": "", "classes": None, "public": False, }) with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "test", "description": "", "classes": [], "public": "Nope", }) with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "test", "classes": [ { "name": ("this", "is", "a", "name"), "recordings": [], }, ], "public": False, }) with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "test", "classes": [ "first", "second", ], "public": False, }) with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "test", "classes": [ { "name": "first", "description": False, "recordings": [], }, ], "public": False, }) with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "test", "classes": [ { "name": "first", "recordings": "I don't have any :(", }, ], "public": False, }) with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "test", "classes": [ { "name": "first", "recordings": [ "my favourite" ], }, ], "public": False, }) # Incorrect lengths with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "", # incorrect "classes": [], "public": False, }) with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "this dataset", "classes": [ { "name": "", # incorrect "recordings": [], }, ], "public": False, }) with self.assertRaises(dataset_validator.ValidationException): dataset_validator.validate({ "name": "test", "classes": [ { "name": "Not Rock", "why": "Because", # this item shouldn't be there "recordings": [], }, ], "public": False, })