Show all revisions (~git log) starting from
diff --git a/swh/web/ui/tests/test_service.py b/swh/web/ui/tests/test_service.py
--- a/swh/web/ui/tests/test_service.py
+++ b/swh/web/ui/tests/test_service.py
@@ -1186,7 +1186,8 @@
# when
actual_revision = service.lookup_revision_log(
- 'abcdbe353ed3480476f032475e7c233eff7371d5')
+ 'abcdbe353ed3480476f032475e7c233eff7371d5',
+ limit=25)
# then
self.assertEqual(list(actual_revision), [self.SAMPLE_REVISION])
diff --git a/swh/web/ui/tests/views/test_browse.py b/swh/web/ui/tests/views/test_browse.py
--- a/swh/web/ui/tests/views/test_browse.py
+++ b/swh/web/ui/tests/views/test_browse.py
@@ -20,6 +20,26 @@
class SearchView(test_app.SWHViewTestCase):
render_template = False
+ @patch('swh.web.ui.apidoc.APIUrls')
+ @istest
+ def browse_api_doc(self, mock_api_urls):
+ # given
+ endpoints = {
+ '/a/doc/endpoint/': 'relevant documentation',
+ '/some/other/endpoint/': 'more docstrings'}
+ mock_api_urls.apidoc_routes = endpoints
+
+ # when
+ rv = self.client.get('/api/1/doc/')
+
+ # then
+ self.assertEquals(rv.status_code, 200)
+ self.assertIsNotNone(
+ self.get_context_variable('doc_routes'),
+ sorted(endpoints.items())
+ )
+ self.assert_template_used('api.html')
+
@istest
def search_default(self):
# when
diff --git a/swh/web/ui/views/api.py b/swh/web/ui/views/api.py
--- a/swh/web/ui/views/api.py
+++ b/swh/web/ui/views/api.py
@@ -5,32 +5,36 @@
from types import GeneratorType
-from flask import request, url_for, Response, redirect
+from flask import request, url_for
-from swh.web.ui import service, utils
+from swh.web.ui import service, utils, apidoc as doc
from swh.web.ui.exc import NotFoundExc
from swh.web.ui.main import app
@app.route('/api/1/stat/counters/')
+@doc.route('/api/1/stat/counters/', noargs=True)
+@doc.returns(rettype=doc.rettypes.dict,
+ retdoc="A dictionary of SWH's most important statistics")
def api_stats():
"""Return statistics on SWH storage.
- Returns:
- SWH storage's statistics.
-
"""
return service.stat_counters()
@app.route('/api/1/stat/visits//')
+@doc.route('/api/1/stat/visits/')
+@doc.arg('origin_id',
+ default=1,
+ argtype=doc.argtypes.int,
+ argdoc='The requested SWH origin identifier')
+@doc.returns(rettype=doc.rettypes.list,
+ retdoc="""All instances of visits of the origin pointed by
+ origin_id as POSIX time since epoch""")
def api_origin_visits(origin_id):
- """Return visit dates for the given revision.
-
- Returns:
- A list of SWH visit occurrence timestamps, sorted from oldest to
- newest.
-
+ """Return a list of visit dates as POSIX timestamps for the
+ given revision.
"""
date_gen = (item['date'] for item in service.stat_origin_visits(origin_id))
return sorted(date_gen)
@@ -38,22 +42,27 @@
@app.route('/api/1/search/', methods=['POST'])
@app.route('/api/1/search//')
+@doc.route('/api/1/search/')
+@doc.arg('q',
+ default='sha1:adc83b19e793491b1c6ea0fd8b46cd9f32e592fc',
+ argtype=doc.argtypes.algo_and_hash,
+ argdoc="""An algo_hash:hash string, where algo_hash is one of sha1,
+ sha1_git or sha256 and hash is the hash to search for in SWH""")
+@doc.raises(exc=doc.excs.badinput,
+ doc='Raised if q is not well formed')
+@doc.returns(rettype=doc.rettypes.dict,
+ retdoc="""A dict with keys:
+ * search_res: a list of dicts corresponding to queried content
+ with key 'found' to True if found, 'False' if not
+ * search_stats: a dict containing number of files searched and
+ percentage of files found
+ """)
def api_search(q=None):
"""Search a content per hash.
- Args:
- q is of the form algo_hash:hash with algo_hash in
- (sha1, sha1_git, sha256).
-
- Returns:
- Dictionary with 'found' key and the associated result.
-
- Raises:
- BadInputExc in case of unknown algo_hash or bad hash.
-
- Example:
- GET /api/1/search/sha1:bd819b5b28fcde3bf114d16a44ac46250da94ee5/
-
+ This may take the form of a GET request with a single checksum, or a POST
+ request with many hashes, with the request body containing identifiers
+ (typically filenames) as keys and corresponding hashes as values.
"""
response = {'search_res': None,
@@ -139,71 +148,56 @@
return enrich_fn(res)
-@app.route('/api/1/origin/')
@app.route('/api/1/origin//')
+@doc.route('/api/1/origin/')
+@doc.arg('origin_id',
+ default=1,
+ argtype=doc.argtypes.int,
+ argdoc="The origin's SWH origin_id.")
+@doc.raises(exc=doc.excs.notfound,
+ doc='Raised if origin_id does not correspond to an origin in SWH')
+@doc.returns(rettype=doc.rettypes.dict,
+ retdoc='The metadata of the origin identified by origin_id')
def api_origin(origin_id):
"""Return information about origin with id origin_id.
-
-
- Args:
- origin_id: the origin's identifier.
-
- Returns:
- Information on the origin if found.
-
- Raises:
- NotFoundExc if the origin is not found.
-
- Example:
- GET /api/1/origin/1/
-
"""
return _api_lookup(
origin_id, lookup_fn=service.lookup_origin,
error_msg_if_not_found='Origin with id %s not found.' % origin_id)
-@app.route('/api/1/person/')
@app.route('/api/1/person//')
+@doc.route('/api/1/person/')
+@doc.arg('person_id',
+ default=1,
+ argtype=doc.argtypes.int,
+ argdoc="The person's SWH identifier")
+@doc.raises(exc=doc.excs.notfound,
+ doc='Raised if person_id does not correspond to an origin in SWH')
+@doc.returns(rettype=doc.rettypes.dict,
+ retdoc='The metadata of the person identified by person_id')
def api_person(person_id):
"""Return information about person with identifier person_id.
-
- Args:
- person_id: the person's identifier.
-
- Returns:
- Information on the person if found.
-
- Raises:
- NotFoundExc if the person is not found.
-
- Example:
- GET /api/1/person/1/
-
"""
return _api_lookup(
person_id, lookup_fn=service.lookup_person,
error_msg_if_not_found='Person with id %s not found.' % person_id)
-@app.route('/api/1/release/')
@app.route('/api/1/release//')
+@doc.route('/api/1/release/')
+@doc.arg('sha1_git',
+ default='8b137891791fe96927ad78e64b0aad7bded08bdc',
+ argtype=doc.argtypes.sha1_git,
+ argdoc="The release's sha1_git identifier")
+@doc.raises(exc=doc.excs.badinput,
+ doc='Raised if the argument is not a sha1')
+@doc.raises(exc=doc.excs.notfound,
+ doc='Raised if sha1_git does not correspond to a release in SWH')
+@doc.returns(rettype=doc.rettypes.dict,
+ retdoc='The metadata of the release identified by sha1_git')
def api_release(sha1_git):
"""Return information about release with id sha1_git.
-
- Args:
- sha1_git: the release's hash.
-
- Returns:
- Information on the release if found.
-
- Raises:
- BadInputExc in case of unknown algo_hash or bad hash.
- NotFoundExc if the release is not found.
-
- Example:
- GET /api/1/release/b307094f00c3641b0c9da808d894f3a325371414
-
"""
error_msg = 'Release with sha1_git %s not found.' % sha1_git
return _api_lookup(
@@ -267,6 +261,31 @@
'/branch/'
'/ts/'
'/directory//')
+@doc.route('/api/1/revision/origin/directory/')
+@doc.arg('origin_id',
+ default=1,
+ argtype=doc.argtypes.int,
+ argdoc="The revision's origin's SWH identifier")
+@doc.arg('branch_name',
+ default='refs/heads/master',
+ argtype=doc.argtypes.path,
+ argdoc="""The optional branch for the given origin (default
+ to master""")
+@doc.arg('ts',
+ default='2000-01-17T11:23:54+00:00',
+ argtype=doc.argtypes.ts,
+ argdoc="""Optional timestamp (default to the nearest time
+ crawl of timestamp)""")
+@doc.arg('path',
+ default='.',
+ argtype=doc.argtypes.path,
+ argdoc='The path to the directory or file to display')
+@doc.raises(exc=doc.excs.notfound,
+ doc="""Raised if a revision matching the passed criteria was
+ not found""")
+@doc.returns(rettype=doc.rettypes.dict,
+ retdoc="""The metadata of the revision corresponding to the
+ passed criteria""")
def api_directory_through_revision_origin(origin_id,
branch_name="refs/heads/master",
ts=None,
@@ -274,24 +293,6 @@
with_data=False):
"""Display directory or content information through a revision identified
by origin/branch/timestamp.
-
- Args:
- origin_id: origin's identifier (default to 1).
- branch_name: the optional branch for the given origin (default
- to master).
- timestamp: optional timestamp (default to the nearest time
- crawl of timestamp).
- path: Path to directory or file to display.
- with_data: indicate to retrieve the content's raw data if path resolves
- to a content.
-
- Returns:
- Information on the directory or content pointed to by such revision.
-
- Raises:
- NotFoundExc if the revision is not found or the path pointed to
- is not found.
-
"""
if ts:
ts = utils.parse_timestamp(ts)
@@ -319,28 +320,31 @@
@app.route('/api/1/revision'
'/origin/'
'/ts//')
+@doc.route('/api/1/revision/origin/')
+@doc.arg('origin_id',
+ default=1,
+ argtype=doc.argtypes.int,
+ argdoc="The queried revision's origin identifier in SWH")
+@doc.arg('branch_name',
+ default='refs/heads/master',
+ argtype=doc.argtypes.path,
+ argdoc="""The optional branch for the given origin (default
+ to master)""")
+@doc.arg('ts',
+ default='2000-01-17T11:23:54+00:00',
+ argtype=doc.argtypes.ts,
+ argdoc="The time at which the queried revision should be constrained")
+@doc.raises(exc=doc.excs.notfound,
+ doc="""Raised if a revision matching given criteria was not found
+ in SWH""")
+@doc.returns(rettype=doc.rettypes.dict,
+ retdoc="""The metadata of the revision identified by the given
+ criteria""")
def api_revision_with_origin(origin_id,
branch_name="refs/heads/master",
ts=None):
- """Instead of having to specify a (root) revision by SHA1_GIT, users
- might want to specify a place and a time. In SWH a "place" is an
- origin; a "time" is a timestamp at which some place has been
- observed by SWH crawlers.
-
- Args:
- origin_id: origin's identifier (default to 1).
- branch_name: the optional branch for the given origin (default
- to master).
- timestamp: optional timestamp (default to the nearest time
- crawl of timestamp).
-
- Returns:
- Information on the revision if found.
-
- Raises:
- BadInputExc in case of unknown algo_hash or bad hash.
- NotFoundExc if the revision is not found.
-
+ """Display revision information through its identification by
+ origin/branch/timestamp.
"""
if ts:
ts = utils.parse_timestamp(ts)
@@ -357,24 +361,25 @@
ts)
-@app.route('/api/1/revision/')
@app.route('/api/1/revision//')
@app.route('/api/1/revision//prev//')
+@doc.route('/api/1/revision/')
+@doc.arg('sha1_git',
+ default='ec72c666fb345ea5f21359b7bc063710ce558e39',
+ argtype=doc.argtypes.sha1_git,
+ argdoc="The revision's sha1_git identifier")
+@doc.arg('context',
+ default='6adc4a22f20bbf3bbc754f1ec8c82be5dfb5c71a',
+ argtype=doc.argtypes.path,
+ argdoc='The navigation breadcrumbs -- use at your own risk')
+@doc.raises(exc=doc.excs.badinput,
+ doc='Raised if sha1_git is not well formed')
+@doc.raises(exc=doc.excs.notfound,
+ doc='Raised if a revision matching sha1_git was not found in SWH')
+@doc.returns(rettype=doc.rettypes.dict,
+ retdoc='The metadata of the revision identified by sha1_git')
def api_revision(sha1_git, context=None):
"""Return information about revision with id sha1_git.
-
- Args:
- sha1_git: the revision's hash.
-
- Returns:
- Information on the revision if found.
-
- Raises:
- BadInputExc in case of unknown algo_hash or bad hash.
- NotFoundExc if the revision is not found.
-
- Example:
- GET /api/1/revision/baf18f9fc50a0b6fef50460a76c33b2ddc57486e
"""
def _enrich_revision(revision, context=context):
return utils.enrich_revision(revision, context)
@@ -387,58 +392,53 @@
@app.route('/api/1/revision//raw/')
+@doc.route('/api/1/revision/raw/')
+@doc.arg('sha1_git',
+ default='ec72c666fb345ea5f21359b7bc063710ce558e39',
+ argtype=doc.argtypes.sha1_git,
+ argdoc="The queried revision's sha1_git identifier")
+@doc.raises(exc=doc.excs.badinput,
+ doc='Raised if sha1_git is not well formed')
+@doc.raises(exc=doc.excs.notfound,
+ doc='Raised if a revision matching sha1_git was not found in SWH')
+@doc.returns(rettype=doc.argtypes.octet_stream,
+ retdoc="""The message of the revision identified by sha1_git
+ as a downloadable octet stream""")
def api_revision_raw_message(sha1_git):
- """Return the raw data of the revision's message
-
- Args:
- sha1_git: the revision's hash
-
- Returns:
- The raw revision message, possibly in an illegible
- format for humans, decoded in utf-8 by default.
-
- Raises:
- BadInputExc in case of unknown algo_hash or bad hash.
- NotFoundExc if the revision is not found or the revision has no
- message
-
- Example:
- GET /api/1/revision/baf18f9fc50a0b6fef50460a76c33b2ddc57486e/raw/
-
+ """Return the raw data of the message of revision identified by sha1_git
"""
raw = service.lookup_revision_message(sha1_git)
- return Response(raw['message'],
- headers={'Content-disposition': 'attachment;'
- 'filename=rev_%s_raw' % sha1_git},
- mimetype='application/octet-stream')
+ return app.response_class(raw['message'],
+ headers={'Content-disposition': 'attachment;'
+ 'filename=rev_%s_raw' % sha1_git},
+ mimetype='application/octet-stream')
@app.route('/api/1/revision//directory/')
@app.route('/api/1/revision//directory//')
+@doc.route('/api/1/revision/directory/')
+@doc.arg('sha1_git',
+ default='ec72c666fb345ea5f21359b7bc063710ce558e39',
+ argtype=doc.argtypes.sha1_git,
+ argdoc="The revision's sha1_git identifier.")
+@doc.arg('dir_path',
+ default='.',
+ argtype=doc.argtypes.path,
+ argdoc='The path from the top level directory')
+@doc.raises(exc=doc.excs.badinput,
+ doc='Raised if sha1_git is not well formed')
+@doc.raises(exc=doc.excs.notfound,
+ doc="""Raised if a revision matching sha1_git was not found in SWH
+ , or if the path specified does not exist""")
+@doc.returns(rettype=doc.rettypes.dict,
+ retdoc="""The metadata of the directory pointed by revision id
+ sha1-git and dir_path""")
def api_revision_directory(sha1_git,
dir_path=None,
with_data=False):
"""Return information on directory pointed by revision with sha1_git.
If dir_path is not provided, display top level directory.
Otherwise, display the directory pointed by dir_path (if it exists).
-
- Args:
- sha1_git: revision's hash.
- dir_path: optional directory pointed to by that revision.
- with_data: indicate to retrieve the content's raw data if path resolves
- to a content
-
- Returns:
- Information on the directory pointed to by that revision.
-
- Raises:
- BadInputExc in case of unknown algo_hash or bad hash.
- NotFoundExc either if the revision is not found or the path referenced
- does not exist
-
- Example:
- GET /api/1/revision/baf18f9fc50a0b6fef50460a76c33b2ddc57486e/directory/
-
"""
return _revision_directory_by(
{
@@ -451,23 +451,27 @@
@app.route('/api/1/revision//log/')
@app.route('/api/1/revision//prev//log/')
+@doc.route('/api/1/revision/log/')
+@doc.arg('sha1_git',
+ default='ec72c666fb345ea5f21359b7bc063710ce558e39',
+ argtype=doc.argtypes.sha1_git,
+ argdoc='The sha1_git of the revision queried')
+@doc.arg('prev_sha1s',
+ default='6adc4a22f20bbf3bbc754f1ec8c82be5dfb5c71a',
+ argtype=doc.argtypes.path,
+ argdoc='The navigation breadcrumbs -- use at your own risk!')
+@doc.raises(exc=doc.excs.badinput,
+ doc='Raised if sha1_git or prev_sha1s is not well formed')
+@doc.raises(exc=doc.excs.notfound,
+ doc='Raised if a revision matching sha1_git was not found in SWH')
+@doc.returns(rettype=doc.rettypes.dict,
+ retdoc="""The log data starting at the revision identified by
+ sha1_git, completed with the navigation breadcrumbs,
+ if any""")
def api_revision_log(sha1_git, prev_sha1s=None):
"""Show all revisions (~git log) starting from sha1_git.
- The first element returned is the given sha1_git.
-
- Args:
- sha1_git: the revision's hash.
- prev_sha1s: the navigation breadcrumb
- limit: optional query parameter to limit the revisions log
- (default to 100).
-
- Returns:
- Information on the revision if found, complemented with the revision's
- children if we have navigation breadcrumbs for them.
-
- Raises:
- BadInputExc in case of unknown algo_hash or bad hash.
- NotFoundExc if the revision is not found.
+ The first element returned is the given sha1_git, or the first
+ breadcrumb, if any.
"""
limit = app.config['conf']['max_log_revs']
@@ -510,8 +514,6 @@
@app.route('/api/1/revision'
- '/origin/log/')
-@app.route('/api/1/revision'
'/origin//log/')
@app.route('/api/1/revision'
'/origin/'
@@ -523,26 +525,32 @@
@app.route('/api/1/revision'
'/origin/'
'/ts//log/')
+@doc.route('/api/1/revision/origin/log/')
+@doc.arg('origin_id',
+ default=1,
+ argtype=doc.argtypes.int,
+ argdoc="The revision's SWH origin identifier")
+@doc.arg('branch_name',
+ default='refs/heads/master',
+ argtype=doc.argtypes.path,
+ argdoc="The revision's branch name within the origin specified")
+@doc.arg('ts',
+ default='2000-01-17T11:23:54+00:00',
+ argtype=doc.argtypes.ts,
+ argdoc="""A time or timestamp string to parse""")
+@doc.raises(exc=doc.excs.notfound,
+ doc="""Raised if a revision matching the given criteria was not
+ found in SWH""")
+@doc.returns(rettype=doc.rettypes.dict,
+ retdoc="""The metadata of the revision log starting at the revision
+ matching the given criteria.""")
def api_revision_log_by(origin_id,
branch_name='refs/heads/master',
ts=None):
"""Show all revisions (~git log) starting from the revision
- described by its origin_id, optional branch name and timestamp.
- The first element returned is the described revision.
-
- Args:
- origin_id: the revision's origin.
- branch_name: the branch of the revision (optional, defaults to
- master
- ts: the requested timeframe near which the revision was created.
- limit: optional query parameter to limit the revisions log
- (default to 100).
-
- Returns:
- Information on the revision log if found.
+ described by its origin_id, optional branch name and timestamp.
+ The first element returned is the described revision.
- Raises:
- NotFoundExc if the revision is not found.
"""
limit = app.config['conf']['max_log_revs']
response = {'revisions': None, 'next_revs_url': None}
@@ -576,26 +584,28 @@
return response
-@app.route('/api/1/directory/')
@app.route('/api/1/directory//')
@app.route('/api/1/directory///')
+@doc.route('/api/1/directory/')
+@doc.arg('sha1_git',
+ default='adc83b19e793491b1c6ea0fd8b46cd9f32e592fc',
+ argtype=doc.argtypes.sha1_git,
+ argdoc="The queried directory's corresponding sha1_git hash")
+@doc.arg('path',
+ default='.',
+ argtype=doc.argtypes.path,
+ argdoc="A path relative to the queried directory's top level")
+@doc.raises(exc=doc.excs.badinput,
+ doc='Raised if sha1_git is not well formed')
+@doc.raises(exc=doc.excs.notfound,
+ doc='Raised if a directory matching sha1_git was not found in SWH')
+@doc.returns(rettype=doc.rettypes.dict,
+ retdoc="""The metadata and contents of the release identified by
+ sha1_git""")
def api_directory(sha1_git,
path=None):
"""Return information about release with id sha1_git.
- Args:
- sha1_git: Directory's sha1_git. If path exists: starting directory for
- relative navigation.
- path: The path to the queried directory
-
- Raises:
- BadInputExc in case of unknown algo_hash or bad hash.
- NotFoundExc if the content is not found.
-
- Example:
- GET /api/1/directory/8d7dc91d18546a91564606c3e3695a5ab568d179
- GET /api/1/directory/8d7dc91d18546a91564606c3e3695a5ab568d179/path/dir/
-
"""
if path:
error_msg_path = ('Entry with path %s relative to directory '
@@ -644,21 +654,23 @@
@app.route('/api/1/content//raw/')
+@doc.route('/api/1/content/raw/')
+@doc.arg('q',
+ default='adc83b19e793491b1c6ea0fd8b46cd9f32e592fc',
+ argtype=doc.argtypes.algo_and_hash,
+ argdoc="""An algo_hash:hash string, where algo_hash is one of sha1,
+ sha1_git or sha256 and hash is the hash to search for in SWH. Defaults
+ to sha1 in the case of a missing algo_hash
+ """)
+@doc.raises(exc=doc.excs.badinput,
+ doc='Raised if q is not well formed')
+@doc.raises(exc=doc.excs.notfound,
+ doc='Raised if a content matching q was not found in SWH')
+@doc.returns(rettype='octet stream',
+ retdoc='The raw content data as an octet stream')
def api_content_raw(q):
"""Return content's raw data if content is found.
- Args:
- q is of the form (algo_hash:)hash with algo_hash in
- (sha1, sha1_git, sha256).
- When algo_hash is not provided, 'hash' is considered sha1.
-
- Returns:
- Content's raw data in application/octet-stream.
-
- Raises:
- - BadInputExc in case of unknown algo_hash or bad hash
- - NotFoundExc if the content is not found.
-
"""
def generate(content):
yield content['data']
@@ -667,30 +679,31 @@
if not content:
raise NotFoundExc('Content with %s not found.' % q)
- return Response(generate(content), mimetype='application/octet-stream')
+ return app.response_class(generate(content),
+ headers={'Content-disposition': 'attachment;'
+ 'filename=content_%s_raw' % q},
+ mimetype='application/octet-stream')
-@app.route('/api/1/content/')
@app.route('/api/1/content//')
+@doc.route('/api/1/content/')
+@doc.arg('q',
+ default='adc83b19e793491b1c6ea0fd8b46cd9f32e592fc',
+ argtype=doc.argtypes.algo_and_hash,
+ argdoc="""An algo_hash:hash string, where algo_hash is one of sha1,
+ sha1_git or sha256 and hash is the hash to search for in SWH. Defaults
+ to sha1 in the case of a missing algo_hash
+ """)
+@doc.raises(exc=doc.excs.badinput,
+ doc='Raised if q is not well formed')
+@doc.raises(exc=doc.excs.notfound,
+ doc='Raised if a content matching q was not found in SWH')
+@doc.returns(rettype=doc.rettypes.dict,
+ retdoc="""The metadata of the content identified by q. If content
+ decoding was successful, it also returns the data""")
def api_content_metadata(q):
"""Return content information if content is found.
- Args:
- q is of the form (algo_hash:)hash with algo_hash in
- (sha1, sha1_git, sha256).
- When algo_hash is not provided, 'hash' is considered sha1.
-
- Returns:
- Content's information.
-
- Raises:
- - BadInputExc in case of unknown algo_hash or bad hash.
- - NotFoundExc if the content is not found.
-
- Example:
- GET /api/1/content/sha256:e2c76e40866bb6b28916387bdfc8649beceb
- 523015738ec6d4d540c7fe65232b
-
"""
return _api_lookup(
q,
@@ -699,27 +712,21 @@
enrich_fn=utils.enrich_content)
-@app.route('/api/1/entity/')
@app.route('/api/1/entity//')
+@doc.route('/api/1/entity/')
+@doc.arg('uuid',
+ default='5f4d4c51-498a-4e28-88b3-b3e4e8396cba',
+ argtype=doc.argtypes.uuid,
+ argdoc="The entity's uuid identifier")
+@doc.raises(exc=doc.excs.badinput,
+ doc='Raised if uuid is not well formed')
+@doc.raises(exc=doc.excs.notfound,
+ doc='Raised if an entity matching uuid was not found in SWH')
+@doc.returns(rettype=doc.rettypes.dict,
+ retdoc='The metadata of the entity identified by uuid')
def api_entity_by_uuid(uuid):
"""Return content information if content is found.
- Args:
- q is of the form (algo_hash:)hash with algo_hash in
- (sha1, sha1_git, sha256).
- When algo_hash is not provided, 'hash' is considered sha1.
-
- Returns:
- Content's information.
-
- Raises:
- - BadInputExc in case of unknown algo_hash or bad hash.
- - NotFoundExc if the content is not found.
-
- Example:
- - GET /api/1/entity/5f4d4c51-498a-4e28-88b3-b3e4e8396cba/
- - GET /api/1/entity/7c33636b-8f11-4bda-89d9-ba8b76a42cec/
-
"""
return _api_lookup(
uuid,
diff --git a/swh/web/ui/views/browse.py b/swh/web/ui/views/browse.py
--- a/swh/web/ui/views/browse.py
+++ b/swh/web/ui/views/browse.py
@@ -10,7 +10,7 @@
from flask.ext.api.renderers import HTMLRenderer
from swh.core.hashutil import ALGORITHMS
-from .. import service, utils
+from .. import service, utils, apidoc
from ..exc import BadInputExc, NotFoundExc
from ..main import app
from . import api
@@ -18,6 +18,19 @@
hash_filter_keys = ALGORITHMS
+@app.route('/api/1/doc/')
+@set_renderers(HTMLRenderer)
+def api_doc():
+ """Render the API's documentation.
+ """
+ routes = apidoc.APIUrls.get_app_endpoints()
+ # Return a list of routes with consistent ordering
+ env = {
+ 'doc_routes': sorted(routes.items())
+ }
+ return render_template('api.html', **env)
+
+
@app.route('/search/', methods=['GET', 'POST'])
@set_renderers(HTMLRenderer)
def search():