Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Add multiple labels in backend #101

Merged
merged 28 commits into from
Nov 7, 2022
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
79d5884
Add multilabels for parser
aadarsh-ram Oct 6, 2022
c0097ed
Add multiple labels to api and db functions
aadarsh-ram Oct 6, 2022
6c8bfe4
Wrap functions in class
aadarsh-ram Oct 6, 2022
033c432
Merge branch 'main' into multilabelnew
aadarsh-ram Oct 6, 2022
12ae462
Remove hyphens for imports
aadarsh-ram Oct 6, 2022
71b1970
Merge branch 'multilabelnew' of https://github.com/openfoodfacts/taxo…
aadarsh-ram Oct 6, 2022
6ac6700
Add multilabel to unparser and tests
aadarsh-ram Oct 7, 2022
340db38
Add requested changes
aadarsh-ram Oct 8, 2022
09db6a6
Add prefix test
aadarsh-ram Oct 8, 2022
5aa7c5e
Reformat files acc to tests
aadarsh-ram Oct 8, 2022
f975c38
Reformatted files
aadarsh-ram Oct 8, 2022
00634a4
Merge branch 'main' into multilabelnew
aadarsh-ram Oct 10, 2022
d126c50
build: fix backend Dockerfile
alexgarel Oct 10, 2022
f494001
refactor: black fix
alexgarel Oct 10, 2022
727314e
Merge branch 'main' into multilabelnew
aadarsh-ram Oct 10, 2022
16d3070
refactor: Add p_ label to taxonomy
aadarsh-ram Oct 10, 2022
312d75c
Remove other labels
aadarsh-ram Oct 10, 2022
cd3593a
feat: Add new endpoint for fetching root nodes (#104)
aadarsh-ram Oct 11, 2022
4060662
feat: Add routes for import/export taxonomy (#116)
aadarsh-ram Nov 5, 2022
410d1dd
Resolve conflicts
aadarsh-ram Nov 5, 2022
85056cc
Merge branch 'main' into multilabelnew
aadarsh-ram Nov 5, 2022
239155f
fix: Add source dir in docker
aadarsh-ram Nov 5, 2022
a8d27d0
Merge branch 'multilabelnew' of https://github.com/openfoodfacts/taxo…
aadarsh-ram Nov 5, 2022
2e872f0
Change context for docker
aadarsh-ram Nov 5, 2022
5bbbcc3
Add dockerfile in dev.yml
aadarsh-ram Nov 5, 2022
d64a923
Rollback changes
aadarsh-ram Nov 5, 2022
1651164
fix: Add ./ for path
aadarsh-ram Nov 7, 2022
ba982e1
fix: Add build context in dev.yml
aadarsh-ram Nov 7, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# use windows path separator for compat
COMPOSE_PATH_SEPARATOR=;
COMPOSE_FILE=docker-compose.yml;docker/dev.yml

DOCKER_TAG=dev

# domain name
TAXONOMY_EDITOR_DOMAIN=taxonomy.localhost
# exposition
Expand Down
7 changes: 5 additions & 2 deletions backend/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
FROM python:3.8
WORKDIR /code
COPY ./requirements.txt /code/requirements.txt
COPY backend/requirements.txt /code/requirements.txt
COPY backend/editor /code/editor
COPY parser /parser
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
COPY ./editor /code/editor
# this is purely cosmetic
RUN ln -s /parser/openfoodfacts_taxonomy_parser /code/openfoodfacts_taxonomy_parser
CMD ["uvicorn", "editor.api:app", "--host", "0.0.0.0", "--port", "80"]
154 changes: 86 additions & 68 deletions backend/editor/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Taxonomy Editor Backend API
"""
# Required imports
#------------------------------------------------------------------------#
#----------------------------------------------------------------------------#
from datetime import datetime

# FastAPI
Expand All @@ -14,10 +14,8 @@

# DB helper imports
from . import graph_db
from .entries import get_all_nodes, get_nodes, get_children, get_parents, get_label, full_text_search
from .entries import update_nodes, update_node_children
from .entries import create_node, add_node_to_end, add_node_to_beginning, delete_node
#------------------------------------------------------------------------#
from .entries import TaxonomyGraph
#----------------------------------------------------------------------------#

app = FastAPI(title="Open Food Facts Taxonomy Editor API")

Expand Down Expand Up @@ -83,128 +81,141 @@ async def pong(response: Response):
pong = datetime.now()
return {"ping": "pong @ %s" % pong}

@app.get("/nodes")
async def findAllNodes(response: Response):
@app.get("/{taxonomy_name}/{branch}/nodes")
async def findAllNodes(response: Response, branch: str, taxonomy_name: str):
"""
Get all nodes within taxonomy
"""
result = get_all_nodes("")
taxonomy = TaxonomyGraph(branch, taxonomy_name)
result = taxonomy.get_all_nodes("")
allNodes = list(result)
return allNodes

@app.get("/entry/{entry}")
async def findOneEntry(response: Response, entry: str):
@app.get("/{taxonomy_name}/{branch}/entry/{entry}")
async def findOneEntry(response: Response, branch: str, taxonomy_name: str, entry: str):
"""
Get entry corresponding to id within taxonomy
"""
result = get_nodes("ENTRY", entry)
taxonomy = TaxonomyGraph(branch, taxonomy_name)
result = taxonomy.get_nodes("ENTRY", entry)
oneEntry = list(result)

check_single(oneEntry)

return oneEntry[0]

@app.get("/entry/{entry}/parents")
async def findOneEntryParents(response: Response, entry: str):
@app.get("/{taxonomy_name}/{branch}/entry/{entry}/parents")
async def findOneEntryParents(response: Response, branch: str, taxonomy_name: str, entry: str):
"""
Get parents for a entry corresponding to id within taxonomy
"""
result = get_parents(entry)
taxonomy = TaxonomyGraph(branch, taxonomy_name)
result = taxonomy.get_parents(entry)
oneEntryParents = list(result)

return oneEntryParents

@app.get("/entry/{entry}/children")
async def findOneEntryChildren(response: Response, entry: str):
@app.get("/{taxonomy_name}/{branch}/entry/{entry}/children")
async def findOneEntryChildren(response: Response, branch: str, taxonomy_name: str, entry: str):
"""
Get children for a entry corresponding to id within taxonomy
"""
result = get_children(entry)
taxonomy = TaxonomyGraph(branch, taxonomy_name)
result = taxonomy.get_children(entry)
oneEntryChildren = list(result)

return oneEntryChildren

@app.get("/entry")
async def findAllEntries(response: Response):
@app.get("/{taxonomy_name}/{branch}/entry")
async def findAllEntries(response: Response, branch: str, taxonomy_name: str):
"""
Get all entries within taxonomy
"""
result = get_all_nodes("ENTRY")
taxonomy = TaxonomyGraph(branch, taxonomy_name)
result = taxonomy.get_all_nodes("ENTRY")
allEntries = list(result)
return allEntries

@app.get("/synonym/{synonym}")
async def findOneSynonym(response: Response, synonym: str):
@app.get("/{taxonomy_name}/{branch}/synonym/{synonym}")
async def findOneSynonym(response: Response, branch: str, taxonomy_name: str, synonym: str):
"""
Get synonym corresponding to id within taxonomy
"""
result = get_nodes("SYNONYMS", synonym)
taxonomy = TaxonomyGraph(branch, taxonomy_name)
result = taxonomy.get_nodes("SYNONYMS", synonym)
oneSynonym = list(result)

check_single(oneSynonym)

return oneSynonym[0]

@app.get("/synonym")
async def findAllSynonyms(response: Response):
@app.get("/{taxonomy_name}/{branch}/synonym")
async def findAllSynonyms(response: Response, branch: str, taxonomy_name: str):
"""
Get all synonyms within taxonomy
"""
result = get_all_nodes("SYNONYMS")
taxonomy = TaxonomyGraph(branch, taxonomy_name)
result = taxonomy.get_all_nodes("SYNONYMS")
allSyononyms = list(result)
return allSyononyms

@app.get("/stopword/{stopword}")
async def findOneStopword(response: Response, stopword: str):
@app.get("/{taxonomy_name}/{branch}/stopword/{stopword}")
async def findOneStopword(response: Response, branch: str, taxonomy_name: str, stopword: str):
"""
Get stopword corresponding to id within taxonomy
"""
result = get_nodes("STOPWORDS", stopword)
taxonomy = TaxonomyGraph(branch, taxonomy_name)
result = taxonomy.get_nodes("STOPWORDS", stopword)
oneStopword = list(result)

check_single(oneStopword)

return oneStopword[0]

@app.get("/stopword")
async def findAllStopwords(response: Response):
@app.get("/{taxonomy_name}/{branch}/stopword")
async def findAllStopwords(response: Response, branch: str, taxonomy_name: str):
"""
Get all stopwords within taxonomy
"""
result = get_all_nodes("STOPWORDS")
taxonomy = TaxonomyGraph(branch, taxonomy_name)
result = taxonomy.get_all_nodes("STOPWORDS")
allStopwords = list(result)
return allStopwords

@app.get("/header")
async def findHeader(response: Response):
@app.get("/{taxonomy_name}/{branch}/header")
async def findHeader(response: Response, branch: str, taxonomy_name: str):
"""
Get __header__ within taxonomy
"""
result = get_nodes("TEXT", "__header__")
taxonomy = TaxonomyGraph(branch, taxonomy_name)
result = taxonomy.get_nodes("TEXT", "__header__")
header = list(result)
return header[0]

@app.get("/footer")
async def findFooter(response: Response):
@app.get("/{taxonomy_name}/{branch}/footer")
async def findFooter(response: Response, branch: str, taxonomy_name: str):
"""
Get __footer__ within taxonomy
"""
result = get_nodes("TEXT", "__footer__")
taxonomy = TaxonomyGraph(branch, taxonomy_name)
result = taxonomy.get_nodes("TEXT", "__footer__")
footer = list(result)
return footer[0]

@app.get("/search")
async def searchNode(response: Response, query: str):
result = full_text_search(query)
@app.get("/{taxonomy_name}/{branch}/search")
async def searchNode(response: Response, branch: str, taxonomy_name: str, query: str):
taxonomy = TaxonomyGraph(branch, taxonomy_name)
result = taxonomy.full_text_search(query)
return result

# Post methods

@app.post("/nodes")
async def createNode(request: Request):
@app.post("/{taxonomy_name}/{branch}/nodes")
async def createNode(request: Request, branch: str, taxonomy_name: str):
"""
Creating a new node in a taxonomy
"""
taxonomy = TaxonomyGraph(branch, taxonomy_name)
incomingData = await request.json()
id = incomingData["id"]
main_language = incomingData["main_language"]
Expand All @@ -213,87 +224,94 @@ async def createNode(request: Request):
if (main_language == None):
raise HTTPException(status_code=400, detail="Invalid main language code")

create_node(get_label(id), id, main_language)
if (get_label(id) == "ENTRY"):
add_node_to_end(get_label(id), id)
taxonomy.create_node(taxonomy.get_label(id), id, main_language)
if (taxonomy.get_label(id) == "ENTRY"):
taxonomy.add_node_to_end(taxonomy.get_label(id), id)
else:
add_node_to_beginning(get_label(id), id)
taxonomy.add_node_to_beginning(taxonomy.get_label(id), id)

@app.post("/entry/{entry}")
async def editEntry(request: Request, entry: str):
@app.post("/{taxonomy_name}/{branch}/entry/{entry}")
async def editEntry(request: Request, branch: str, taxonomy_name: str, entry: str):
"""
Editing an entry in a taxonomy.
New key-value pairs can be added, old key-value pairs can be updated.
URL will be of format '/entry/<id>'
"""
taxonomy = TaxonomyGraph(branch, taxonomy_name)
incomingData = await request.json()
result = update_nodes("ENTRY", entry, incomingData)
result = taxonomy.update_nodes("ENTRY", entry, incomingData)
updatedEntry = list(result)
return updatedEntry

@app.post("/entry/{entry}/children")
async def editEntryChildren(request: Request, entry: str):
@app.post("/{taxonomy_name}/{branch}/entry/{entry}/children")
async def editEntryChildren(request: Request, branch: str, taxonomy_name: str, entry: str):
"""
Editing an entry's children in a taxonomy.
New children can be added, old children can be removed.
URL will be of format '/entry/<id>/children'
"""
taxonomy = TaxonomyGraph(branch, taxonomy_name)
incomingData = await request.json()
result = update_node_children(entry, incomingData)
result = taxonomy.update_node_children(entry, incomingData)
updatedChildren = list(result)
return updatedChildren

@app.post("/synonym/{synonym}")
async def editSynonyms(request: Request, synonym: str):
@app.post("/{taxonomy_name}/{branch}/synonym/{synonym}")
async def editSynonyms(request: Request, branch: str, taxonomy_name: str, synonym: str):
"""
Editing a synonym in a taxonomy.
New key-value pairs can be added, old key-value pairs can be updated.
URL will be of format '/synonym/<id>'
"""
taxonomy = TaxonomyGraph(branch, taxonomy_name)
incomingData = await request.json()
result = update_nodes("SYNONYMS", synonym, incomingData)
result = taxonomy.update_nodes("SYNONYMS", synonym, incomingData)
updatedSynonym = list(result)
return updatedSynonym

@app.post("/stopword/{stopword}")
async def editStopwords(request: Request, stopword: str):
@app.post("/{taxonomy_name}/{branch}/stopword/{stopword}")
async def editStopwords(request: Request, branch: str, taxonomy_name: str, stopword: str):
"""
Editing a stopword in a taxonomy.
New key-value pairs can be added, old key-value pairs can be updated.
URL will be of format '/stopword/<id>'
"""
taxonomy = TaxonomyGraph(branch, taxonomy_name)
incomingData = await request.json()
result = update_nodes("STOPWORDS", stopword, incomingData)
result = taxonomy.update_nodes("STOPWORDS", stopword, incomingData)
updatedStopword = list(result)
return updatedStopword

@app.post("/header")
async def editHeader(incomingData: Header):
@app.post("/{taxonomy_name}/{branch}/header")
async def editHeader(incomingData: Header, branch: str, taxonomy_name: str):
"""
Editing the __header__ in a taxonomy.
"""
taxonomy = TaxonomyGraph(branch, taxonomy_name)
convertedData = incomingData.dict()
result = update_nodes("TEXT", "__header__", convertedData)
result = taxonomy.update_nodes("TEXT", "__header__", convertedData)
updatedHeader = list(result)
return updatedHeader

@app.post("/footer")
async def editFooter(incomingData: Footer):
@app.post("/{taxonomy_name}/{branch}/footer")
async def editFooter(incomingData: Footer, branch: str, taxonomy_name: str):
"""
Editing the __footer__ in a taxonomy.
"""
taxonomy = TaxonomyGraph(branch, taxonomy_name)
convertedData = incomingData.dict()
result = update_nodes("TEXT", "__footer__", convertedData)
result = taxonomy.update_nodes("TEXT", "__footer__", convertedData)
updatedFooter = list(result)
return updatedFooter

# Delete methods

@app.delete("/nodes")
async def deleteNode(request: Request):
@app.delete("/{taxonomy_name}/{branch}/nodes")
async def deleteNode(request: Request, branch: str, taxonomy_name: str):
"""
Deleting given node from a taxonomy
"""
taxonomy = TaxonomyGraph(branch, taxonomy_name)
incomingData = await request.json()
id = incomingData["id"]
delete_node(get_label(id), id)
taxonomy.delete_node(taxonomy.get_label(id), id)
Loading