33# SPDX-FileCopyrightText: 2021 Pen-Yuan Hsing
44# SPDX-License-Identifier: AGPL-3.0-or-later
55
6+ # Python Standard Library imports
7+ import json
8+ import sys
69
10+ # External library imports
711from fastapi import FastAPI , status
812from fastapi .responses import JSONResponse
913from pydantic import BaseModel , HttpUrl
1014
11- import oshminer .supported_domains
12- class Item (BaseModel ):
13- name : str
14- description : str | None = None
15- price : float
16- tax : float | None = None
15+ # Internal module imports
16+ from oshminer .supported_platforms import supported_domains
17+ from oshminer .errors import exceptions
1718
1819class MiningRequest (BaseModel ):
19- repo_urls : HttpUrl = set ()
20- requested_data : str = set ()
20+ repo_urls : list [ HttpUrl ] = set ()
21+ requested_data : list [ str ] = set ()
2122
2223# Supported data-mining request types. Items in `required_data` must
2324# be from this list.
2425supported_data_requests : list = [
25- "file_types" ,
26- "issue_activity_level" ,
27- "commits_over_time" ,
28- "skill_tags" ,
29- "manufacturing_tags" ,
30- "standards_tags" ,
31- "license" ,
32- "files_editable"
26+ "files_info" ,
27+ "issues_level" ,
28+ "commits_level" ,
29+ "tags" ,
30+ "license"
3331]
3432
3533app = FastAPI (
@@ -45,34 +43,28 @@ class MiningRequest(BaseModel):
4543async def root ():
4644 return {"message" : "Dashboard data-mining backend is on" }
4745
48- @app .post ("/items/" )
49- async def create_item (item : Item ):
50- item_dict : dict = item .dict ()
51- if item .tax :
52- price_with_tax : float = item .price + item .tax
53- item_dict .update ({"price_with_tax" : price_with_tax })
54- return item_dict
55-
56- @app .get ("/items/{item_id}" )
57- async def read_item (item_id : int ):
58- return {"requested item_id" : item_id }
59-
6046@app .post (
6147 "/data/" ,
62- name = "Primary endpoint for retrieving data"
48+ name = "API endpoint" ,
49+ description = "Primary endpoint for requesting data."
6350 )
6451async def mining_request (request_body : MiningRequest ):
6552 #
6653 # Check API client's request body
6754 #
6855
69- # Check if each repository URL is supported
70- print ("Handling request..." )
56+ # Check if each repository URL is supported, and if it is, add it to a list
57+ # of platforms for which we need to construct API queries for
58+ print ("Handling request..." , file = sys .stderr )
59+ platforms : list = [] # Tracks which platforms are in the received request
7160 for url in request_body .repo_urls :
7261 print (f"Checking URL: { url } " )
7362 # See: https://stackoverflow.com/a/6531704/186904
7463 if any (domain in url .host for domain in supported_domains ):
7564 print (f"{ url } domain is supported." )
65+ if url .host .replace ("www." , "" ) not in platforms :
66+ platforms .append (url .host .replace ("www." , "" ))
67+ ## TODO: Also check if the repository actually exists
7668 else :
7769 return JSONResponse (
7870 status_code = status .HTTP_400_BAD_REQUEST ,
@@ -88,75 +80,26 @@ async def mining_request(request_body: MiningRequest):
8880 status_code = status .HTTP_400_BAD_REQUEST ,
8981 content = f"Requested data type not supported: { data_item } "
9082 )
91-
92- #
93- # Process request body
94- #
95-
83+
9684 #
9785 # Prepare API response
9886 #
9987
10088 response : list = []
10189
102- for repo in request_body .repo_urls :
103- repo_dict : dict = {
104- "repo_url" : str (repo ),
105- "requested_data" : dict ()
106- }
107- for data_item in request_body .requested_data :
108- if data_item == "file_types" :
109- repo_dict ["requested_data" ][data_item ] = [
110- ".pdf" ,
111- ".stl" ,
112- ".md" ,
113- ".dxf"
114- ]
115- elif data_item == "skill_tags" :
116- repo_dict ["requested_data" ][data_item ] = [
117- "3D printing" ,
118- "Markdown" ,
119- "PCB design"
120- ]
121- elif data_item == "license" :
122- repo_dict ["requested_data" ][data_item ] = {
123- "SPDX" : "CERN-OHL-S-2.0" ,
124- "permissions" : [
125- "commercial use" ,
126- "modification" ,
127- "distribution" ,
128- "private use"
129- ],
130- "limitations" : [
131- "liability" ,
132- "warranty"
133- ],
134- "conditions" : [
135- "license and copyright notice"
136- ]
137- }
138- else :
139- repo_dict ["requested_data" ][data_item ] = ""
140- response .append (repo_dict )
141- return response
142-
143-
144-
145-
146-
147-
148-
149-
150-
90+ #
91+ # Construct, send API requests, and get results
92+ #
15193
94+ for repo in request_body .repo_urls :
95+ platform = repo .host .replace ("www." , "" )
96+ try :
97+ repo_info : dict = await supported_domains [platform ](repo , request_body .requested_data )
98+ except exceptions .BadRepoError :
99+ return JSONResponse (
100+ status_code = status .HTTP_400_BAD_REQUEST ,
101+ content = f"Error with repository: { repo } "
102+ )
103+ response .append (repo_info )
152104
153- """
154- 1. get `list` of requested info
155- 2. compile API request
156- 2.1 get needed API requests for each item in `list`
157- 2.2 deduplicate into list of what's needed from API
158- 2.3 create API call
159- 2.4 make API call
160- 3. interpret and derive info from API response
161- 4. send our own response
162- """
105+ return response
0 commit comments