Browse Source

Api doc base

pull/84/head
Ruud 13 years ago
parent
commit
7df24643ac
  1. 21
      couchpotato/api.py
  2. 14
      couchpotato/core/_base/_core/main.py
  3. 20
      couchpotato/core/_base/updater/main.py
  4. 13
      couchpotato/core/plugins/browser/main.py
  5. 8
      couchpotato/core/plugins/file/main.py
  6. 24
      couchpotato/core/plugins/log/main.py
  7. 7
      couchpotato/core/plugins/manage/main.py
  8. 34
      couchpotato/core/plugins/movie/main.py
  9. 37
      couchpotato/core/settings/__init__.py
  10. 75
      couchpotato/static/style/api.css
  11. 49
      couchpotato/templates/api.html

21
couchpotato/api.py

@ -1,21 +1,30 @@
from couchpotato.core.helpers.request import jsonified
from flask.blueprints import Blueprint
from flask.templating import render_template
api = Blueprint('api', __name__)
api_docs = {}
api_docs_missing = []
def addApiView(route, func, static = False):
api.add_url_rule(route + ('' if static else '/'), endpoint = route.replace('.', '-') if route else 'index', view_func = func)
def addApiView(route, func, static = False, docs = None):
api.add_url_rule(route + ('' if static else '/'), endpoint = route.replace('.', '::') if route else 'index', view_func = func)
if docs:
api_docs[route[4:] if route[0:4] == 'api.' else route] = docs
else:
api_docs_missing.append(route)
""" Api view """
def index():
from couchpotato import app
from couchpotato import app
routes = []
for route, x in sorted(app.view_functions.iteritems()):
if route[0:4] == 'api.':
routes += [route[4:]]
routes += [route[4:].replace('::', '.')]
return jsonified({'routes': routes})
if api_docs.get(''):
del api_docs['']
del api_docs_missing['']
return render_template('api.html', routes = sorted(routes), api_docs = api_docs, api_docs_missing = sorted(api_docs_missing))
addApiView('', index)
addApiView('default', index)

14
couchpotato/core/_base/_core/main.py

@ -24,9 +24,17 @@ class Core(Plugin):
shutdown_started = False
def __init__(self):
addApiView('app.shutdown', self.shutdown)
addApiView('app.restart', self.restart)
addApiView('app.available', self.available)
addApiView('app.shutdown', self.shutdown, docs = {
'desc': 'Shutdown the app.',
'return': {'type': 'string: shutdown'}
})
addApiView('app.restart', self.restart, docs = {
'desc': 'Restart the app.',
'return': {'type': 'string: restart'}
})
addApiView('app.available', self.available, docs = {
'desc': 'Check if app available.'
})
addEvent('app.crappy_shutdown', self.crappyShutdown)
addEvent('app.crappy_restart', self.crappyRestart)

20
couchpotato/core/_base/updater/main.py

@ -29,9 +29,25 @@ class Updater(Plugin):
addEvent('app.load', self.check)
addApiView('updater.info', self.getInfo)
addApiView('updater.info', self.getInfo, docs = {
'desc': 'Get updater information',
'return': {
'type': 'object',
'example': """
{
'repo_name': "Name of used repository",
'last_check': "last checked for update",
'update_version': "available update version or empty",
'version': current_cp_version
}
"""
}
})
addApiView('updater.update', self.doUpdateView)
addApiView('updater.check', self.checkView)
addApiView('updater.check', self.checkView, docs = {
'desc': 'Check for available update',
'return': {'type': 'see updater.info'}
})
def getInfo(self):

13
couchpotato/core/plugins/browser/main.py

@ -11,7 +11,18 @@ if os.name == 'nt':
class FileBrowser(Plugin):
def __init__(self):
addApiView('directory.list', self.view)
addApiView('directory.list', self.view, docs = {
'desc': 'Return the directory list of a given directory',
'params': {
'path': {'desc': 'The directory to scan'},
'show_hidden': {'desc': 'Also show hidden files'}
},
'return': {'type': 'object', 'example': """{
'is_root': bool, //is top most folder
'empty': bool, //directory is empty
'dirs': array, //directory names
}"""}
})
def getDirectories(self, path = '/', show_hidden = True):

8
couchpotato/core/plugins/file/main.py

@ -19,7 +19,13 @@ class FileManager(Plugin):
addEvent('file.download', self.download)
addEvent('file.types', self.getTypes)
addApiView('file.cache/<path:filename>', self.showCacheFile, static = True)
addApiView('file.cache/<path:filename>', self.showCacheFile, static = True, docs = {
'desc': 'Return a file from the cp_data/cache directory',
'params': {
'filename': {'desc': 'path/filename of the wanted file'}
},
'return': {'type': 'file'}
})
def showCacheFile(self, filename = ''):

24
couchpotato/core/plugins/log/main.py

@ -12,9 +12,27 @@ log = CPLog(__name__)
class Logging(Plugin):
def __init__(self):
addApiView('logging.get', self.get)
addApiView('logging.clear', self.clear)
addApiView('logging.log', self.log)
addApiView('logging.get', self.get, docs = {
'desc': 'Get the full log file by number',
'params': {
'nr': {'desc': 'Number of the log to get.'}
},
'return': {'type': 'object', 'example': """{
'success': True,
'log': string, //Log file
'total': int, //Total log files available
}"""}
})
addApiView('logging.clear', self.clear, docs = {
'desc': 'Remove all the log files'
})
addApiView('logging.log', self.log, docs = {
'desc': 'Get the full log file by number',
'params': {
'type': {'desc': 'Type of logging, default "error"'},
'**kwargs': {'type':'object', 'desc': 'All other params will be printed in the log string.'},
}
})
def get(self):

7
couchpotato/core/plugins/manage/main.py

@ -21,7 +21,12 @@ class Manage(Plugin):
fireEvent('scheduler.interval', identifier = 'manage.update_library', handle = self.updateLibrary, hours = 2)
addEvent('manage.update', self.updateLibrary)
addApiView('manage.update', self.updateLibraryView)
addApiView('manage.update', self.updateLibraryView, docs = {
'desc': 'Update the library by scanning for new movies',
'params': {
'full': {'desc': 'Do a full update or just recently changed/added movies.'},
}
})
if not Env.get('dev'):
addEvent('app.load', self.updateLibrary)

34
couchpotato/core/plugins/movie/main.py

@ -26,9 +26,37 @@ class MoviePlugin(Plugin):
}
def __init__(self):
addApiView('movie.search', self.search)
addApiView('movie.list', self.listView)
addApiView('movie.refresh', self.refresh)
addApiView('movie.search', self.search, docs = {
'desc': 'Search the movie providers for a movie',
'params': {
'q': {'desc': 'The (partial) movie name you want to search for'},
},
'return': {'type': 'object', 'example': """{
'success': True,
'empty': bool, any movies returned or not,
'movies': array, movies found,
}"""}
})
addApiView('movie.list', self.listView, docs = {
'desc': 'List movies in wanted list',
'params': {
'status': {'type': 'array or csv', 'desc': 'Filter movie by status. Example:"active,done"'},
'limit_offset': {'desc': 'Limit the movie list. Examples: "50", "50,30"'},
'starts_with': {'desc': 'Starts with these characters. Example: "a" returns all movies starting with the letter "a"'},
'search': {'desc': 'Search movie title'},
},
'return': {'type': 'object', 'example': """{
'success': True,
'empty': bool, any movies returned or not,
'movies': array, movies found,
}"""}
})
addApiView('movie.refresh', self.refresh, docs = {
'desc': 'Refresh a movie by id',
'params': {
'id': {'desc': 'The id of the movie that needs to be refreshed'},
}
})
addApiView('movie.available_chars', self.charView)
addApiView('movie.add', self.addView)

37
couchpotato/core/settings/__init__.py

@ -16,8 +16,41 @@ class Settings(object):
def __init__(self):
addApiView('settings', self.view)
addApiView('settings.save', self.saveView)
addApiView('settings', self.view, docs = {
'desc': 'Return the options and its values of settings.conf. Including the default values and group ordering used on the settings page.',
'return': {'type': 'object', 'example': """{
// objects like in __init__.py of plugin
"options": {
"moovee" : {
"groups" : [{
"description" : "SD movies only",
"name" : "#alt.binaries.moovee",
"options" : [{
"default" : false,
"name" : "enabled",
"type" : "enabler"
}],
"tab" : "providers"
}],
"name" : "moovee"
}
},
// object structured like settings.conf
"values": {
"moovee": {
"enabled": false
}
}
}"""}
})
addApiView('settings.save', self.saveView, docs = {
'desc': 'Save setting to config file (settings.conf)',
'params': {
'section': {'desc': 'The section name in settings.conf'},
'option': {'desc': 'The option name'},
'value': {'desc': 'The value you want to save'},
}
})
def setFile(self, config_file):
self.file = config_file

75
couchpotato/static/style/api.css

@ -0,0 +1,75 @@
html {
font-size: 12px;
line-height: 1.5;
font-family: "Helvetica Neue", Helvetica, Arial, Geneva, sans-serif;
font-size: 14px;
}
h1, h2, h3, h4, h5 {
clear: both;
padding: 0;
margin: 0;
font-size: 14px;
}
h1 {
font-size: 25px;
}
h2 {
font-size: 20px;
}
pre {
background: #ccc;
font-family: monospace;
margin: 0;
padding: 2%;
width: 96%;
display: block;
}
.api {
margin-bottom: 20px;
overflow: hidden;
}
.api .description {
color: #333;
padding: 0 0 5px;
}
.api .params {
background: #f5f5f5;
width: 100%;
}
.api h3 {
clear: both;
float: left;
width: 100px;
}
.api .params {
float: left;
width: 700px;
}
.api .params .param {
vertical-align: top;
}
.api .params .param th {
text-align: left;
width: 100px;
}
.api .param .type {
font-style: italic;
margin-right: 10px;
width: 100px;
}
.api .return {
float: left;
width: 700px;
}

49
couchpotato/templates/api.html

@ -0,0 +1,49 @@
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="{{ url_for('web.static', filename='style/api.css') }}" type="text/css">
<title>API documentation</title>
</head>
<body>
<h1>API</h1>
{% for route in routes %}
{% if api_docs.get(route) %}
<div class="api">
<h2>{{route}}</h2>
<div class="description">{{api_docs[route].get('desc', '')}}</div>
{% if api_docs[route].get('params') %}
<h3>Params</h3>
<table class="params">
{% for param in api_docs[route]['params'] %}
<tr class="param">
<th>{{param}}</th>
<td class="type">{{ api_docs[route]['params'][param].get('type', 'string') }}</td>
<td class="description">{{ api_docs[route]['params'][param]['desc'] }}</td>
</tr>
{% endfor %}
</table>
{% endif %}
{% if api_docs[route].get('return') %}
<h3>Return</h3>
<div class="return">
<div class="type">{{ api_docs[route]['return'].get('type', '{"success": True}') }}</div>
{% if api_docs[route]['return'].get('example') %}
<div class="example">
<h4>Example</h4>
<pre>{{ api_docs[route]['return'].get('example', '')|safe }}</pre>
</div>
{% endif %}
</div>
{% endif %}
</div>
{% endif %}
{% endfor %}
<h1>Missing documentation</h1>
<div class="missing">{{', '.join(api_docs_missing)}}</div>
</body>
</html>
Loading…
Cancel
Save