Skip to content

Commit

Permalink
[doc] Contribute API cookbook recipes in Python
Browse files Browse the repository at this point in the history
Signed-off-by: Mélanie Bats <[email protected]>
  • Loading branch information
mbats authored and AxelRICHARD committed Jan 29, 2025
1 parent 5245006 commit 39d5d48
Show file tree
Hide file tree
Showing 23 changed files with 714 additions and 158 deletions.
2 changes: 1 addition & 1 deletion doc/content/modules/ROOT/pages/integration.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ a|image::tap_app.svg[xref=user-manual:key-features.adoc]

Standard APIs support for seamless connections.

xref:user-manual:integration/api.adoc[Delve into]
xref:developer-guide:api.adoc[Delve into]

a|image::globe.svg[xref=user-manual:what-is.adoc]

Expand Down

Large diffs are not rendered by default.

50 changes: 50 additions & 0 deletions doc/content/modules/developer-guide/examples/create_project.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# These examples are adapted from the SysML v2 API Cookbook, available at
# https://github.com/Systems-Modeling/SysML-v2-API-Cookbook, maintained by the
# Object Management Group (OMG).
# The original cookbook is designed for use with Jupyter Lab.
# These examples have been adapted to run as standalone Python scripts, making
# them suitable for use in various environments, including SysON.
# They showcase practical usage scenarios and may include additional functionality
# or modifications tailored to specific needs.

import requests # <1>
from init_api import init_sysmlv2_api
from fetch_projects import fetch_projects
from datetime import datetime

def create_project(host, project_name): # <2>
# Define project data as query parameters
project_params = {
"name": project_name
}

# API endpoint to create a project
url = f"{host}/projects" # <3>

# Send POST request with query parameters
response = requests.post(url, params=project_params) # <4>

# Check if the project creation was successful
if response.status_code == 201: # <5>
response_json = response.json()
print("Project created successfully:")
print(f"Project ID: {response_json.get("@id", "Unknown ID")}")
print(f"Project Name: {response_json.get('name', 'Unknown Name')}")
else:
print(f"Error creating project: {response.status_code} - {response.text}")

if __name__ == "__main__":
host = init_sysmlv2_api()

# Fetch and display the list of projects currently available on the server
print("Fetching the list of projects currently available on the server:")
fetch_projects(host)

# Create a new project with a unique name by appending a timestamp
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
project_name = f"New Project - {timestamp}"
create_project(host, project_name)

# Fetch and display the updated list of projects after creating the new project
print("Fetching the updated list of projects after creating a new project:")
fetch_projects(host)
43 changes: 43 additions & 0 deletions doc/content/modules/developer-guide/examples/fetch_commits.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# These examples are adapted from the SysML v2 API Cookbook, available at
# https://github.com/Systems-Modeling/SysML-v2-API-Cookbook, maintained by the
# Object Management Group (OMG).
# The original cookbook is designed for use with Jupyter Lab.
# These examples have been adapted to run as standalone Python scripts, making
# them suitable for use in various environments, including SysON.
# They showcase practical usage scenarios and may include additional functionality
# or modifications tailored to specific needs.

import requests # <1>
from init_api import parse_arguments
from init_api import init_sysmlv2_api

def fetch_commits(host, project_id): # <2>
commits_url = f"{host}/projects/{project_id}/commits" # <3>
response = requests.get(commits_url) # <4>
if response.status_code == 200: # <5>
commits = response.json()
for commit in commits:
print(f"Commit ID: {commit['@id']}")
return commits
else:
print(f"Error fetching commits: {response.status_code} - {response.text}")
return None

# Retrieves the latest commit for a given project.
def get_last_commit_id(host, project_id):
commits = fetch_commits(host, project_id)
if commits:
last_commit = commits[-1] if commits else None
if last_commit:
last_commit_id = last_commit['@id']
print(f"Last Commit ID: {last_commit_id}")
return last_commit_id
else:
print("No commits available.")
return None

if __name__ == "__main__":
args = parse_arguments()
host = init_sysmlv2_api()
project_id = args.project_id
fetch_commits(host, project_id)
34 changes: 34 additions & 0 deletions doc/content/modules/developer-guide/examples/fetch_elements.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# These examples are adapted from the SysML v2 API Cookbook, available at
# https://github.com/Systems-Modeling/SysML-v2-API-Cookbook, maintained by the
# Object Management Group (OMG).
# The original cookbook is designed for use with Jupyter Lab.
# These examples have been adapted to run as standalone Python scripts, making
# them suitable for use in various environments, including SysON.
# They showcase practical usage scenarios and may include additional functionality
# or modifications tailored to specific needs.

import requests # <1>
from init_api import parse_arguments
from init_api import init_sysmlv2_api
from fetch_commits import get_last_commit_id

def fetch_elements(host, project_id): # <2>
commit_id = get_last_commit_id(host, project_id)
# API endpoint to fetch elements of the commit
element_get_url = f"{host}/projects/{project_id}/commits/{commit_id}/elements" # <3>
# Send GET request to retrieve elements
response = requests.get(element_get_url) # <4>
if response.status_code == 200: # <5>
elements = response.json()
for element in elements:
print(f"Element ID: {element['@id']}, Name: {element['name']}")
return elements
else:
print(f"Error fetching elements: {response.status_code} - {response.text}")
return None

if __name__ == "__main__":
args = parse_arguments()
host = init_sysmlv2_api()
project_id = args.project_id
fetch_elements(host, project_id)
26 changes: 26 additions & 0 deletions doc/content/modules/developer-guide/examples/fetch_projects.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# These examples are adapted from the SysML v2 API Cookbook, available at
# https://github.com/Systems-Modeling/SysML-v2-API-Cookbook, maintained by the
# Object Management Group (OMG).
# The original cookbook is designed for use with Jupyter Lab.
# These examples have been adapted to run as standalone Python scripts, making
# them suitable for use in various environments, including SysON.
# They showcase practical usage scenarios and may include additional functionality
# or modifications tailored to specific needs.

import requests # <1>
from init_api import init_sysmlv2_api

def fetch_projects(host): # <2>
projects_url = f"{host}/projects" # <3>
response = requests.get(projects_url) # <4>
if response.status_code == 200: # <5>
projects = response.json()
for project in projects:
print(f"Project Name: {project['name']}, ID: {project['@id']}")
else:
print(f"Error fetching projects: {response.status_code} - {response.text}")

if __name__ == "__main__":
host = init_sysmlv2_api()
# Get the projects
fetch_projects(host)
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# These examples are adapted from the SysML v2 API Cookbook, available at
# https://github.com/Systems-Modeling/SysML-v2-API-Cookbook, maintained by the
# Object Management Group (OMG).
# The original cookbook is designed for use with Jupyter Lab.
# These examples have been adapted to run as standalone Python scripts, making
# them suitable for use in various environments, including SysON.
# They showcase practical usage scenarios and may include additional functionality
# or modifications tailored to specific needs.

from init_api import parse_arguments
from init_api import init_sysmlv2_api
from fetch_commits import get_last_commit_id
from get_owned_elements import get_element

def get_member_features(host, project_id, commit_id, element_id, member_type, indent):
# Fetch the element
element_data = get_element(host, project_id, commit_id, element_id, indent)
if element_data:
element_type = element_data ['@type']

if element_type == member_type:
print(element_data)
# Feature memberships
element_features = element_data['ownedFeature']
if len(element_features) > 0:
for feature in element_features:
get_member_features(host, project_id, commit_id, feature['@id'], member_type, indent + " ")

if __name__ == "__main__":
args = parse_arguments()
host = init_sysmlv2_api()
project_id = args.project_id
commit_id = get_last_commit_id(host, project_id)
element_id = args.element_id

# Get Parts Tree
print("Parts Tree:")
get_member_features(host, project_id, commit_id, element_id, 'PartUsage', " ")

# Get Behaviour Tree
print("Behaviours Tree:")
get_member_features(host, project_id, commit_id, element_id, 'ActionUsage', " ")

# Get Requirements Tree
print("Requirements Tree:")
get_member_features(host, project_id, commit_id, element_id, 'RequirementUsage', " ")
66 changes: 66 additions & 0 deletions doc/content/modules/developer-guide/examples/get_owned_elements.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# These examples are adapted from the SysML v2 API Cookbook, available at
# https://github.com/Systems-Modeling/SysML-v2-API-Cookbook, maintained by the
# Object Management Group (OMG).
# The original cookbook is designed for use with Jupyter Lab.
# These examples have been adapted to run as standalone Python scripts, making
# them suitable for use in various environments, including SysON.
# They showcase practical usage scenarios and may include additional functionality
# or modifications tailored to specific needs.

import requests
from init_api import parse_arguments
from init_api import init_sysmlv2_api
from fetch_commits import get_last_commit_id

# Function to fetch an element and print its name and type
def get_element(host, project_id, commit_id, element_id, indent):
# Fetch the element in the given commit of the given project
element_url = f"{host}/projects/{project_id}/commits/{commit_id}/elements/{element_id}" # <3>
response = requests.get(element_url) # <1>

if response.status_code == 200:
element_data = response.json()
element_name_to_print = element_data['name'] if element_data['name'] else 'N/A'
element_id = element_data ['@id']
element_type = element_data ['@type']
print(f"{indent} - {element_name_to_print} (id = {element_id} , type = {element_type})") # <2>
return element_data
else:
return None

# Fetches immediate owned elements for a given element
def get_owned_elements_immediate(host, project_id, commit_id, element_id, indent):
element_data = get_element(host, project_id, commit_id, element_id, indent)
if element_data:
owned_elements = element_data['ownedElement']
if len(owned_elements) > 0:
for owned_element in owned_elements:
get_element(host, project_id, commit_id, owned_element['@id'], indent + ' ')
else:
print(f"Unable to fetch element with id '{element_id}' in commit '{commit_id}' of project '{project_id}'")

# Fetches owned elements recursively for a given element
def get_owned_elements(host, project_id, commit_id, element_id, indent):
element_data = get_element(host, project_id, commit_id, element_id, indent)
if element_data: # <3>
owned_elements = element_data['ownedElement']
if len(owned_elements) > 0:
for owned_element in owned_elements:
get_owned_elements(host, project_id, commit_id, owned_element['@id'], indent+' ')
else:
print(f"Unable to fetch element with id '{element_id}' in commit '{commit_id}' of project '{project_id}'") # <4>

if __name__ == "__main__":
args = parse_arguments()
host = init_sysmlv2_api()
project_id = args.project_id
commit_id = get_last_commit_id(host, project_id)
element_id = args.element_id

#Get owned elements (immediate) for the given element in the given commit of the given project
print("Immediate Owned Elements:")
get_owned_elements_immediate(host, project_id, commit_id, element_id, '')

# Get owned elements (recursive) for the given element in the given commit of the given project
print("\nRecursive Owned Elements:")
get_owned_elements(host, project_id, commit_id, element_id, '')
29 changes: 29 additions & 0 deletions doc/content/modules/developer-guide/examples/init_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# These examples are adapted from the SysML v2 API Cookbook, available at
# https://github.com/Systems-Modeling/SysML-v2-API-Cookbook, maintained by the
# Object Management Group (OMG).
# The original cookbook is designed for use with Jupyter Lab.
# These examples have been adapted to run as standalone Python scripts, making
# them suitable for use in various environments, including SysON.
# They showcase practical usage scenarios and may include additional functionality
# or modifications tailored to specific needs.
import argparse

def init_sysmlv2_api():
host = "http://localhost:8080/api/rest" # Replace with your actual API host URL # <1>
return host

def parse_arguments():
# Parse command-line arguments
parser = argparse.ArgumentParser()
parser.add_argument(
"project_id",
type=str,
help="The project ID.",
)
parser.add_argument(
"element_id",
type=str,
nargs="?", # This makes element_id optional
help="The element ID (optional).",
)
return parser.parse_args()
63 changes: 63 additions & 0 deletions doc/content/modules/developer-guide/pages/api-cookbook.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
= APIs cookbook
The APIs cookbook offers a collection of practical examples and step-by-step instructions to help you interact with {product}’s REST APIs.
It includes ready-to-use code snippets and explanations, allowing you to integrate with other tools, automate tasks, and explore advanced features efficiently.
Each recipe aims for clarity, ease of use, and customizability for different use cases.

== Setup instructions
To get started with the examples, Python is used to interact with {product}’s features and data.
Python offers a powerful way to automate tasks, handle API calls, and process data, making it an ideal choice for this purpose.
Follow the steps after to set up your environment and get everything ready to run the provided code snippets.

=== Step 1: Install required Python libraries
Confirm you have the following Python libraries installed before running the code snippets:

* `requests`: For making HTTP requests to the {sysmlv2} API.
* `pandas`: For organizing and manipulating data.

To install these libraries, run:

`pip install requests pandas`

=== Step 2: Configure {sysmlv2} API access

[source,python]
.init_api.py
----
include::example$init_api.py[]
----

TIP: Replace `http://localhost:8080` with the actual URL of your API server if hosted elsewhere.

*What this code does*:

<1> Define the base host: Assigns the variable `host` with the base URL of the {sysmlv2} API server.

[NOTE]
====
In the examples, the {product} server uses a randomization function to generate unique IDs, so outputs can differ when you run the examples on your project.
====

Other code snippets use this function.
To run it, see the following section about recipes.

=== Step 3: Test code snippets
Once you have configured the {sysmlv2} API access, you can start testing the xref:developer-guide:api-cookbook.adoc#recipes[recipes].

=== Troubleshooting

. *Error Handling*:
** Check endpoint URLs, `project_id`, `commit_id`, and `authentication` tokens if the API returns errors: for example, 400 or 500 status codes.
** Confirm the API is running.
. *Empty Responses*:
** Verify that queried elements exist within the specified project and commit.
** Use the {product} web interface for visual inspection.
. *Recursive Function Depth*:
** For large models, manage recursion depth appropriately.
** Change the logic to handle large datasets by limiting recursion depth.

[#recipes]
== Recipes

include::developer-guide:project_commit_branch_tag_recipe.adoc[leveloffset=+2]

include::developer-guide:element_owned_elements_recipe.adoc[leveloffset=+2]
Loading

0 comments on commit 39d5d48

Please sign in to comment.