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

WIP Cobigen Python Flask #160

Open
wants to merge 19 commits into
base: main
Choose a base branch
from
168 changes: 168 additions & 0 deletions CRUD-Python-CobiGen/files/context.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<contextConfiguration xmlns="http://capgemini.com/devonfw/cobigen/ContextConfiguration" version="2.1">

<trigger id="crud_java_server_app" type="java" templateFolder="crud_java_server_app">
<containerMatcher type="package" value="((.+\.)?([^\.]+))\.([^\.]+)\.dataaccess\.api"
retrieveObjectsRecursively="false"/>
<matcher type="fqn" value="((.+\.)?([^\.]+))\.([^\.]+)\.dataaccess\.api\.([^\.]+)Entity">
<variableAssignment type="regex" key="rootPackage" value="1"/>
<variableAssignment type="regex" key="domain" value="3"/>
<variableAssignment type="regex" key="component" value="4"/>
<variableAssignment type="regex" key="entityName" value="5"/>
</matcher>
</trigger>
<trigger id="crud_java_server_app_complex" type="java" templateFolder="crud_java_server_app_complex">
<containerMatcher type="package" value="((.+\.)?([^\.]+))\.([^\.]+)\.dataaccess\.api"
retrieveObjectsRecursively="false"/>
<matcher type="fqn" value="((.+\.)?([^\.]+))\.([^\.]+)\.dataaccess\.api\.([^\.]+)Entity">
<variableAssignment type="regex" key="rootPackage" value="1"/>
<variableAssignment type="regex" key="domain" value="3"/>
<variableAssignment type="regex" key="component" value="4"/>
<variableAssignment type="regex" key="entityName" value="5"/>
</matcher>
</trigger>
<trigger id="crud_typescript_angular_client_app" type="typescript" templateFolder="crud_typescript_angular_client_app">
<matcher type="fqn" value="([^\.]+).entity">
<variableAssignment type="regex" key="entityName" value="1"/>
<variableAssignment type="regex" key="component" value="1"/>
<variableAssignment type="constant" key="domain" value="demo"/>
</matcher>
</trigger>
<trigger id="testdata_builder" type="java" templateFolder="testdata_builder">
<containerMatcher type="package" value="((.+\.)?([^\.]+))\.([^\.]+)\.dataaccess\.api"
retrieveObjectsRecursively="false"/>
<matcher type="fqn" value="((.+\.)?([^\.]+))\.([^\.]+)\.dataaccess\.api\.([^\.]+Entity)">
<variableAssignment type="regex" key="rootPackage" value="1"/>
<variableAssignment type="regex" key="domain" value="3"/>
<variableAssignment type="regex" key="component" value="4"/>
<variableAssignment type="regex" key="pojoName" value="5"/>
</matcher>
<matcher type="fqn" value="((.+\.)?([^\.]+))\.([^\.]+)\.logic\.api\.to\.([^\.]+[E|C]to)">
<variableAssignment type="regex" key="rootPackage" value="1"/>
<variableAssignment type="regex" key="domain" value="3"/>
<variableAssignment type="regex" key="component" value="4"/>
<variableAssignment type="regex" key="pojoName" value="5"/>
</matcher>
<matcher type="expression" value="instanceof java.lang.Enum" accumulationType="NOT"/>
<matcher type="expression" value="isAbstract" accumulationType="NOT"/>
</trigger>
<trigger id="constants_security_permissions" type="xml" templateFolder="constants/security_permissions">
<matcher type="nodename" value="access-control-schema">
<variableAssignment type="constant" key="rootPackage" value="com.devonfw.gastronomy.restaurant"/>
</matcher>
</trigger>
<trigger id="constants_named_queries" type="xml" templateFolder="constants/named_queries">
<matcher type="nodename" value="entity-mappings">
<variableAssignment type="constant" key="rootPackage" value="com.devonfw.gastronomy.restaurant"/>
</matcher>
</trigger>
<trigger id="crud_angular_client_app" type="java" templateFolder="crud_angular_client_app">
<matcher type="fqn" value="((.+\.)?([^\.]+))\.([^\.]+)\.logic\.api\.to\.([^\.]+)Eto">
<variableAssignment type="regex" key="rootPackage" value="1"/>
<variableAssignment type="regex" key="domain" value="3"/>
<variableAssignment type="regex" key="component" value="4"/>
<variableAssignment type="regex" key="etoName" value="5"/>
</matcher>
</trigger>
<trigger id="crud_ngrx_client_app" type="java" templateFolder="crud_ngrx_client_app">
<matcher type="fqn" value="((.+\.)?([^\.]+))\.([^\.]+)\.logic\.api\.to\.([^\.]+)Eto">
<variableAssignment type="regex" key="rootPackage" value="1"/>
<variableAssignment type="regex" key="domain" value="3"/>
<variableAssignment type="regex" key="component" value="4"/>
<variableAssignment type="regex" key="etoName" value="5"/>
</matcher>
</trigger>
<trigger id="crud_java_ea_uml" type="xml" templateFolder="crud_java_ea_uml">
<containerMatcher type="xpath" value="./uml:Model//packagedElement[@xmi:type='uml:Class']"/>
<matcher type="xpath" value="self::node()[@xmi:type='uml:Class']/ancestor::uml:Model">
<variableAssignment type="xpath" key="rootPackage"
value="self::node()/ancestor::packagedElement/packagedElement/@name"/>
<variableAssignment type="xpath" key="component"
value="self::node()/ancestor::packagedElement/packagedElement/packagedElement/@name"/>
<variableAssignment type="xpath" key="className" value="self::node()/@name"/>
</matcher>
</trigger>
<trigger id="crud_openapi_java_server_app" type="openapi" templateFolder="crud_openapi_java_server_app">
<containerMatcher type="element" value="openAPIFile"/>
<matcher type="element" value="EntityDef">
<variableAssignment type="extension" key="rootPackage" value="x-rootpackage"/>
<variableAssignment type="property" key="component" value="componentName"/>
<variableAssignment type="property" key="entityName" value="name"/>
</matcher>
</trigger>
<trigger id="crud_openapi_angular_client_app" type="openapi" templateFolder="crud_openapi_angular_client_app">
<containerMatcher type="element" value="openAPIFile"/>
<matcher type="element" value="EntityDef">
<variableAssignment type="constant" key="domain" value="demo"/>
<variableAssignment type="property" key="component" value="componentName"/>
<variableAssignment type="property" key="etoName" value="name"/>
</matcher>
</trigger>
<trigger id="crud_openapi_angular_service_based_app" type="openapi" templateFolder="crud_openapi_angular_service_based_app">
<containerMatcher type="element" value="openAPIFile"/>
<matcher type="element" value="ComponentDef">
<variableAssignment type="constant" key="domain" value="demo"/>
<variableAssignment type="property" key="component" value="name"/>
<variableAssignment type="property" key="etoName" value="name"/>
</matcher>
</trigger>
<trigger id="cobigen-python-templates" type="openapi" templateFolder="cobigen-python-templates">
<containerMatcher type="element" value="openAPIFile"/>
<matcher type="element" value="EntityDef">
<variableAssignment type="extension" key="rootPackage" value="x-rootpackage"/>
<variableAssignment type="property" key="component" value="componentName"/>
<variableAssignment type="property" key="entityName" value="name"/>
</matcher>
</trigger>
<trigger id="crud_openapi_net" type="openapi" templateFolder="crud_openapi_net">
<containerMatcher type="element" value="openAPIFile"/>
<matcher type="element" value="EntityDef">
<variableAssignment type="extension" key="rootPackage" value="x-rootpackage"/>
<variableAssignment type="property" key="component" value="componentName"/>
<variableAssignment type="property" key="entityName" value="name"/>
</matcher>
</trigger>
<trigger id="crud_openapi_ionic_client_app" type="openapi" templateFolder="crud_openapi_ionic_client_app">
<containerMatcher type="element" value="openAPIFile"/>
<matcher type="element" value="EntityDef">
<variableAssignment type="constant" key="domain" value="demo"/>
<variableAssignment type="property" key="component" value="componentName"/>
<variableAssignment type="property" key="etoName" value="name"/>
</matcher>
</trigger>
<trigger id="crud_ionic_client_app" type="java" templateFolder="crud_ionic_client_app">
<matcher type="fqn" value="((.+\.)?([^\.]+))\.([^\.]+)\.logic\.api\.to\.([^\.]+)Eto">
<variableAssignment type="regex" key="rootPackage" value="1"/>
<variableAssignment type="regex" key="domain" value="3"/>
<variableAssignment type="regex" key="component" value="4"/>
<variableAssignment type="regex" key="etoName" value="5"/>
</matcher>
</trigger>
<trigger id="REST_Docs" type="java" templateFolder="documentation/rest">
<containerMatcher type="package" value="((.+\.)?([^\.]+))\.([^\.]+)\.service\.api\.rest"
retrieveObjectsRecursively="false"/>
<matcher type="fqn" value="((.+\.)?([^\.]+))\.([^\.]+)\.service\.api\.rest\.([^\.]+)RestService">
<variableAssignment type="regex" key="rootPackage" value="1"/>
<variableAssignment type="regex" key="domain" value="3"/>
<variableAssignment type="regex" key="component" value="4"/>
</matcher>
</trigger>
<trigger id="Swagger_Docs" type="java" templateFolder="documentation/kafka">
<containerMatcher type="package" value="((.+\.)?([^\.]+))\.([^\.]+)\.service\.data"
retrieveObjectsRecursively="false"/>
<matcher type="fqn" value="((.+\.)?([^\.]+))\.([^\.]+)\.service\.data\.([^\.]+)To">
<variableAssignment type="regex" key="rootPackage" value="1"/>
<variableAssignment type="regex" key="domain" value="3"/>
<variableAssignment type="regex" key="component" value="4"/>
<variableAssignment type="regex" key="toName" value="5"/>
</matcher>
</trigger>
<trigger id="OpenAPI_docs" type="openapi" templateFolder="documentation/openapi">
<containerMatcher type="element" value="openAPIFile"/>
<matcher type="element" value="EntityDef">
<variableAssignment type="constant" key="rootPackage" value="com.devonfw"/>
<variableAssignment type="property" key="component" value="componentName"/>
<variableAssignment type="property" key="entityName" value="name"/>
</matcher>
</trigger>
</contextConfiguration>
5 changes: 5 additions & 0 deletions CRUD-Python-CobiGen/files/initialCommit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
In order to upload the table declared in our "Model.py" we need a migration script. This command requires an attached message whenever it runs, for instance:

`flask db migrate -m` "`first migration`"

In this case, the terminal should print in return `Detected added table user`, among others. We can now upload the migration script.
21 changes: 21 additions & 0 deletions CRUD-Python-CobiGen/files/postmanTest.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
We can test our application using Postman. Paste the main path on a new Postman tab, for instance:

http://127.0.0.1:5000/user

Our table is empty for the moment, so we will select the POST method to add new data. We can submit JSON requests by clicking on the "Body" tab and selecting "raw". For example, submit:


{ "name" : "elena", "age" : 26, "phone" : "555123", "email" : "[email protected]" }


Our new user should now be accessible from the database under "id" number 1. Check this by submitting a GET request to the following path:

http://127.0.0.1:5000/user/1

We will now edit our entry by sending a PUT request. Submit the following body to http://127.0.0.1:5000/user/1:

{ "phone" : "777123" }

Now send another GET request and check whether the column was properly updated.

Lastly, you can check the DELETE method by sending this request to http://127.0.0.1:5000/user/1. Then send a GET request to http://127.0.0.1:5000/user. The application returns "User list is empty".
39 changes: 39 additions & 0 deletions CRUD-Python-CobiGen/files/user.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
openapi: 3.0.0
servers:
- url: 'https://localhost:8081/server/services/rest'
description: Just some data
info:
title: devonfw Example
description: Example of a API definition
version: 1.0.0
x-rootpackage: com.devonfw.poc.jwtsample
paths:
/:
post:
responses:
'200':
description: Any
components:
schemas:
User:
x-component: usermanagement
description: Entity definiton of User
type: object
properties:
name:
type: string
maxLength: 100
uniqueItems: true
age:
type: integer
phone :
type: string
maxLength: 100
uniqueItems: true
email:
type: string
maxLength: 100
uniqueItems: true
required:
- name
- email
60 changes: 60 additions & 0 deletions CRUD-Python-CobiGen/index.asciidoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
= Create a CRUD Python Flask application using CobiGen's OpenAPI plugin
====
The aim of this tutorial is to create a basic CRUD Python Flask application from a single OpenAPI .yml file declaring an entity.

The code will be generated using devonfw's CobiGen. This will result in a basic application layout, the declaration of a Flask-SQLAlchemy table with the entity's attributes as columns, and a service returning JSON objects for the GET, POST, PUT and DELETE methods.
====

[step]
--
installDevonfwIde(["java","mvn"])
installCobiGen()
executeCommand("devon","devon")
--

[step]
--
adaptTemplatesCobiGen()
changeWorkspace(".cobigen/templates/CobiGen_Templates/src/main/templates")
cloneRepository("", "https://github.com/devonfw-forge/cobigen-python-templates.git")
--

[step]
--
changeFile("context.xml", { "file": "files/context.xml"})
--

[step]
--
executeCommand("cd /root/devonfw/workspaces/main","cd /root/devonfw/workspaces/main")
changeWorkspace("devonfw/workspaces/main")
createFile("cobigen-python-example/user.yml", "files/user.yml")
--

[step]
--
executeCommand("cobigen generate user.yml -i 1","cobigen generate user.yml -i 1",{"dir":"cobigen-python-example"})
--

[step]
--
executeCommand("python3 -m pip install virtualenv","python3 -m pip install virtualenv")
executeCommand("python3 -m virtualenv venv","python3 -m virtualenv venv")
executeCommand("activate.ps1","source activate", {"dir":"venv/bin"} )
executeCommand("cd /root/devonfw/workspaces/main/cobigen-python-example","cd /root/devonfw/workspaces/main/cobigen-python-example")
executeCommand("pip install -r requirements.txt","pip install -r requirements.txt")
--

[step]
--
executeCommand("flask db init","flask db init")
display("Initial commit", [{ "file": "files/initialCommit.md" }])
executeCommand("flask db upgrade","flask db upgrade")
--

[step]
--
executeCommand("flask run","flask run")
display("Postman test", [{ "file": "files/postmanTest.md" }])
--