Implemented Topic API and tests

Added (Artist) Topic POST and DELETE calls as well as tests for them. The tests do not include Artist-to-Topic assignment.
master
Peery 2 years ago
parent 245c8737d1
commit 81b069b0f4

@ -6,7 +6,7 @@ import sqlalchemy.orm as db
import sqlalchemy import sqlalchemy
from sqlalchemy.orm import declarative_base, relationship, load_only from sqlalchemy.orm import declarative_base, relationship, load_only
from database.models import Art, ArtnoID, Artist, Presence, TagCategory, TagCategorynoID, TagNoID, Tag from database.models import Art, ArtnoID, Artist, Presence, TagCategory, TagCategorynoID, TagNoID, Tag, Topic, TopicNoId
# TODO read sensitive data from environment file or similar # TODO read sensitive data from environment file or similar
SQLALCHEMY_DATABASE_URL = "postgresql://artnet_editor:G606Rm9sFEXe6wfTLxVu@[::1]/test_artnet" SQLALCHEMY_DATABASE_URL = "postgresql://artnet_editor:G606Rm9sFEXe6wfTLxVu@[::1]/test_artnet"
@ -361,6 +361,9 @@ class Database:
# Topic # Topic
def get_topic_list(self):
return self.__get_db().query(DBTopic).all() # TODO fix StackOverflow
def get_topic_by_id(self, id: int) -> DBTopic: def get_topic_by_id(self, id: int) -> DBTopic:
result = self.__get_db().query(DBTopic).filter(DBTopic.id == id).first() result = self.__get_db().query(DBTopic).filter(DBTopic.id == id).first()
return result return result
@ -369,10 +372,37 @@ class Database:
result = self.__get_db().query(DBTopic).filter(func.lower(DBTopic.name) == name.lower()).first() result = self.__get_db().query(DBTopic).filter(func.lower(DBTopic.name) == name.lower()).first()
return result return result
def update_topic(self, name: str, description: str): def create_topic_by_model(self, topic: TopicNoId):
raise NotImplementedError if not isinstance(topic.name, str) and len(topic.name) > 2:
raise ValueError("Topic name must be at least 2 letters long!")
def delete_topic(self, name: str): if self.get_topic_by_name(topic.name) is not None:
raise ValueError(f"Topic name must be unique! '{topic.name}' already exists!")
db_topic = DBTopic(name=topic.name, description=topic.description)
db = self.__get_db()
db.add(db_topic)
db.commit()
return db_topic
def update_topic_by_model(self, topic: Topic):
db_topic = self.get_topic_by_id(topic.id)
db_topic.name = topic.name
db_topic.description = topic.description
self.__get_db().commit()
return db_topic
def delete_topic_by_id(self, id: int):
db_topic = self.get_topic_by_id(id)
self.__get_db().delete(db_topic)
self.__get_db().commit()
def delete_topic_by_name(self, name: str):
raise NotImplementedError raise NotImplementedError
# Artist -> Topic # Artist -> Topic

@ -11,7 +11,7 @@ class TopicNoId(BaseModel):
class Topic(TopicNoId): class Topic(TopicNoId):
topic_id: int id: int
class ArtistNoId(BaseModel): class ArtistNoId(BaseModel):

@ -5,7 +5,7 @@ from typing import List, Tuple
from database.database import Database from database.database import Database
from database.database import DBPresence, DBArt2Presence from database.database import DBPresence, DBArt2Presence
from database.models import Art, ArtnoID, Presence, ArtistNoId, Tag, TagNoID, TagCategory, TagCategorynoID from database.models import Art, ArtnoID, Presence, ArtistNoId, Tag, TagNoID, TagCategory, TagCategorynoID, TopicNoId, Topic
app = FastAPI() app = FastAPI()
db = Database() db = Database()
@ -198,10 +198,10 @@ async def artist(id: int):
async def topic(name: str = None, id: int = None, artist_id: int = None): async def topic(name: str = None, id: int = None, artist_id: int = None):
name = unquote(name) if name is not None else None name = unquote(name) if name is not None else None
print(f"Received GET on /artnet/metadata/topic (name={name}, id={id}, artist_id={artist_id})") print(f"Received GET on /artnet/metadata/topic (name={name}, id={id}, artist_id={artist_id})")
if name is None and id is None and artist_id is None:
raise HTTPException(status_code=406)
result = None result = None
if name is None and id is None and artist_id is None:
result = db.get_topic_list()
if name is not None or id is not None: if name is not None or id is not None:
if id is not None: if id is not None:
result = db.get_topic_by_id(id) result = db.get_topic_by_id(id)
@ -221,6 +221,30 @@ async def topic(name: str = None, id: int = None, artist_id: int = None):
raise HTTPException(status_code=404, detail="Topic was not found!") raise HTTPException(status_code=404, detail="Topic was not found!")
@app.post("/artnet/metadata/topic")
async def topic(topic: TopicNoId, id: int = None):
print(f"Received POST on /artnet/metadata/topic (id={id}) body: topic={topic}")
if id is None: # creating new topic
try:
new_id = db.create_topic_by_model(topic).id
return {"id": new_id}
except ValueError as e:
raise HTTPException(status_code=406, detail=str(e))
else: # updating topic
topic_ = Topic(name=topic.name, description=topic.description, id=id)
db.update_topic_by_model(topic_)
@app.delete("/artnet/metadata/topic")
async def topic(id: int):
print(f"Received DELETE on /artnet/metadata/topic (id={id})")
if db.get_topic_by_id(id) is None:
raise HTTPException(status_code=404, detail="No topic with this id could be found!")
db.delete_topic_by_id(id)
@app.get("/artnet/metadata/tag") @app.get("/artnet/metadata/tag")
async def tag(id: int = None, name: str = None, fuzzy: bool = False, category: int = None): async def tag(id: int = None, name: str = None, fuzzy: bool = False, category: int = None):
name = unquote(name) if name is not None else None name = unquote(name) if name is not None else None

@ -174,7 +174,7 @@ def run_tag_test(url: str, port: int):
print(f"Found {len(list_tags(url, port))} tag entries!") print(f"Found {len(list_tags(url, port))} tag entries!")
print("Deleting the tag entries ...") print("Deleting the tag entries ...")
delete_tag_entries(url, port) # would throw an exception if an error occurred delete_tag_entries(url, port) # would throw an exception if an error occurred
delete_tag_result = True delete_tag_result = False if not len(list_tags(url, port)) == 0 else True
print(f"Found {len(list_tags(url, port))} tag entries!") print(f"Found {len(list_tags(url, port))} tag entries!")
# Clean up # Clean up

@ -0,0 +1,131 @@
import requests
import json
from typing import List, Tuple
from tests.createAPI.create_delete_artist import create_artist_entries, test_artist_entries, delete_artist_entries, \
list_artists
test_topic_entries = [{"name": "topic_name1", "description": "description1", "id": None, "artists": [0, 1]},
{"name": "topic_name2", "description": "description2", "id": None, "artists": [1, 2]}]
def create_topic_entries(url: str, port: int):
"""
Create many topic entries for testing purposes
:param url:
:param port:
:return:
"""
for i in range(len(test_topic_entries)):
r = create_topic(url, port, name=test_topic_entries[i]["name"], desc=test_topic_entries[i]["description"])
if r.status_code != 200:
print(f"Create Topic Entry Test Nr.{i}: failed with {r.status_code} and reason {r.text}")
raise Exception("Create Topic Entry Test: FAILED")
else:
test_topic_entries[i]["id"] = json.loads(r.text)["id"]
def update_topic_entries(url: str, port: int):
for i in range(len(test_topic_entries)):
new_name = test_topic_entries[i]["name"] + "_updated"
new_description = test_topic_entries[i]["description"] + "_updated"
r = update_topic(url, port, id=test_topic_entries[i]["id"], name=new_name, desc=new_description)
if r.status_code != 200:
print(f"Updating Topuc Entry Test Nr.{i}: failed with {r.status_code} and reason {r.text}")
raise Exception("Update Topic Entry Test: FAILED")
topic = get_topic_by_id(url, port, test_topic_entries[i]["id"])
if not topic["name"] == new_name:
print(f"Name is not matching the expected one! "
f"Current: {topic['name']} Expceted: {new_name}")
raise Exception("Update Topic Entry Test: FAILED")
if not topic["description"] == new_description:
print(f"Description is not matching the expected one! "
f"Current: {topic['description']} Expceted: {new_description}")
raise Exception("Update Topic Entry Test: FAILED")
def delete_topic_entries(url: str, port: int):
for i in range(len(test_topic_entries)):
r = delete_topic(url, port, id=test_topic_entries[i]["id"])
if r.status_code != 200:
print(f"Delete Topic Entry Test Nr.{i}: failed with {r.status_code} and reason {r.text}")
raise Exception("Delete Topic Entry Test: FAILED")
def delete_all_topics(url: str, port: int):
topics = list_topics(url, port)
print(f"Removing following topics: {topics}")
for topic in topics:
delete_topic(url, port, id=topic["id"])
def list_topics(url: str, port: int):
r = requests.get(f"http://{url}:{port}/artnet/metadata/topic")
if r.status_code != 200:
raise Exception(f"Failed querying for topics! Status: {r.status_code} Reason: {r.text}")
topics = json.loads(r.text)
return topics
def get_topic_by_id(url: str, port: int, id: str):
r = requests.get(f"http://{url}:{port}/artnet/metadata/topic?id={id}")
if r.status_code != 200:
raise Exception("Failed querying for topic!")
return json.loads(r.text)
def create_topic(url: str, port: int, name: str, desc: str):
r = requests.post(f"http://{url}:{port}/artnet/metadata/topic",
json={"name": name, "description": desc})
return r
def update_topic(url: str, port: int, id: str, name: str = None, desc: str = None):
r = requests.post(f"http://{url}:{port}/artnet/metadata/topic?id={id}",
json={"name": name, "description": desc})
return r
def delete_topic(url: str, port: int, id: str):
r = requests.delete(f"http://{url}:{port}/artnet/metadata/topic?id={id}")
return r
def run_topic_tests(url: str, port: int):
print()
print("----------------")
l = len(list_topics(url, port))
print(f"Starting topic tests with ({l}) topics!")
if l > 0:
print("Deleting leftover topics ...")
delete_all_topics(url, port)
print(f"Creating {len(test_topic_entries)} topic entries for the test ...")
create_topic_entries(url, port)
create_topic_result = False if not len(test_topic_entries) == len(list_topics(url, port)) else True
print(f"Found {len(list_topics(url, port))} topic entries!")
print("Updating topic entries with new data now ...")
update_topic_entries(url, port) # throws exception if not working
update_topic_result = True
print("Finished updating the topic entries.")
print(f"Found {len(list_topics(url, port))} topic entries!")
print(f"Deleting all topic entries ...")
delete_topic_entries(url, port)
delete_topic_result = False if not len(list_topics(url, port)) == 0 else True
print(f"Found {len(list_topics(url, port))} topic entries!")
print("Finished topic tests!")
return create_topic_result, update_topic_result, delete_topic_result
if __name__ == "__main__":
url, port = "127.0.0.1", 8000
run_topic_tests(url, port)

@ -2,7 +2,8 @@ from tests.createAPI.create_delete_art import run_art_test, list_art, delete_art
from tests.createAPI.create_delete_presence import run_presence_test, list_presences from tests.createAPI.create_delete_presence import run_presence_test, list_presences
from tests.createAPI.create_delete_artist import delete_artist_entries, list_artists, run_artist_test from tests.createAPI.create_delete_artist import delete_artist_entries, list_artists, run_artist_test
from tests.createAPI.create_delete_tag_category import delete_category_entries, list_tag_categories, run_tag_category_test from tests.createAPI.create_delete_tag_category import delete_category_entries, list_tag_categories, run_tag_category_test
from tests.createAPI.create_delete_tag import create_tag_entries, list_tags, run_tag_test, delete_tag_entries from tests.createAPI.create_delete_tag import list_tags, run_tag_test, delete_tag_entries
from tests.createAPI.create_delete_topic import list_topics, run_topic_tests, delete_all_topics
from tests.relationAPI.relate_art import run_art_presence_relation_test from tests.relationAPI.relate_art import run_art_presence_relation_test
@ -33,6 +34,7 @@ def run_tests(url: str, port: int):
create_art2presence_result, delete_art2presence_result = run_art_presence_relation_test(url, port) create_art2presence_result, delete_art2presence_result = run_art_presence_relation_test(url, port)
create_category_result, update_category_result, delete_category_result = run_tag_category_test(url, port) create_category_result, update_category_result, delete_category_result = run_tag_category_test(url, port)
create_tag_result, update_tag_result, delete_tag_result = run_tag_test(url, port) create_tag_result, update_tag_result, delete_tag_result = run_tag_test(url, port)
create_topic_result, update_topic_result, delete_topic_result = run_topic_tests(url, port)
print() print()
print("-------- Test Results ---------") print("-------- Test Results ---------")
@ -47,6 +49,9 @@ def run_tests(url: str, port: int):
print(f"Tag Categories: {len(r)}, {r}") print(f"Tag Categories: {len(r)}, {r}")
r = list_tags(url, port) r = list_tags(url, port)
print(f"Tags: {len(r)}, {r}") print(f"Tags: {len(r)}, {r}")
r = list_topics(url, port)
print(f"Topics: {len(r)}, {r}")
print() print()
print("Functions:") print("Functions:")
print(f"Artists: \t\t\t\tCreate: {create_artist_result} \tUpdate: {'N/A'} " print(f"Artists: \t\t\t\tCreate: {create_artist_result} \tUpdate: {'N/A'} "
@ -61,7 +66,8 @@ def run_tests(url: str, port: int):
f"\tDelete: {delete_category_result} \t(Direct)") f"\tDelete: {delete_category_result} \t(Direct)")
print(f"Tag: \t\t\t\t\tCreate: {create_tag_result} \tUpdate: {update_tag_result} " print(f"Tag: \t\t\t\t\tCreate: {create_tag_result} \tUpdate: {update_tag_result} "
f"\tDelete: {delete_tag_result} \t(Direct)") f"\tDelete: {delete_tag_result} \t(Direct)")
print(f"(Artist) Topic: \t\tN/A") print(f"(Artist) Topic: \t\tCreate: {create_topic_result} \tUpdate: {update_topic_result} "
f"\tDelete: {delete_topic_result} \t(Direct)")
print(f"Art Collection: \t\tN/A") print(f"Art Collection: \t\tN/A")
print(f"Art2Art Collection: \tN/A") print(f"Art2Art Collection: \tN/A")
print(f"Artist2Topic: \t\t\tN/A") print(f"Artist2Topic: \t\t\tN/A")

Loading…
Cancel
Save