You may have read my previous article about generating a Java library to call Jira’s REST APIs, but what about other languages?
Here I’ll cover doing the same with Python.
I will generate a library for Python, and then run through some sample code to create a project, find the “task” issue type in the project, and then create a issue of type “task”.
There are 3rd party Python libraries around that can talk to Jira Cloud. If these work well for you, then that might be a good solution.
Atlassian publishes the Swagger/Open API spec for Jira’s API in real time though. If you need to call a new Jira Cloud API, or act on some feature that is being deprecated, then being able to generate an up-to-date library might be of value to your project.
Just a quick recap: Swagger/Open API is a way of documenting APIs in a standard way. While you can always write your own code to call Jira’s APIs, the APIs change all the time in small ways. Generating a client library from the spec using a code generation tool is a quick way to get started (and easy to update in the future).
If you go to the documentation for the Jira Cloud REST API, you'll see the "…" in the top right. Click that, and you'll see the link for "Download OpenAPI Spec." This is a JSON file that describes the REST API for Jira Cloud. Here I'm using the v2 API so that I can use plain text for the issue description.
I’m going to use swagger-codegen to generate my code. (Read more here)
The actual URL to this file is https://dac-static.atlassian.com/cloud/jira/platform/swagger.v3.json?_v=1.6234.0-0.1265.0. Although swagger-codegen can generate APIs directly from a URL, I recommend saving a local copy of this file. I am going to use a local copy in my examples.
In this post I will deal with APIs common to all Jira project types, but the process is similar for Jira Software's APIs, and Jira Service Desk's APIs.
Once you have downloaded the swagger-v3.v3.json file, the swagger-codegen command to generate a Python client under the current directory is:
swagger-codegen generate \
-i swagger.v3.json \
-l python \
-o .
This will generate a usable client in the current directory, but it’s probably worth tweaking the configuration a little. I’m going to set the package name, and project name (which is used in setup.py).
Create a config.json file that describes your configuration overrides.
{
"packageName": "jira_client",
"projectName": "jira-cloud"
}
Now to generate code using the above config file use:
swagger-codegen generate \
-i swagger.v3.json \
-c config.json \
-l python \
-o .
Run the following to install the library in your virtual environment:
python3 setup.py install
The output directory includes a README.md file that has more details on how you might install it. You may prefer to use pip3 install foldername
.
You may wish to integrate the built code directly into your project, rather that install it as its own library.
While the client code is generated, my recommended best practice is to version control the generated client code.
Why? This helps you to know what changed since the last time you generated it. You can re-generate it from an updated spec file, and your version control system will show you what changed.
For my code example I’m going to assume the library was installed using the package name “jira_client”, and I can just import it directly.
In this example I'm going to
Look up my user
Create a new project where I am the project lead
Find out the issue type ID of “Task” issue type in my project
Create a new issue of type Task in my project, and display the issue key
If you have used the Java client, you will notice that the API and model classes have similar names to the Java version, except with Python naming conventions.
Note: The generated code uses a class called Configuration to specify the configuration when creating the ApiClient. This will clash with a model class called Configuration, so I’m going to import it as ApiConfiguration.
from jira_client import ApiClient
# Configuration is ambiguous
from jira_client.configuration import Configuration as ApiConfiguration
from jira_client.rest import ApiException
from jira_client import ProjectsApi, MyselfApi, IssuesApi
from jira_client.models.create_project_details import CreateProjectDetails
from pprint import pprint
configuration = ApiConfiguration()
configuration.username = 'myemail@atlassian.com'
configuration.password = 'my_application_password'
configuration.host = 'https://myjirahost.atlassian.net/'
# Turn on debug output
configuration.debug = True
api_client = ApiClient(configuration)
# Get my account ID
myself_api = MyselfApi(api_client)
current_user = myself_api.get_current_user()
# Create a new project
projects_api = ProjectsApi(api_client)
details = CreateProjectDetails(
key='JPY',
name='Jira Python',
lead_account_id=current_user.account_id,
project_type_key='business')
project = projects_api.create_project(details)
# Now do a project search, expanding issue types
paged_projects = projects_api.search_projects(
start_at=0,
max_results=100,
query='JPY',
expand="issueTypes")
projects = paged_projects.values
project_result = projects[0]
task_issue_type_id = 0
for issue_type in project_result.issue_types:
if issue_type.name == 'Task':
task_issue_type_id = issue_type.id
print(f"Task issue type is {task_issue_type_id}")
# Now create an issue using the Task issue type
issues_api = IssuesApi(api_client)
project_field = {
"id": project_result.id
}
issue_type_field = {
"id": task_issue_type_id
}
issue_fields = {
"summary": "Learn Python",
"description": "Remember to study up on Python programming",
"project": project_field,
"issuetype": issue_type_field
}
issue_body = {
"fields": issue_fields
}
issue = issues_api.create_issue(issue_body)
print(f"Issue created. Key is {issue.key}")
Now if I log in to my site I should see that there is a project with the key “JPY”, and with a “Learn Python” task.
Ben Kelley
Senior Java Developer
Atlassian
Sydney
5 accepted answers
6 comments