mirror of
https://github.com/ycd/universities.git
synced 2026-03-13 09:14:01 +08:00
Rewrite.
This commit is contained in:
@@ -1,12 +1,11 @@
|
|||||||
language: python
|
language: python
|
||||||
python:
|
python:
|
||||||
- "3.7"
|
- "3.7"
|
||||||
- "3.8"
|
- "3.8"
|
||||||
services:
|
services:
|
||||||
- postgresql
|
- postgresql
|
||||||
install:
|
install:
|
||||||
- pip install -r requirements.txt
|
- pip install -r requirements.txt
|
||||||
script:
|
script:
|
||||||
- cd tests
|
- cd app/tests
|
||||||
- pytest test_main.py
|
- pytest test_main.py
|
||||||
|
|
||||||
|
|||||||
27
app/db/database.py
Normal file
27
app/db/database.py
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import sqlalchemy
|
||||||
|
from sqlalchemy import create_engine
|
||||||
|
import databases
|
||||||
|
|
||||||
|
|
||||||
|
## Postgres Database
|
||||||
|
DATABASE_URL = "postgresql://yagu:yagu123@localhost:5432/universities"
|
||||||
|
# DATABASE_URL = os.environ.get("TRAVIS")
|
||||||
|
database = databases.Database(DATABASE_URL)
|
||||||
|
metadata = sqlalchemy.MetaData()
|
||||||
|
|
||||||
|
|
||||||
|
# SQLAlchemy database model
|
||||||
|
universities = sqlalchemy.Table(
|
||||||
|
"universities",
|
||||||
|
metadata,
|
||||||
|
sqlalchemy.Column("name", sqlalchemy.String, primary_key=True),
|
||||||
|
sqlalchemy.Column("alpha_two_code", sqlalchemy.String),
|
||||||
|
sqlalchemy.Column("country", sqlalchemy.String),
|
||||||
|
sqlalchemy.Column("web_pages", sqlalchemy.ARRAY(sqlalchemy.String)),
|
||||||
|
sqlalchemy.Column("domains", sqlalchemy.ARRAY(sqlalchemy.String)),
|
||||||
|
sqlalchemy.Column("state_province", sqlalchemy.String),
|
||||||
|
)
|
||||||
|
|
||||||
|
engine = sqlalchemy.create_engine(DATABASE_URL)
|
||||||
|
|
||||||
|
metadata.create_all(engine)
|
||||||
113
app/main.py
113
app/main.py
@@ -1,70 +1,31 @@
|
|||||||
import sqlalchemy
|
|
||||||
from sqlalchemy import and_, literal
|
|
||||||
from sqlalchemy import create_engine
|
|
||||||
from sqlalchemy.ext.declarative import declarative_base
|
|
||||||
from sqlalchemy.dialects.postgresql import insert
|
|
||||||
import databases
|
|
||||||
import psycopg2
|
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
from fastapi_utils.tasks import repeat_every
|
from fastapi.responses import RedirectResponse, ORJSONResponse
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
|
from app.db.database import universities, database
|
||||||
|
from fastapi_utils.tasks import repeat_every
|
||||||
import requests
|
import requests
|
||||||
from asyncpg.exceptions import UniqueViolationError
|
from asyncpg.exceptions import UniqueViolationError
|
||||||
import os
|
|
||||||
|
|
||||||
|
|
||||||
## Postgres Database
|
|
||||||
# DATABASE_URL = "postgresql://user:password@host:5432/universities"
|
|
||||||
DATABASE_URL = os.environ.get("TRAVIS")
|
|
||||||
database = databases.Database(DATABASE_URL)
|
|
||||||
metadata = sqlalchemy.MetaData()
|
|
||||||
|
|
||||||
|
|
||||||
tags_metadata = [
|
tags_metadata = [
|
||||||
{
|
{"name": "Search", "description": ""},
|
||||||
"name": "Search",
|
|
||||||
"description": ""
|
|
||||||
},
|
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
#SQLAlchemy database model
|
|
||||||
universities = sqlalchemy.Table(
|
|
||||||
"universities",
|
|
||||||
metadata,
|
|
||||||
sqlalchemy.Column("name" , sqlalchemy.String, primary_key=True),
|
|
||||||
sqlalchemy.Column("alpha_two_code", sqlalchemy.String),
|
|
||||||
sqlalchemy.Column("country" , sqlalchemy.String),
|
|
||||||
sqlalchemy.Column("web_pages" , sqlalchemy.ARRAY(sqlalchemy.String)),
|
|
||||||
sqlalchemy.Column("domains" , sqlalchemy.ARRAY(sqlalchemy.String)),
|
|
||||||
sqlalchemy.Column("state_province", sqlalchemy.String),
|
|
||||||
)
|
|
||||||
|
|
||||||
engine = sqlalchemy.create_engine(
|
|
||||||
DATABASE_URL
|
|
||||||
)
|
|
||||||
|
|
||||||
metadata.create_all(engine)
|
|
||||||
|
|
||||||
|
|
||||||
# FastAPI
|
|
||||||
app = FastAPI(
|
app = FastAPI(
|
||||||
title="Universities API",
|
title="Universities API",
|
||||||
openapi_tags=tags_metadata,
|
openapi_tags=tags_metadata,
|
||||||
|
default_response_class=ORJSONResponse,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# **Database Connection**
|
|
||||||
@app.on_event("startup")
|
@app.on_event("startup")
|
||||||
async def startup():
|
async def startup():
|
||||||
await database.connect()
|
await database.connect()
|
||||||
|
|
||||||
|
|
||||||
@app.on_event("shutdown")
|
@app.on_event("shutdown")
|
||||||
async def shutdown():
|
async def shutdown():
|
||||||
await database.disconnect()
|
await database.disconnect()
|
||||||
|
|
||||||
|
|
||||||
@repeat_every(seconds=86400)
|
@repeat_every(seconds=86400)
|
||||||
@@ -73,17 +34,19 @@ async def update_database():
|
|||||||
"""
|
"""
|
||||||
Asynchronous database updater, runs itself in 86400 seconds | 1 day
|
Asynchronous database updater, runs itself in 86400 seconds | 1 day
|
||||||
"""
|
"""
|
||||||
r = requests.get("https://raw.githubusercontent.com/Hipo/university-domains-list/master/world_universities_and_domains.json")
|
r = requests.get(
|
||||||
|
"https://raw.githubusercontent.com/Hipo/university-domains-list/master/world_universities_and_domains.json"
|
||||||
|
)
|
||||||
data = r.json()
|
data = r.json()
|
||||||
|
|
||||||
for i in data:
|
for i in data:
|
||||||
query = universities.insert().values(
|
query = universities.insert().values(
|
||||||
country = i["country"],
|
country=i["country"],
|
||||||
name = i["name"],
|
name=i["name"],
|
||||||
web_pages = i["web_pages"],
|
web_pages=i["web_pages"],
|
||||||
alpha_two_code = i["alpha_two_code"],
|
alpha_two_code=i["alpha_two_code"],
|
||||||
state_province = i["state-province"],
|
state_province=i["state-province"],
|
||||||
domains = i["domains"],
|
domains=i["domains"],
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -91,34 +54,56 @@ async def update_database():
|
|||||||
except UniqueViolationError:
|
except UniqueViolationError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@app.get("/search", tags=["Search"])
|
@app.get("/search", tags=["Search"])
|
||||||
async def search(country: Optional[str] = None, name: Optional[str] = None, alpha_two_code: Optional[str] = None, domain: Optional[str] = None) :
|
async def search(
|
||||||
|
country: Optional[str] = None,
|
||||||
|
name: Optional[str] = None,
|
||||||
|
alpha_two_code: Optional[str] = None,
|
||||||
|
domain: Optional[str] = None,
|
||||||
|
):
|
||||||
|
|
||||||
if country and name:
|
if country and name:
|
||||||
query = "SELECT * FROM universities WHERE country ILIKE '%"+country+"%' AND name ILIKE '%"+name+"%'"
|
query = (
|
||||||
|
"SELECT * FROM universities WHERE country ILIKE '%"
|
||||||
|
+ country
|
||||||
|
+ "%' AND name ILIKE '%"
|
||||||
|
+ name
|
||||||
|
+ "%'"
|
||||||
|
)
|
||||||
return await database.fetch_all(query)
|
return await database.fetch_all(query)
|
||||||
|
|
||||||
elif alpha_two_code and name:
|
elif alpha_two_code and name:
|
||||||
query = "SELECT * FROM universities WHERE alpha_two_code ILIKE '%"+alpha_two_code+"%' AND name ILIKE '%"+name+"%'"
|
query = (
|
||||||
|
"SELECT * FROM universities WHERE alpha_two_code ILIKE '%"
|
||||||
|
+ alpha_two_code
|
||||||
|
+ "%' AND name ILIKE '%"
|
||||||
|
+ name
|
||||||
|
+ "%'"
|
||||||
|
)
|
||||||
return await database.fetch_all(query)
|
return await database.fetch_all(query)
|
||||||
|
|
||||||
elif country:
|
elif country:
|
||||||
query = "SELECT * FROM universities WHERE country ILIKE '%"+country+"%'"
|
query = "SELECT * FROM universities WHERE country ILIKE '%" + country + "%'"
|
||||||
return await database.fetch_all(query)
|
return await database.fetch_all(query)
|
||||||
|
|
||||||
elif name:
|
elif name:
|
||||||
query = "SELECT * FROM universities WHERE name ILIKE '%"+name+"%'"
|
query = "SELECT * FROM universities WHERE name ILIKE '%" + name + "%'"
|
||||||
return await database.fetch_all(query)
|
return await database.fetch_all(query)
|
||||||
|
|
||||||
elif alpha_two_code:
|
elif alpha_two_code:
|
||||||
query = "SELECT * FROM universities WHERE alpha_two_code ILIKE '%"+alpha_two_code+"%'"
|
query = (
|
||||||
|
"SELECT * FROM universities WHERE alpha_two_code ILIKE '%"
|
||||||
|
+ alpha_two_code
|
||||||
|
+ "%'"
|
||||||
|
)
|
||||||
return await database.fetch_all(query)
|
return await database.fetch_all(query)
|
||||||
|
|
||||||
elif domain:
|
elif domain:
|
||||||
query = "SELECT * FROM universities WHERE domains && '{"+domain+"}'"
|
query = "SELECT * FROM universities WHERE domains && '{" + domain + "}'"
|
||||||
return await database.fetch_all(query)
|
return await database.fetch_all(query)
|
||||||
|
|
||||||
|
|
||||||
@app.get("/")
|
@app.get("/", include_in_schema=False)
|
||||||
async def index():
|
async def index():
|
||||||
return {"Please go to docs.": "universitiesapi.herokuapp.com/docs"}
|
return RedirectResponse("/docs")
|
||||||
|
|||||||
0
app/tests/__init__.py
Normal file
0
app/tests/__init__.py
Normal file
143
app/tests/test_main.py
Normal file
143
app/tests/test_main.py
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
import pytest
|
||||||
|
from fastapi.testclient import TestClient
|
||||||
|
|
||||||
|
from app.main import app
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="module")
|
||||||
|
def base_client():
|
||||||
|
client = TestClient(app)
|
||||||
|
yield client
|
||||||
|
|
||||||
|
|
||||||
|
def test_home(base_client):
|
||||||
|
"Clients"
|
||||||
|
response = base_client.get("/")
|
||||||
|
|
||||||
|
"Status Code"
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
"Response"
|
||||||
|
assert response.json() == {
|
||||||
|
"Please go to docs.": "universitiesapi.herokuapp.com/docs"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async def test_country_and_name(base_client):
|
||||||
|
"Clients"
|
||||||
|
response_one = base_client.get("/search?country=tur&name=saban")
|
||||||
|
response_two = base_client.get("/search?country=turkey&name=middle")
|
||||||
|
|
||||||
|
"Status Code"
|
||||||
|
assert response_one.status_code == 200
|
||||||
|
assert response_two.status_code == 200
|
||||||
|
|
||||||
|
"Response"
|
||||||
|
assert response_one.json() == [
|
||||||
|
{
|
||||||
|
"name": "Sabanci University",
|
||||||
|
"alpha_two_code": "TR",
|
||||||
|
"country": "Turkey",
|
||||||
|
"web_pages": "http://www.sabanciuniv.edu.tr/http://www.sabanciuniv.edu/",
|
||||||
|
"domains": "sabanciuniv.edu.trsabanciuniv.edu",
|
||||||
|
"state_province": null,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
assert response_two.json() == [
|
||||||
|
{
|
||||||
|
"name": "Middle East Technical University",
|
||||||
|
"alpha_two_code": "TR",
|
||||||
|
"country": "Turkey",
|
||||||
|
"web_pages": "http://www.metu.edu.tr/",
|
||||||
|
"domains": "metu.edu.tr",
|
||||||
|
"state_province": null,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def test_alpha_two_code_and_name(base_client):
|
||||||
|
"Clients"
|
||||||
|
response_one = base_client.get("/search?name=krako&alpha_two_code=pl")
|
||||||
|
response_two = base_client.get("/search?name=harva&alpha_two_code=us")
|
||||||
|
|
||||||
|
"Status Code"
|
||||||
|
assert response_one.status_code == 200
|
||||||
|
assert response_two.status_code == 200
|
||||||
|
|
||||||
|
"Response"
|
||||||
|
assert response_one.json() == [
|
||||||
|
{
|
||||||
|
"name": "Pedagogical University of Krakow",
|
||||||
|
"alpha_two_code": "PL",
|
||||||
|
"country": "Poland",
|
||||||
|
"web_pages": "http://www.wsp.krakow.pl/",
|
||||||
|
"domains": "wsp.krakow.pl",
|
||||||
|
"state_province": null,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
assert response_two.json() == [
|
||||||
|
{
|
||||||
|
"name": "Harvard University",
|
||||||
|
"alpha_two_code": "US",
|
||||||
|
"country": "United States",
|
||||||
|
"web_pages": "http://www.harvard.edu/",
|
||||||
|
"domains": "harvard.edu",
|
||||||
|
"state_province": null,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def test_country(base_client):
|
||||||
|
"Clients"
|
||||||
|
response_one = base_client.get("/search?country=United States")
|
||||||
|
response_two = base_client.get("/search?country=russia")
|
||||||
|
|
||||||
|
"Status Code"
|
||||||
|
assert response_one.status_code == 200
|
||||||
|
assert response_two.status_code == 200
|
||||||
|
|
||||||
|
"Response"
|
||||||
|
response_one_body = response_one.json()
|
||||||
|
response_two_body = response_two.json()
|
||||||
|
response_one_body[0]["country"] == "United States"
|
||||||
|
response_two_body[0]["country"] == "Russian Federation"
|
||||||
|
|
||||||
|
|
||||||
|
def test_name(base_client):
|
||||||
|
"Clients"
|
||||||
|
response_one = base_client.get("/search?name=University of California")
|
||||||
|
response_two = base_client.get("/search?name=Stanfo")
|
||||||
|
|
||||||
|
"Status Code"
|
||||||
|
assert response_one.status_code == 200
|
||||||
|
assert response_two.status_code == 200
|
||||||
|
|
||||||
|
"Response"
|
||||||
|
response_one_body = response_one.json()
|
||||||
|
response_two_body = response_two.json()
|
||||||
|
response_one_body[0]["name"] == "University of California, Berkeley"
|
||||||
|
response_two_body[0]["name"] == "Stanford University"
|
||||||
|
|
||||||
|
|
||||||
|
def test_alpha_two_code(base_client):
|
||||||
|
"Clients"
|
||||||
|
response_one = base_client.get("/search?alpha_two_code=fr")
|
||||||
|
response_two = base_client.get("/search?alpha_two_code=de")
|
||||||
|
response_three = base_client.get("/search?alpha_two_code=gr")
|
||||||
|
response_four = base_client.get("/search?alpha_two_code=il")
|
||||||
|
|
||||||
|
"Status Code"
|
||||||
|
assert response_one.status_code == 200
|
||||||
|
assert response_two.status_code == 200
|
||||||
|
assert response_three.status_code == 200
|
||||||
|
assert response_four.status_code == 200
|
||||||
|
|
||||||
|
"Response"
|
||||||
|
response_one_body = response_one.json()
|
||||||
|
response_two_body = response_two.json()
|
||||||
|
response_three_body = response_three.json()
|
||||||
|
response_four_body = response_four.json()
|
||||||
|
response_one_body[0]["alpha_two_code"] == "France"
|
||||||
|
response_two_body[0]["alpha_two_code"] == "Deutschland"
|
||||||
|
response_three_body[0]["alpha_two_code"] == "Greece"
|
||||||
|
response_four_body[0]["alpha_two_code"] == "Isreal"
|
||||||
@@ -1,136 +0,0 @@
|
|||||||
from fastapi.testclient import TestClient
|
|
||||||
|
|
||||||
from app.main import app
|
|
||||||
|
|
||||||
client = TestClient(app)
|
|
||||||
|
|
||||||
|
|
||||||
def test_home():
|
|
||||||
"Clients"
|
|
||||||
response = client.get("/")
|
|
||||||
|
|
||||||
"Status Code"
|
|
||||||
assert response.status_code == 200
|
|
||||||
|
|
||||||
"Response"
|
|
||||||
assert response.json() == {"Please go to docs.":"universitiesapi.herokuapp.com/docs"}
|
|
||||||
|
|
||||||
async def test_country_and_name():
|
|
||||||
"Clients"
|
|
||||||
response_one = client.get("/search?country=tur&name=saban")
|
|
||||||
response_two = client.get("/search?country=turkey&name=middle")
|
|
||||||
|
|
||||||
"Status Code"
|
|
||||||
assert response_one.status_code == 200
|
|
||||||
assert response_two.status_code == 200
|
|
||||||
|
|
||||||
"Response"
|
|
||||||
assert response_one.json() == [
|
|
||||||
{
|
|
||||||
"name": "Sabanci University",
|
|
||||||
"alpha_two_code": "TR",
|
|
||||||
"country": "Turkey",
|
|
||||||
"web_pages": "http://www.sabanciuniv.edu.tr/http://www.sabanciuniv.edu/",
|
|
||||||
"domains": "sabanciuniv.edu.trsabanciuniv.edu",
|
|
||||||
"state_province": null
|
|
||||||
}
|
|
||||||
]
|
|
||||||
assert response_two.json() == [
|
|
||||||
{
|
|
||||||
"name": "Middle East Technical University",
|
|
||||||
"alpha_two_code": "TR",
|
|
||||||
"country": "Turkey",
|
|
||||||
"web_pages": "http://www.metu.edu.tr/",
|
|
||||||
"domains": "metu.edu.tr",
|
|
||||||
"state_province": null
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def test_alpha_two_code_and_name():
|
|
||||||
"Clients"
|
|
||||||
response_one = client.get("/search?name=krako&alpha_two_code=pl")
|
|
||||||
response_two = client.get("/search?name=harva&alpha_two_code=us")
|
|
||||||
|
|
||||||
"Status Code"
|
|
||||||
assert response_one.status_code == 200
|
|
||||||
assert response_two.status_code == 200
|
|
||||||
|
|
||||||
"Response"
|
|
||||||
assert response_one.json() == [
|
|
||||||
{
|
|
||||||
"name": "Pedagogical University of Krakow",
|
|
||||||
"alpha_two_code": "PL",
|
|
||||||
"country": "Poland",
|
|
||||||
"web_pages": "http://www.wsp.krakow.pl/",
|
|
||||||
"domains": "wsp.krakow.pl",
|
|
||||||
"state_province": null
|
|
||||||
}
|
|
||||||
]
|
|
||||||
assert response_two.json() == [
|
|
||||||
{
|
|
||||||
"name": "Harvard University",
|
|
||||||
"alpha_two_code": "US",
|
|
||||||
"country": "United States",
|
|
||||||
"web_pages": "http://www.harvard.edu/",
|
|
||||||
"domains": "harvard.edu",
|
|
||||||
"state_province": null
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
def test_country():
|
|
||||||
"Clients"
|
|
||||||
response_one = client.get("/search?country=United States")
|
|
||||||
response_two = client.get("/search?country=russia")
|
|
||||||
|
|
||||||
"Status Code"
|
|
||||||
assert response_one.status_code == 200
|
|
||||||
assert response_two.status_code == 200
|
|
||||||
|
|
||||||
"Response"
|
|
||||||
response_one_body = response_one.json()
|
|
||||||
response_two_body = response_two.json()
|
|
||||||
response_one_body[0]['country'] == "United States"
|
|
||||||
response_two_body[0]['country'] == "Russian Federation"
|
|
||||||
|
|
||||||
|
|
||||||
def test_name():
|
|
||||||
"Clients"
|
|
||||||
response_one = client.get("/search?name=University of California")
|
|
||||||
response_two = client.get("/search?name=Stanfo")
|
|
||||||
|
|
||||||
"Status Code"
|
|
||||||
assert response_one.status_code == 200
|
|
||||||
assert response_two.status_code == 200
|
|
||||||
|
|
||||||
"Response"
|
|
||||||
response_one_body = response_one.json()
|
|
||||||
response_two_body = response_two.json()
|
|
||||||
response_one_body[0]['name'] == "University of California, Berkeley"
|
|
||||||
response_two_body[0]['name'] == "Stanford University"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def test_alpha_two_code():
|
|
||||||
"Clients"
|
|
||||||
response_one = client.get("/search?alpha_two_code=fr")
|
|
||||||
response_two = client.get("/search?alpha_two_code=de")
|
|
||||||
response_three = client.get("/search?alpha_two_code=gr")
|
|
||||||
response_four = client.get("/search?alpha_two_code=il")
|
|
||||||
|
|
||||||
|
|
||||||
"Status Code"
|
|
||||||
assert response_one.status_code == 200
|
|
||||||
assert response_two.status_code == 200
|
|
||||||
assert response_three.status_code == 200
|
|
||||||
assert response_four.status_code == 200
|
|
||||||
|
|
||||||
"Response"
|
|
||||||
response_one_body = response_one.json()
|
|
||||||
response_two_body = response_two.json()
|
|
||||||
response_three_body = response_three.json()
|
|
||||||
response_four_body = response_four.json()
|
|
||||||
response_one_body[0]['alpha_two_code'] == "France"
|
|
||||||
response_two_body[0]['alpha_two_code'] == "Deutschland"
|
|
||||||
response_three_body[0]['alpha_two_code'] == "Greece"
|
|
||||||
response_four_body[0]['alpha_two_code'] == "Isreal"
|
|
||||||
Reference in New Issue
Block a user