Issue

Supported by Redmine starting from version 1.0

Manager

All operations on the Issue resource are provided by its manager. To get access to it you have to call redmine.issue where redmine is a configured redmine object. See the Configuration about how to configure redmine object.

Create methods

create

redminelib.managers.ResourceManager.create(**fields)

Creates new Issue resource with given fields and saves it to the Redmine.

Parameters:
  • project_id (int or string) – (required). Id or identifier of issue’s project.

  • subject (string) – (required). Issue subject.

  • tracker_id (int) – (optional). Issue tracker id.

  • description (string) – (optional). Issue description.

  • status_id (int) – (optional). Issue status id.

  • priority_id (int) – (optional). Issue priority id.

  • category_id (int) – (optional). Issue category id.

  • fixed_version_id (int) – (optional). Issue version id.

  • is_private (bool) – (optional). Whether issue is private.

  • assigned_to_id (int) – (optional). Issue will be assigned to this user id.

  • watcher_user_ids (list) – (optional). User ids watching this issue.

  • parent_issue_id (int) – (optional). Parent issue id.

  • start_date (string or date object) – (optional). Issue start date.

  • due_date (string or date object) – (optional). Issue end date.

  • estimated_hours (int) – (optional). Issue estimated hours.

  • done_ratio (int) – (optional). Issue done ratio.

  • custom_fields (list) – (optional). Custom fields as [{‘id’: 1, ‘value’: ‘foo’}].

  • uploads (list) – (optional). Uploads as [{'': ''}, ...], accepted keys are:

    • path (required). Absolute file path or file-like object that should be uploaded.

    • filename (optional). Name of the file after upload.

    • description (optional). Description of the file.

    • content_type (optional). Content type of the file.

Returns:

Resource object

>>> from io import BytesIO
>>> issue = redmine.issue.create(
...     project_id='vacation',
...     subject='Vacation',
...     tracker_id=8,
...     description='foo',
...     status_id=3,
...     priority_id=7,
...     assigned_to_id=123,
...     watcher_user_ids=[123],
...     parent_issue_id=345,
...     start_date=datetime.date(2014, 1, 1),
...     due_date=datetime.date(2014, 2, 1),
...     estimated_hours=4,
...     done_ratio=40,
...     custom_fields=[{'id': 1, 'value': 'foo'}, {'id': 2, 'value': 'bar'}],
...     uploads=[{'path': '/absolute/path/to/file'}, {'path': BytesIO(b'I am content of file 2')}]
... )
>>> issue
<redminelib.resources.Issue #123 "Vacation">

new

redminelib.managers.ResourceManager.new()

Creates new empty Issue resource but saves it to the Redmine only when save() is called, also calls pre_create() and post_create() methods of the Resource object. Valid attributes are the same as for create() method above.

Returns:

Resource object

>>> issue = redmine.issue.new()
>>> issue.project_id = 'vacation'
>>> issue.subject = 'Vacation'
>>> issue.tracker_id = 8
>>> issue.description = 'foo'
>>> issue.status_id = 3
>>> issue.priority_id = 7
>>> issue.assigned_to_id = 123
>>> issue.watcher_user_ids = [123]
>>> issue.parent_issue_id = 345
>>> issue.start_date = datetime.date(2014, 1, 1)
>>> issue.due_date = datetime.date(2014, 2, 1)
>>> issue.estimated_hours = 4
>>> issue.done_ratio = 40
>>> issue.custom_fields = [{'id': 1, 'value': 'foo'}, {'id': 2, 'value': 'bar'}]
>>> issue.uploads = [{'path': '/absolute/path/to/file'}, {'path': '/absolute/path/to/file2'}]
>>> issue.save()
<redminelib.resources.Issue #123 "Vacation">

Read methods

get

redminelib.managers.ResourceManager.get(resource_id, **params)

Returns single Issue resource from Redmine by its id.

Parameters:
  • resource_id (int) – (required). Id of the issue.

  • include (list) – (optional). Fetches associated data in one call. Accepted values:

    • children

    • attachments

    • relations

    • changesets

    • journals

    • watchers (requires Redmine >= 2.3.0)

    • allowed_statuses (requires Redmine >= 5.0.0)

Returns:

Resource object

>>> issue = redmine.issue.get(34441, include=['children', 'journals', 'watchers'])
>>> issue
<redminelib.resources.Issue #34441 "Vacation">

Hint

Issue resource object provides you with on demand includes. On demand includes are the other resource objects wrapped in a ResourceSet which are associated with an Issue resource object. Keep in mind that on demand includes are retrieved in a separate request, that means that if the speed is important it is recommended to use get() method with include keyword argument. On demand includes provided by the Issue resource object are the same as in the get() method above:

>>> issue = redmine.issue.get(34441)
>>> issue.journals
<redminelib.resultsets.ResourceSet object with IssueJournal resources>

Hint

Issue resource object provides you with some relations. Relations are the other resource objects wrapped in a ResourceSet which are somehow related to an Issue resource object. The relations provided by the Issue resource object are:

>>> issue = redmine.issue.get(34441)
>>> issue.time_entries
<redminelib.resultsets.ResourceSet object with TimeEntry resources>

all

redminelib.managers.ResourceManager.all(**params)

Returns all Issue resources (both open and closed) from Redmine, to return issues with specific status from Redmine use filter() method below.

Parameters:
  • sort (string) – (optional). Column to sort. Append :desc to invert the order.

  • limit (int) – (optional). How much resources to return.

  • offset (int) – (optional). Starting from what resource to return the other resources.

  • include (list) – (optional). Fetches associated data in one call. Accepted values:

    • relations

    • attachments (requires Redmine >= 3.4.0)

Returns:

ResourceSet object

>>> issues = redmine.issue.all(sort='category:desc', include=['relations', 'attachments'])
>>> issues
<redminelib.resultsets.ResourceSet object with Issue resources>

filter

redminelib.managers.ResourceManager.filter(**filters)

Returns Issue resources that match the given lookup parameters.

Parameters:
  • issue_id (int or string) – (optional). Find issue or issues by id (separated by ,)

  • parent_id (int) – (optional). Get issues whose parent issue is given id.

  • project_id (int or string) – (optional). Id or identifier of issue’s project.

  • subproject_id (int or string) – (optional). Get issues from the subproject with the given id. You can use project_id=X, subproject_id=!* to get only the issues of a given project and none of its subprojects.

  • tracker_id (int) – (optional). Get issues from the tracker with given id.

  • query_id (int) – (optional). Get issues for the given query id if the project_id is given.

  • status_id (int or string) – (optional). Get issues with given status id. One of:

    • open - open issues

    • closed - closed issues

    • * - all issues

    • id - status id

  • author_id (int) – (optional). Get issues which are authored by the given user id.

  • assigned_to_id (int) – (optional). Get issues which are assigned to the given user id. To get the issues assigned to the user whose credentials were used to access the API pass me as a string.

  • cf_x (string) – (optional). Get issues with given value for custom field with an ID of x. The ~ sign can be used before the value to find issues containing a string in a custom field.

  • sort (string) – (optional). Column to sort. Append :desc to invert the order.

  • limit (int) – (optional). How much resources to return.

  • offset (int) – (optional). Starting from what resource to return the other resources.

  • include (list) – (optional). Fetches associated data in one call. Accepted values:

    • relations

    • attachments (requires Redmine >= 3.4.0)

Returns:

ResourceSet object

>>> issues = redmine.issue.filter(
...     project_id='vacation',
...     subproject_id='!*',
...     created_on='><2012-03-01|2012-03-07',
...     cf_22='~foo',
...     sort='category:desc'
... )
>>> issues
<redminelib.resultsets.ResourceSet object with Issue resources>
>>> issues = redmine.issue.filter(
...     project_id='vacation',
...     query_id=326
... )
>>> issues
<redminelib.resultsets.ResourceSet object with Issue resources>

Hint

You can also get issues from a Project, Tracker, IssueStatus or User resource objects directly using issues relation:

>>> project = redmine.project.get('vacation')
>>> project.issues
<redminelib.resultsets.ResourceSet object with Issue resources>

New in version 2.5.0.

Apart from issues relation a User resource object provides issues_assigned which is an alias to issues relation and issues_authored relation which returns Issue objects authored by a user:

>>> user = redmine.user.get(9)
>>> user.issues
<redminelib.resultsets.ResourceSet object with Issue resources>
>>> user.issues_assigned
<redminelib.resultsets.ResourceSet object with Issue resources>
>>> user.issues_authored
<redminelib.resultsets.ResourceSet object with Issue resources>

Update methods

update

redminelib.managers.ResourceManager.update(resource_id, **fields)

Updates values of given fields of an Issue resource and saves them to the Redmine.

Parameters:
  • resource_id (int) – (required). Issue id.

  • project_id (int) – (optional). Issue project id.

  • subject (string) – (optional). Issue subject.

  • tracker_id (int) – (optional). Issue tracker id.

  • description (string) – (optional). Issue description.

  • notes (string) – (optional). Issue journal note.

  • private_notes (bool) – (optional). Whether notes are private.

  • status_id (int) – (optional). Issue status id.

  • priority_id (int) – (optional). Issue priority id.

  • category_id (int) – (optional). Issue category id.

  • fixed_version_id (int) – (optional). Issue version id.

  • is_private (bool) – (optional). Whether issue is private.

  • assigned_to_id (int) – (optional). Issue will be assigned to this user id.

  • parent_issue_id (int) – (optional). Parent issue id.

  • start_date (string or date object) – (optional). Issue start date.

  • due_date (string or date object) – (optional). Issue end date.

  • estimated_hours (int) – (optional). Issue estimated hours.

  • done_ratio (int) – (optional). Issue done ratio.

  • custom_fields (list) – (optional). Custom fields as [{‘id’: 1, ‘value’: ‘foo’}].

  • uploads (list) – (optional). Uploads as [{'': ''}, ...], accepted keys are:

    • path (required). Absolute file path or file-like object that should be uploaded.

    • filename (optional). Name of the file after upload.

    • description (optional). Description of the file.

    • content_type (optional). Content type of the file.

Returns:

True

>>> from io import BytesIO
>>> redmine.issue.update(
...     1,
...     project_id=1,
...     subject='Vacation',
...     tracker_id=8,
...     description='foo',
...     notes='A journal note',
...     private_notes=True,
...     status_id=3,
...     priority_id=7,
...     assigned_to_id=123,
...     parent_issue_id=345,
...     start_date=datetime.date(2014, 1, 1),
...     due_date=datetime.date(2014, 2, 1),
...     estimated_hours=4,
...     done_ratio=40,
...     custom_fields=[{'id': 1, 'value': 'foo'}, {'id': 2, 'value': 'bar'}],
...     uploads=[{'path': '/absolute/path/to/file'}, {'path': BytesIO(b'I am content of file 2')}]
... )
True

save

redminelib.resources.Issue.save(**attrs)

Saves the current state of an Issue resource to the Redmine. Attrs that can be changed are the same as for update() method above.

Returns:

Resource object

>>> issue = redmine.issue.get(1)
>>> issue.project_id = 1
>>> issue.subject = 'Vacation'
>>> issue.tracker_id = 8
>>> issue.description = 'foo'
>>> issue.notes = 'A journal note'
>>> issue.private_notes = True
>>> issue.status_id = 3
>>> issue.priority_id = 7
>>> issue.assigned_to_id = 123
>>> issue.parent_issue_id = 345
>>> issue.start_date = datetime.date(2014, 1, 1)
>>> issue.due_date = datetime.date(2014, 2, 1)
>>> issue.estimated_hours = 4
>>> issue.done_ratio = 40
>>> issue.custom_fields = [{'id': 1, 'value': 'foo'}, {'id': 2, 'value': 'bar'}]
>>> issue.uploads = [{'path': '/absolute/path/to/file'}, {'path': '/absolute/path/to/file2'}]
>>> issue.save()
<redminelib.resources.Issue #1 "Vacation">

New in version 2.1.0: Alternative syntax was introduced.

>>> issue = redmine.issue.get(1).save(
...     project_id=1,
...     subject='Vacation',
...     tracker_id=8,
...     description='foo',
...     notes='A journal note',
...     private_notes=True,
...     status_id=3,
...     priority_id=7,
...     assigned_to_id=123,
...     parent_issue_id=345,
...     start_date=datetime.date(2014, 1, 1),
...     due_date=datetime.date(2014, 2, 1),
...     estimated_hours=4,
...     done_ratio=40,
...     custom_fields=[{'id': 1, 'value': 'foo'}, {'id': 2, 'value': 'bar'}],
...     uploads=[{'path': '/absolute/path/to/file'}, {'path': '/absolute/path/to/file2'}]
... )
>>> issue
<redminelib.resources.Issue #1 "Vacation">

Delete methods

delete

redminelib.managers.ResourceManager.delete(resource_id)

Deletes single Issue resource from Redmine by its id.

Parameters:

resource_id (int) – (required). Issue id.

Returns:

True

>>> redmine.issue.delete(1)
True
redminelib.resources.Issue.delete()

Deletes current Issue resource object from Redmine.

Returns:

True

>>> issue = redmine.issue.get(1)
>>> issue.delete()
True

Copying

New in version 2.5.0.

redminelib.managers.IssueManager.copy(resource_id, project_id=None, link_original=True, include=('subtasks', 'attachments'), **fields)

Copies single Issue resource by its id using the same API as Redmine’s GUI copying which means copying is done the most efficient way possible. By default links original to a copy via relations and copies both subtasks and attachments.

Parameters:
  • resource_id (int) – (required). Issue id.

  • project_id (int or string) – (required). Id or identifier of issue’s project.

  • link_original (bool) – (optional). Whether to link the original issue to a copy via relations.

  • include (list) – (optional). Additional data to copy or None. Accepted values:

    • subtasks

    • attachments

  • fields (dict) – (optional). Accepts the same fields as Issue’s create() method to add or modify original values.

Returns:

Resource object

>>> copy = redmine.issue.copy(1, project_id='vacation', link_original=False, include=['attachments'])
>>> copy
<redminelib.resources.Issue #124 "Vacation">
redminelib.resources.Issue.copy(link_original=True, include=('subtasks', 'attachments'), **fields)

Copies current Issue resource object.

Returns:

Resource object

>>> issue = redmine.issue.get(123)
>>> copy = issue.copy(subject='this is a copy')
>>> copy
<redminelib.resources.Issue #124 "this is a copy">

Export

New in version 2.0.0.

redminelib.resources.Issue.export(fmt, savepath=None, filename=None)

Exports Issue resource in one of the following formats: atom, pdf

Parameters:
  • fmt (string) – (required). Format to use for export.

  • savepath (string) – (optional). Path where to save the file.

  • filename (string) – (optional). Name that will be used for the file.

Returns:

String or Object

>>> issue = redmine.issue.get(123)
>>> issue.export('pdf', savepath='/home/jsmith')
'/home/jsmith/123.pdf'
redminelib.resultsets.ResourceSet.export(fmt, savepath=None, filename=None, columns=None, encoding='UTF-8')

Exports a resource set of Issue resources in one of the following formats: atom, pdf, csv

Parameters:
  • fmt (string) – (required). Format to use for export.

  • savepath (string) – (optional). Path where to save the file.

  • filename (string) – (optional). Name that will be used for the file.

  • columns (iterable or string) – (optional). Iterable of column names or “all” string for all available columns or “all_gui” string for GUI like behaviour or iterable of elements with “all_gui” string and additional columns to export.

  • encoding – (optional). Encoding that will be used for the result file.

Returns:

String or Object

>>> issues = redmine.issue.all()
>>> issues.export('csv', savepath='/home/jsmith', filename='issues.csv', columns='all')
'/home/jsmith/issues.csv'

Journals

The history of an issue is represented as a ResourceSet of IssueJournal resources. Currently the following operations are possible:

create

To create a new record in issue history, i.e. new journal:

redmine.issue.update(1, notes='new note')
True

read

Recommended way to access issue journals is through associated data includes:

>>> issue = redmine.issue.get(1, include=['journals'])
>>> issue.journals
<redminelib.resultsets.ResourceSet object with IssueJournal resources>

But they can also be accessed through on demand includes:

>>> issue = redmine.issue.get(1)
>>> issue.journals
<redminelib.resultsets.ResourceSet object with IssueJournal resources>

After that they can be used as usual:

>>> for journal in issue.journals:
...     print(journal.id, journal.notes)
...
1 foobar
2 lalala
3 hohoho

update

New in version 2.4.0.

To update notes attribute (the only attribute that can be updated) of a journal:

>>> issue = redmine.issue.get(1, include=['journals'])
>>> for journal in issue.journals:
...     journal.save(notes='setting notes to a new value')
...

Or if you know the id beforehand:

>>> redmine.issue_journal.update(1, notes='setting notes to a new value')
True

delete

New in version 2.4.0.

To delete a journal set its notes attribute to empty string:

>>> issue = redmine.issue.get(1, include=['journals'])
>>> for journal in issue.journals:
...     journal.save(notes='')
...

Or if you know the id beforehand:

>>> redmine.issue_journal.update(1, notes='')
True

Note

You can only delete a journal that doesn’t have the associated details attribute.

Watchers

Python-Redmine provides 2 methods to work with issue watchers:

add

redminelib.resources.Issue.Watcher.add(user_id)

Adds a user to issue watchers list by its id.

Parameters:

user_id (int) – (required). User id.

Returns:

True

>>> issue = redmine.issue.get(1)
>>> issue.watcher.add(1)
True

remove

redminelib.resources.Issue.Watcher.remove(user_id)

Removes a user from issue watchers list by its id.

Parameters:

user_id (int) – (required). User id.

Returns:

True

>>> issue = redmine.issue.get(1)
>>> issue.watcher.remove(1)
True