Project

Profile

Help

Task #3836

Updated by bizhang over 2 years ago

h2. Why do we need to convert to pyswagger?

The schema that we use for documentation and bindings are openapi based. PySwagger is a python swagger client that reads in schema, and makes calls to the REST API based on that schema.

Pyswagger makes it so we don't need to typecheck body parameters, and we don't need to format query and path parameters in URLs.

h2. Creating the nested Click commands.

Every openapi operation has its own operationId. These OperationIds can be accessed from pyswagger like so:

<pre><code class="python">
app = App.create(DOCUMENT_PATH)
app.op.keys()
</code></pre>

This returns something like:
<pre><code class="python">
['repositories!##!repositories_versions_removed_content',
'repositories!##!repositories_versions_content',
'repositories!##!repositories_versions_added_content',
'repositories!##!repositories_versions_delete',
'repositories!##!repositories_versions_read',
'repositories!##!repositories_versions_create',
'repositories!##!repositories_versions_list',
'repositories!##!repositories_partial_update',
'repositories!##!repositories_delete',
'repositories!##!repositories_update',
'repositories!##!repositories_read',
'repositories!##!repositories_create',
'repositories!##!repositories_list',
'remotes!##!remotes_create',
...
]
</code></pre>

Individual operations are separated via '_', this is less than ideal, since some of our operations contain '_' like 'added_content'.

A solution would be to separate this list with \!\#\#\!, !##!, group all the common operations together (things to the left of \!\#\#\!), !##!), and find the longest common startswith substring for any subset of the list (care should be taken that this substing has to be separated by a _, since we don't want repo_versions, and repositories to return repo as a substring).

This longest common substring should be a 'group' that other commands nest under. This substring should then be removed from the rest of the items in the the subset, and if there is no more shared substrings, everything can be added as a command.

h2. Getting indivudual operation parameters

Individual parameters can be found on

<pre><code class="python">
app.op['repositories!##!repositories_update'].parameters
</code></pre>

Usually this is a data parameter (for body params) and whatever path params are in the URL.

The data param has a schema reference that can be accessed
<pre><code class="python">
getattr(app.op['repositories!##!repositories_create'].parameters[0].schema, '$ref')
</code></pre>

And a pyswagger Resolver can be used to load up that reference and get the necessary parameters
<pre><code class="python">
>>> from pyswagger.resolve import Resolver
>>> res = Resolver()
>>> res.resolve(getattr(app.op['repositories!##!repositories_create'].parameters[0].schema, '$ref'))
{
'required':[
'name'
],
'type':'object',
'properties':{
'id':{
'title':'Id',
'type':'string',
'format':'uuid',
'readOnly':True
},
'_href':{
'title':' href',
'type':'string',
'format':'uri',
'readOnly':True
},
'created':{
'title':'Created',
'description':'Timestamp of creation.',
'type':'string',
'format':'date-time',
'readOnly':True
},
'_versions_href':{
'title':' versions href',
'type':'string',
'format':'uri',
'readOnly':True
},
'_latest_version_href':{
'title':' latest version href',
'type':'string',
'format':'uri',
'readOnly':True
},
'name':{
'title':'Name',
'description':'A unique name for this repository.',
'type':'string',
'minLength':1
},
'description':{
'title':'Description',
'description':'An optional description.',
'type':'string'
},
'notes':{
'title':'Notes',
'description':'A mapping of string keys to string values, for storing notes on this object.',
'type':'object',
'additionalProperties':{
'type':'string',
'minLength':1
}
}
}
}
</code></pre>

Back