Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open Api to Hydra Parser basic implementation #197

Merged
merged 18 commits into from
May 29, 2018

Conversation

vaibhavchellani
Copy link
Contributor

@vaibhavchellani vaibhavchellani commented May 26, 2018

Fixes #193 and #198

Checklist

  • Everything works and tested for Python 3.5.2 and above.
  • My branch is up-to-date with upstream/develop branch.

Description

This script is able to parse the open api spec and is able to extract the classes , supported props , supported operations from the file and create a Hydra Api Documentation .

Test Logs

@xadahiya @chrizandr @Shekharrajak , let me know the changes , its WIP

@vaibhavchellani vaibhavchellani changed the title Open Api to Hydra Parser rough implementation Open Api to Hydra Parser basic implementation May 26, 2018
Copy link
Member

@xadahiya xadahiya left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hydrus code uses mypy static typing format. Please use that format instead. It'll reduce your overhead later.

baseURL = doc["host"]
name = doc["basePath"]
api_doc = HydraDoc(name, title, desc, name, baseURL)
definitions = doc["definitions"]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitions won't always be defined in doc["definitions"]. You should use $ref see this https://swagger.io/docs/specification/using-ref/

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes you are right , right now i am first parsing definitions and adding props and classes to api doc , then i parse paths and check if the path has the same name as class , if yes i add the operations .
Would the following be a better implementation , parse the paths , when $ref is found , parse whatever is defined and create classes ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, you should check where $ref points and then extract the definitions from there. It can be in the same doc or at some remote location but for now using local definitions should be fine

properties = definitions[class_]["properties"]
classAndClassDefinition[class_] = classDefinition
definitionSet.add(class_)
api_doc.add_supported_class(classDefinition, collection=False)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How are you checking if any endpoint is a collection or not?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not right now , in our discussions we decided to do that later .

try:
parameters = paths[path][method]["parameters"]
for param in parameters:
op_expects = param["schema"]["$ref"].split('/')[2]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be 'vocab:'+param["schema"]["$ref"].split('/')[2]. ALso what if the parameter is something as simple as an integer and it's not defined in schema?

For example -

      parameters:
        - name: petId
          in: path
          description: ID of pet to return
          required: true
          type: integer
          format: int64

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have planned on adding some datatypes which Open api support like string , integer etc as classes and add those when we encounter them . I am adding the "vocab" part later in line 94

# dirty hack , do case insensitive search more gracefully
possiblePath = possiblePath.replace(possiblePath[0], possiblePath[0].upper())
# check if the path name exists in the classes defined
if possiblePath in definitionSet and len(path.split('/')) == 2:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about paths like /user/createWithList or any other path with length > 2?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes , want to discuss about what to do about those .

"vocab:" + op_expects,
op_returns,
op_status))
api_doc.add_supported_class(classAndClassDefinition[possiblePath], collection=False)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, will only work for paths like /User. Also, what about collection type?

Important - You're adding same class twice to the doc. First in line 41 and then again here.
Why?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there would be some classes which are only made to be referenced later on , classes are added when their parsing is done , later if we find operations on them we add the operations and add it to the api doc again , the class appears only once in the final doc . Please suggest a better way .

paths = doc["paths"]
definitionSet = set()
classAndClassDefinition = dict()
hydra_doc = ""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please avoid using so many Global variables. You're not using function arguments at all.
It's not a good practice.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay , thank you , i agree , will do .


"""
import yaml
from doc_writer import HydraDoc, HydraClass, HydraClassProp, HydraClassOp
Copy link
Member

@xadahiya xadahiya May 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make sure you use absolute imports, not relative imports.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done !

Copy link
Member

@xadahiya xadahiya left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use absolute imports

@vaibhavchellani
Copy link
Contributor Author

@xadahiya can this PR be merged ?

@xadahiya
Copy link
Member

@chrizandr ^^

@xadahiya xadahiya requested a review from chrizandr May 28, 2018 01:27
@xadahiya
Copy link
Member

@vaibhavchellani reduce the number of global variables a bit. Rest everything looks fine.

@vaibhavchellani
Copy link
Contributor Author

@xadahiya @chrizandr done .

Copy link
Member

@chrizandr chrizandr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please make the changes suggested. Also, have you tried running a hydrus instance with the generated API documentation?
You can replace the API doc in used in hydrus.tests with the newly generated one and see if you get any errors. It's a good way to check if you missed something out. Please check that and let us know what you find.

print(exc)


definitionSet = set()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Declare these in the getClasses() function and pass it as a variable to get_ops(). Whenever you can replace global variables with passable parameters, you should opt for the latter. hydra_doc can be declared in getClasses() as well and can be returned from to main when function finishes execution.

import yaml
import json

from hydrus.hydraspec.doc_writer import HydraDoc, HydraClass, HydraClassProp, HydraClassOp
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good use of doc writer.


from hydrus.hydraspec.doc_writer import HydraDoc, HydraClass, HydraClassProp, HydraClassOp

with open("../samples/openapi_sample.yaml", 'r') as stream:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move this to main as well

except KeyError:
op_returns = None
classAndClassDefinition[possiblePath].add_supported_op(HydraClassOp(op_name,
op_method,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Methods are lower case in OpenAPI, but in Hydra, the standard is to use upper case method names. Convert "put"/"post"/"get"/"delete" to "PUT"/"POST"/"GET"/"DELETE". This is also messing up the proper @type for the supported operations.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah my bad , will correct this .

definitionSet.add(class_)
api_doc.add_supported_class(classDefinition, collection=False)
for prop in properties:
new_prop = HydraClassProp("vocab:" + prop, prop, required=False, read=True, write=True)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maintaining line length < 80 according to PEP8, will be better.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay

@vaibhavchellani
Copy link
Contributor Author

@xadahiya @chrizandr @Shekharrajak fixed most of the things pointed out

@vaibhavchellani
Copy link
Contributor Author

can this be merged ?

@xadahiya
Copy link
Member

Merging #197

@xadahiya xadahiya merged commit 70dbc1c into HTTP-APIs:develop May 29, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants