forked from HTTP-APIs/hydrus
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcli.py
198 lines (174 loc) · 8.55 KB
/
cli.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, scoped_session
from hydrus.app_factory import app_factory
from hydrus.socketio_factory import create_socket
from hydrus.utils import (set_session, set_doc, set_hydrus_server_url,
set_token, set_api_name, set_authentication,
set_page_size, set_pagination)
from hydrus.data import doc_parse
from hydra_python_core import doc_maker
from hydrus.data.db_models import Base
from hydrus.data.user import add_user
from hydrus.data.exceptions import UserExists
from hydrus.data.stale_records_cleanup import remove_stale_modification_records
from gevent.pywsgi import WSGIServer
from hydra_openapi_parser.openapi_parser import parse
from hydrus.samples.hydra_doc_sample import doc as api_document
from importlib.machinery import SourceFileLoader
from typing import Tuple
import json
import click
import yaml
@click.command()
@click.option("--adduser", "-u", default=tuple([1, "test"]),
help="Adds a new user to the API.", nargs=2, type=(int, str))
@click.option("--api", "-a", default="serverapi",
help="The API name.", type=str)
@click.option("--auth/--no-auth", default=True,
help="Set authentication to True or False.")
@click.option("--dburl", default="sqlite:///database.db",
help="Set database url", type=str)
@click.option("--hydradoc", "-d", default=None,
help="Location to HydraDocumentation (JSON-LD) of server.",
type=str)
@click.option("--port", "-p", default=8080,
help="The port the app is hosted at.", type=int)
@click.option("--pagesize", "-ps", default=10,
help="Maximum size of a page(view)", type=int)
@click.option("--pagination/--no-pagination", default=True,
help="Enable or disable pagination.")
@click.option("--token/--no-token", default=True,
help="Toggle token based user authentication.")
@click.option("--serverurl", default="http://localhost",
help="Set server url", type=str)
@click.option("--stale_records_removal_interval", default=900,
help="Interval period between removal of stale modification records.",
type=int)
@click.argument("serve", required=True)
def startserver(adduser: Tuple, api: str, auth: bool, dburl: str, pagination: bool,
hydradoc: str, port: int, pagesize: int, serverurl: str, token: bool,
stale_records_removal_interval: int, serve: None) -> None:
"""
Python Hydrus CLI
:param openapi: : Sets the link to the Open Api Doc file.
:param adduser <tuple> : Contains the user credentials.
:param api <str> : Sets the API name for the server.
:param auth <bool> : Toggles the authentication.
:param dburl <str> : Sets the database URL.
:param hydradoc <str> : Sets the link to the HydraDoc file
(Supported formats - [.py, .jsonld, .yaml])
:param port <int> : Sets the API server port.
:param serverurl <str> : Sets the API server url.
:param token <bool> : Toggle token based user auth.
:param serve : Starts up the server.
:return : None.
Raises:
Error: If `hydradoc` is not of a supported format[.py, .jsonld, .yaml].
"""
# The database connection URL
# See http://docs.sqlalchemy.org/en/rel_1_0/core/engines.html for more info
# DB_URL = 'sqlite:///database.db'
DB_URL = dburl
# Define the server URL, this is what will be displayed on the Doc
HYDRUS_SERVER_URL = "{}:{}/".format(serverurl, str(port))
# The name of the API or the EntryPoint, the api will be at
# http://localhost/<API_NAME>
API_NAME = api
click.echo("Setting up the database")
# Create a connection to the database you want to use
engine = create_engine(DB_URL, connect_args={'check_same_thread': False})
Base.metadata.drop_all(engine)
click.echo("Creating models")
# Add the required Models to the database
Base.metadata.create_all(engine)
# Define the Hydra API Documentation
# NOTE: You can use your own API Documentation and create a HydraDoc object
# using doc_maker or you may create your own HydraDoc Documentation using
# doc_writer [see hydra_python_core/doc_writer_sample]
click.echo("Creating the API Documentation")
if hydradoc:
# Getting hydradoc format
# Currently supported formats [.jsonld, .py, .yaml]
try:
hydradoc_format = hydradoc.split(".")[-1]
if hydradoc_format == 'jsonld':
with open(hydradoc, 'r') as f:
doc = json.load(f)
elif hydradoc_format == 'py':
doc = SourceFileLoader(
"doc", hydradoc).load_module().doc
elif hydradoc_format == 'yaml':
with open(hydradoc, 'r') as stream:
doc = parse(yaml.load(stream))
else:
raise("Error - hydradoc format not supported.")
click.echo("Using %s as hydradoc" % hydradoc)
apidoc = doc_maker.create_doc(doc,
HYDRUS_SERVER_URL, API_NAME)
except BaseException:
click.echo("Problem parsing specified hydradoc file, "
"using sample hydradoc as default.")
apidoc = doc_maker.create_doc(api_document,
HYDRUS_SERVER_URL, API_NAME)
else:
click.echo("No hydradoc specified, using sample hydradoc as default.\n"
"For creating api documentation see this "
"https://www.hydraecosystem.org/01-Usage.html#newdoc\n"
"You can find the example used in hydrus/samples/hydra_doc_sample.py")
apidoc = doc_maker.create_doc(
api_document, HYDRUS_SERVER_URL, API_NAME)
# Start a session with the DB and create all classes needed by the APIDoc
session = scoped_session(sessionmaker(bind=engine))
click.echo("Adding Classes and Properties")
# Get all the classes from the doc
# You can also pass dictionary defined in
# hydra_python_core/doc_writer_sample_output.py
classes = doc_parse.get_classes(apidoc.generate())
# Get all the properties from the classes
properties = doc_parse.get_all_properties(classes)
# Insert them into the database
doc_parse.insert_classes(classes, session)
doc_parse.insert_properties(properties, session)
# Add authorized users and pass if they already exist
click.echo("Adding authorized users")
try:
add_user(id_=adduser[0], paraphrase=adduser[1], session=session)
except UserExists:
pass
# Insert them into the database
doc_parse.insert_classes(classes, session)
doc_parse.insert_properties(properties, session)
click.echo("Creating the application")
# Create a Hydrus app with the API name you want, default will be "api"
app = app_factory(API_NAME)
# Set the name of the API
# Create a socket for the app
socketio = create_socket(app, session)
click.echo("Starting the application")
with set_authentication(app, auth):
# Use authentication for all requests
with set_token(app, token):
with set_api_name(app, api):
# Set the API Documentation
with set_doc(app, apidoc):
# Set HYDRUS_SERVER_URL
with set_hydrus_server_url(app, HYDRUS_SERVER_URL):
# Set the Database session
with set_session(app, session):
# Enable/disable pagination
with set_pagination(app, pagination):
# Set page size of a collection view
with set_page_size(app, pagesize):
# Run a thread to remove stale modification records at some
# interval of time.
remove_stale_modification_records(
session, stale_records_removal_interval)
# Start the hydrus app
socketio.run(app, port=port)
click.echo("Server running at:")
click.echo(
"{}{}".format(
HYDRUS_SERVER_URL,
API_NAME))
if __name__ == "__main__":
startserver()