Skip to content

Commit

Permalink
[REF] update connexion to 3.0.0 (#606)
Browse files Browse the repository at this point in the history
* update connexion to 3.0.0

* fix requirements

* add flask extension to connexion

* use uvicorn workers

* switch openapi to main
  • Loading branch information
jdkent authored Oct 26, 2023
1 parent d59a5c6 commit e424b75
Show file tree
Hide file tree
Showing 23 changed files with 285 additions and 267 deletions.
2 changes: 1 addition & 1 deletion store/docker-compose.dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ services:
neurostore:
expose:
- "8000"
command: /usr/local/bin/gunicorn -w 1 -b :8000 neurostore.core:app --log-level debug --timeout 300 --reload
command: /usr/local/bin/gunicorn -w 1 -b :8000 neurostore.core:connexion_app --worker-class uvicorn.workers.UvicornWorker --log-level debug --timeout 300 --reload
restart: "no"
stdin_open: true # docker run -i
tty: true # docker run -t
Expand Down
2 changes: 1 addition & 1 deletion store/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ services:
- ./:/neurostore
- ${FILE_DIR}:/file-data
- ${ACE_DIR}:/ace
command: /usr/local/bin/gunicorn -w 8 -b :8000 neurostore.core:app --log-level debug --timeout 120
command: /usr/local/bin/gunicorn -w 8 -b :8000 neurostore.core:connexion_app --worker-class uvicorn.workers.UvicornWorker --log-level debug --timeout 120
env_file:
- .env
container_name: neurostore
Expand Down
26 changes: 5 additions & 21 deletions store/neurostore/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,18 @@

from authlib.integrations.flask_client import OAuth
import connexion
from connexion.json_schema import default_handlers as json_schema_handlers
from connexion.resolver import MethodViewResolver
# from connexion.json_schema import default_handlers as json_schema_handlers
from connexion.resolver import MethodResolver
from flask_caching import Cache
from flask_cors import CORS
import prance
import sqltap.wsgi

from .or_json import ORJSONDecoder, ORJSONEncoder
from .database import init_db


connexion_app = connexion.FlaskApp(
__name__, specification_dir="openapi/", debug=os.getenv("DEBUG", False) == "True"
__name__, specification_dir="openapi/"
)

app = connexion_app.app
Expand All @@ -34,29 +33,14 @@

options = {"swagger_ui": True}

# https://github.com/spec-first/connexion/issues/254#issuecomment-1133843523
json_schema_handlers[""] = lambda uri: (
json_schema_handlers["file"](str(connexion_app.specification_dir / uri))
)


# https://github.com/spec-first/connexion/issues/254#issuecomment-504699959
def get_bundled_specs(main_file):
parser = prance.ResolvingParser(
str(main_file.absolute()), lazy=True, backend="openapi-spec-validator"
)
parser.parse()
return parser.specification


openapi_file = Path(os.path.dirname(__file__) + "/openapi/neurostore-openapi.yml")

connexion_app.add_api(
get_bundled_specs(openapi_file),
openapi_file,
base_path="/api",
options=options,
arguments={"title": "NeuroStore API"},
resolver=MethodViewResolver("neurostore.resources"),
resolver=MethodResolver("neurostore.resources"),
strict_validation=os.getenv("DEBUG", False) == "True",
validate_responses=os.getenv("DEBUG", False) == "True",
)
Expand Down
8 changes: 4 additions & 4 deletions store/neurostore/models/auth.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from flask_security import UserMixin, RoleMixin, SQLAlchemyUserDatastore
# from flask_security import UserMixin, RoleMixin, SQLAlchemyUserDatastore


from ..database import db
Expand All @@ -13,14 +13,14 @@
)


class Role(BaseMixin, db.Model, RoleMixin):
class Role(BaseMixin, db.Model):
__tablename__ = "roles"

name = db.Column(db.Text, unique=True)
description = db.Column(db.Text)


class User(BaseMixin, db.Model, UserMixin):
class User(BaseMixin, db.Model):
__tablename__ = "users"
active = db.Column(db.Boolean())
name = db.Column(db.Text, index=True)
Expand All @@ -30,4 +30,4 @@ class User(BaseMixin, db.Model, UserMixin):
)


user_datastore = SQLAlchemyUserDatastore(db, User, Role)
# user_datastore = SQLAlchemyUserDatastore(db, User, Role)
2 changes: 1 addition & 1 deletion store/neurostore/openapi
Submodule openapi updated 1 files
+13 −4 neurostore-openapi.yml
4 changes: 1 addition & 3 deletions store/neurostore/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
aniso8601~=8.1
auth0-python~=3.16
authlib~=0.15
connexion[swagger-ui]~=2.7
connexion[swagger-ui,uvicorn,flask]==3.0.0a7
email-validator~=1.1
flake8~=3.8
flask~=2.0
Expand All @@ -10,7 +10,6 @@ flask-cors~=3.0
flask-dance~=3.2
flask-shell-ipython~=0.4
flask-migrate~=2.5
flask-security~=3.0
flask-sqlalchemy==3.0.2 # fix multiple instance error: https://flask-sqlalchemy.palletsprojects.com/en/3.0.x/changes/#version-3-0-3
gunicorn~=20.0
ipython~=7.19
Expand All @@ -31,4 +30,3 @@ openapi-spec-validator~=0.3
scipy~=1.9
pytest~=7.1
orjson~=3.8
prance
20 changes: 10 additions & 10 deletions store/neurostore/resources/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"""
import re

import connexion
from connexion.context import context
from flask import abort, request, current_app # jsonify
from flask.views import MethodView

Expand Down Expand Up @@ -45,7 +45,7 @@ def create_user():
# user signed up with auth0, but has not made any queries yet...
# should have endpoint to "create user" after sign on with auth0
current_user = User(
external_id=connexion.context["user"], name=profile_info.get("name", "Unknown")
external_id=context["user"], name=profile_info.get("name", "Unknown")
)

return current_user
Expand Down Expand Up @@ -302,11 +302,11 @@ def get(self, id):
record = q.filter_by(id=id).first_or_404()
if self._model is Studyset and args["nested"]:
snapshot = StudysetSnapshot()
return snapshot.dump(record)
return snapshot.dump(record), 200, {"Content-Type": "application/json"}
else:
return self._schema(
context=dict(args),
).dump(record)
).dump(record), 200, {"Content-Type": "application/json"}

def put(self, id):
request_data = self.insert_data(id, request.json)
Expand Down Expand Up @@ -343,12 +343,12 @@ def post_delete(self, record):


LIST_USER_ARGS = {
"search": fields.String(missing=None),
"sort": fields.String(missing="created_at"),
"page": fields.Int(missing=1),
"desc": fields.Boolean(missing=True),
"page_size": fields.Int(missing=20, validate=lambda val: val < 30000),
"user_id": fields.String(missing=None),
"search": fields.String(load_default=None),
"sort": fields.String(load_default="created_at"),
"page": fields.Int(load_default=1),
"desc": fields.Boolean(load_default=True),
"page_size": fields.Int(load_default=20, validate=lambda val: val < 30000),
"user_id": fields.String(load_default=None),
}


Expand Down
28 changes: 14 additions & 14 deletions store/neurostore/resources/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,13 @@
]

LIST_CLONE_ARGS = {
"source_id": fields.String(missing=None),
"source": fields.String(missing=None),
"unique": BooleanOrString(missing=False),
"source_id": fields.String(load_default=None),
"source": fields.String(load_default=None),
"unique": BooleanOrString(load_default=False),
}

LIST_NESTED_ARGS = {
"nested": fields.Boolean(load_default=False, missing=False),
"nested": fields.Boolean(load_default=False),
}


Expand Down Expand Up @@ -91,7 +91,7 @@ def serialize_records(self, records, args):

@view_maker
class AnnotationsView(ObjectView, ListView):
_view_fields = {**LIST_CLONE_ARGS, "studyset_id": fields.String(missing=None)}
_view_fields = {**LIST_CLONE_ARGS, "studyset_id": fields.String(load_default=None)}
_nested = {"annotation_analyses": "AnnotationAnalysesResource"}
_linked = {
"studyset": "StudysetsView",
Expand Down Expand Up @@ -154,10 +154,10 @@ class BaseStudiesView(ObjectView, ListView):
_nested = {"versions": "StudiesView"}

_view_fields = {
"level": fields.String(default="group", missing="group"),
"flat": fields.Boolean(load_default=False, missing=False),
"info": fields.Boolean(load_default=False, missing=False),
"data_type": fields.String(missing=None),
"level": fields.String(dump_default="group", load_default="group"),
"flat": fields.Boolean(load_default=False),
"info": fields.Boolean(load_default=False),
"data_type": fields.String(load_default=None),
}

_multi_search = ("name", "description")
Expand Down Expand Up @@ -272,11 +272,11 @@ def post(self):
class StudiesView(ObjectView, ListView):
_view_fields = {
**{
"data_type": fields.String(missing=None),
"studyset_owner": fields.String(missing=None),
"level": fields.String(default="group", missing="group"),
"flat": fields.Boolean(load_default=False, missing=False),
"info": fields.Boolean(load_default=False, missing=False),
"data_type": fields.String(load_default=None),
"studyset_owner": fields.String(load_default=None),
"level": fields.String(dump_default="group", load_default="group"),
"flat": fields.Boolean(load_default=False),
"info": fields.Boolean(load_default=False),
},
**LIST_NESTED_ARGS,
**LIST_CLONE_ARGS,
Expand Down
6 changes: 3 additions & 3 deletions store/neurostore/resources/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"""
import re

import connexion
from connexion.context import context

from .. import models
from .. import schemas
Expand All @@ -16,10 +16,10 @@ def camel_case_split(str):


def get_current_user():
user = connexion.context.get("user")
user = context.get("user")
if user:
return models.User.query.filter_by(
external_id=connexion.context["user"]
external_id=user
).first()
return None

Expand Down
4 changes: 2 additions & 2 deletions store/neurostore/schemas/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@


class UserSchema(BaseSchema):
name = fields.Str(description="User full name")
external_id = fields.Str(description="External authentication service user ID")
name = fields.Str(metadata={"description": "User full name"})
external_id = fields.Str(metadata={"description": "External authentication service user ID"})

class Meta:
unknown = EXCLUDE
Loading

0 comments on commit e424b75

Please sign in to comment.