Manipuler Redmine à l'aide de Python Redmine

Python Redmine

Python Redmine est une bibliothèque Python qui communique avec Redmine.

Il présente les caractéristiques suivantes.

・ Prise en charge à 100% des fonctions de l'API Redmine (Vous pouvez même créer un projet) · Python 2.7, 3.4-3.7

Les détails sont décrits ci-dessous. https://python-redmine.com/

Comment installer

Il peut être installé à l'aide de pip ou easy_install.

$ pip install python-redmine

Ou

$ easy_install python-redmine

Comme paramètre côté Redmine, cochez «Activer le service Web par l'API REST» dans l'onglet API de l'écran «Administration» -> «Paramètres».

image.png

Si vous activez l'API ici, vous pouvez vérifier la clé API sur l'écran des paramètres personnels. image.png

échantillon

Un exemple est décrit ci-dessous. Cet exemple est confirmé avec Python 3.7 + python redmine 2.2.1 + Redmine 4.0.3. Stable sous Windows.

Méthode d'authentification

Vous pouvez vous connecter à redmine en spécifiant un nom d'utilisateur et un mot de passe.

from redminelib import Redmine
redmine = Redmine('http://localhost/redmine', username='admin', password='admin')

Vous pouvez également vous connecter à l'aide de la clé API comme suit.

from redminelib import Redmine
redmine = Redmine('http://localhost/redmine', key='e4a413a3b7a3c238102b7393c035bbc5f5eb6409')

Opération de ticket

Voir ci-dessous pour les opérations de billetterie https://python-redmine.com/resources/issue.html

Créer un ticket

Vous pouvez créer un ticket en créant un objet ticket avec redmine.issue.new (), en y définissant des propriétés et en l'enregistrant.

import datetime
from redminelib import Redmine
redmine = Redmine('http://192.168.0.200/', key='60076966cebf71506ae3f2391da649235a2b1d46')
issue = redmine.issue.new()
issue.project_id = 'Test1'
issue.subject = 'Matière'
issue.tracker_id = 1     #Traqueur
issue.description = 'Montrez le contenu du ticket.\n Les sauts de ligne sont également possibles.'
issue.status_id = 1      #statut
issue.priority_id = 1    #priorité
issue.assigned_to_id = 1 #ID de la personne responsable
issue.watcher_user_ids = [1] #ID de l'utilisateur à regarder
issue.parent_issue_id = 12     #ID du ticket parent
issue.start_date = datetime.date(2014, 1, 1) #date de début
issue.due_date = datetime.date(2014, 2, 1)   #Date limite
issue.estimated_hours = 4   #Effectif attendu
issue.done_ratio = 40
issue.custom_fields = [{'id': 1, 'value': 'foo'}]
issue.uploads = [{'path': 'C:\\dev\\python3\\redmine\\test.txt'}]
issue.custom_fields = [{'id': 1, 'value': 'foo'}]
issue.save()

Obtenez un seul billet

Spécifiez l'ID du ticket avec redmine.issue.get (). Si ça n'existe pas redmine.exceptions.ResourceNotFoundError Une exception se produit.

import datetime
from redminelib import Redmine
from redminelib.exceptions import ResourceNotFoundError

redmine = Redmine('http://192.168.0.200/', key='60076966cebf71506ae3f2391da649235a2b1d46')
try:
    issue = redmine.issue.get(60)
    print (dir(issue))
    print ('id:%d' % issue.id)
    print ('project:%s' % issue.project.name)
    print ('project_id:%d' % issue.project.id)
    print ('subject:%s' % issue.subject)
    print ('tracker:%s' % issue.tracker.name)
    print ('tracker_id:%d' % issue.tracker.id)
    print ('description:%s' % issue.description)
    print ('status:%s' % issue.status.name)
    print ('status:%d' % issue.status.id)
    print ('author:%s' % issue.author.name)
    print ('author_id:%d' % issue.author.id)
    if hasattr(issue, 'assigned'):
        print ('assigned:%s' % issue.assigned_to.name)
        print ('assigned_id:%d' % issue.assigned_to.id)
    print ('watcher--------')
    for u in issue.watchers:
        print (' %d:%s' % (u.id, u.name))
    print ('Date de création:%s' % issue.created_on)
    print ('Date de mise à jour:%s' % issue.updated_on)
    if hasattr(issue, 'start_date'):
        print ('start_date:%s' % issue.start_date)
    if hasattr(issue, 'due_date'):
        print ('issue_date:%s' % issue.due_date)
    if hasattr(issue, 'issue.estimated_hours'):
        print ('estimated_hours:%d' % issue.estimated_hours)
    print ('Heures d'ouverture:%d' % issue.spent_hours)
    print ('Enregistrement du temps de travail----------')
    for t in issue.time_entries:
        print('  ID:%d' % t.id)
        print('Activités:%s' % t.activity)
        print('commentaire:%s' % str(t.comments))
        print('Date de création:%s' % t.created_on)
        print('temps:%s' %t.hours)
        print('ID de billets:%s' % t.issue)
        print('ID du projet:%s' % t.project)
        print('Date:%s' % t.spent_on)
        print('Date de mise à jour:%s' % t.updated_on)
        print('  user:%d %s' % (t.user.id,t.user.name)) 
    print ('done_ratio:%d' % issue.done_ratio) 
    print ('priority:%s' % issue.priority.name)
    print ('priority_id:%d' % issue.priority.id)
    print ('custom_fields----')
    for c in issue.custom_fields:
        print ('  %d:%s = %s' % (c.id, c.name, c.value))
    print ('attachements---')
    for f in issue.attachments:
        print ('  id:%d' % (f.id))
        print ('  author:%s' % (f.author)) 
        print ('  content_url:%s' % (f.content_url))
        print ('  created_on:%s' % (f.created_on))
        print ('  description:%s' % (f.description))
        print ('  filename:%s' % (f.filename))
        print ('  filesize:%d' % (f.filesize))
        print ('  ---------------')
    print ('changeset---')
    for c in issue.changesets:
        #Journal de validation stocké en tant que type de dictionnaire
        print ('  %s' % c)
    if hasattr(issue, 'parent'):
        print ('parent:%s' % issue.parent)
    print ('children----------')
    for c in issue.children:
        print ('  %s:%s' % (c.id, c.subject))
    print ('relation----------')
    for r in issue.relations:
        print ('  %d:%d->%d(%s)' % (r.id, r.issue_id, r.issue_to_id, r.relation_type)) 
except (ResourceNotFoundError):
    print ('Not found')

Les éléments pour lesquels l'entrée est omise n'ont pas de propriétés proprement dites. Par conséquent, vous devez vérifier l'existence avec hasattr.

Les informations utilisateur des observateurs, du responsable et du créateur ne contiennent que les informations minimales nécessaires. Si vous souhaitez obtenir le nom de connexion, etc., obtenez les détails de l'utilisateur à partir de l'ID utilisateur comme suit.

user = redmine.user.get(u.id)

Obtenez tous les billets

Il peut être obtenu avec redmine.issue.all (). Les paramètres qui peuvent être omis sont les suivants.

sort (chaîne): ordre de tri limit (entier): limite supérieure du nombre d'acquisitions offset (entier): position de début d'acquisition

import datetime
from redminelib import Redmine

redmine = Redmine('http://192.168.0.200/', key='60076966cebf71506ae3f2391da649235a2b1d46')
issues = redmine.issue.all(sort='category:desc')
for issue in issues:
  print ('%d:%s' % (issue.id, issue.subject))

Obtention d'un ticket pour des conditions spécifiques

Les tickets avec des conditions spécifiques peuvent être extraits en utilisant redmine.issue.filter. Dans ce qui suit, le responsable extrait son ticket.

import datetime
from redminelib import Redmine

redmine = Redmine('http://192.168.0.200/', key='60076966cebf71506ae3f2391da649235a2b1d46')
issues = redmine.issue.filter(assigned_to_id='me')
for issue in issues:
  print ('%d:%s' % (issue.id, issue.subject))

Vous pouvez également effectuer une recherche par requête enregistrée à l'aide de query_id.

Opérateur pour la requête

Après tout, vous ne faites que lire l'API REST, vous pouvez donc l'utiliser avec des opérateurs pris en charge par Redmine. http://www.redmine.org/projects/redmine/wiki/Rest_Issues

Dans le document ci-dessus, des exemples tels que "! \ " ">" "<" "" "~" Sont présentés.

Ainsi, par exemple, pour obtenir une tâche qui n'est attribuée à personne, la mise en œuvre est la suivante.

import datetime
from redminelib import Redmine

redmine = Redmine('http://192.168.0.200/', key='60076966cebf71506ae3f2391da649235a2b1d46')
issues = redmine.issue.filter(assigned_to_id='!*')
for issue in issues:
  print ('%d:%s' % (issue.id, issue.subject))

Aussi, si vous souhaitez confier la tâche à un responsable autre que vous-même, ce sera comme suit.

import datetime
from redminelib import Redmine

redmine = Redmine('http://192.168.0.200/', key='60076966cebf71506ae3f2391da649235a2b1d46')
issues = redmine.issue.filter(assigned_to_id='!me')
for issue in issues:
  print ('%d:%s' % (issue.id, issue.subject))

Nous pouvons voir que divers conditionnements sont possibles en utilisant des opérateurs tels que le refus et la spécification de plage, mais le problème est que la documentation de l'API REST ne nous dit pas de quel type d'opérateur il s'agit.

Par conséquent, il est nécessaire de se référer au code réel.

redmine/app/models/query.rb https://github.com/redmine/redmine/blob/9746ab7e5be2db5e2d233ee37365cf21ba4b893a/app/models/query.rb#L254

Si vous regardez cette implémentation, vous pouvez voir quels types d'opérateurs sont définis. Cependant, tous les éléments ne peuvent pas être utilisés par tous les opérateurs. Par exemple, dans le sujet, "\ *: all", "! \ *: None" et "~: include" peuvent être utilisés, mais "^: begin with" ne peut pas être utilisé. Que cela puisse être utilisé ou non est les mêmes que les conditions qui peuvent être effectuées sur l'écran de réglage du filtre ci-dessous. image.png

Renouvellement des billets

Les tickets obtenus avec redmine.issue.get peuvent être modifiés et enregistrés. L'exemple suivant est un exemple de modification de l'état du ticket.

# -*- coding: utf-8 -*-
import datetime
from redmine import Redmine

redmine = Redmine('http://localhost/redmine', key='e4a413a3b7a3c238102b7393c035bbc5f5eb6409')
issue = redmine.issue.get(51)
issue.status_id = 2
issue.save()

Manipulation du temps de travail

Voir ci-dessous pour les opérations sur le temps de travail https://python-redmine.com/resources/time_entry.html

Obtenez du temps de travail

Voici un exemple d'énumération des heures de travail.

import datetime
from redminelib import Redmine

redmine = Redmine('http://192.168.0.200/', key='60076966cebf71506ae3f2391da649235a2b1d46')
time_entries = redmine.time_entry.all()
for t in time_entries:
    print('  ID:%d' % t.id)
    print('Activités:%s' % t.activity)
    print('commentaire:%s' % str(t.comments))
    print('Date de création:%s' % t.created_on)
    print('temps:%s' %t.hours)
    print('ID de billets:%s' % t.issue)
    print('ID du projet:%s' % t.project)
    print('Date:%s' % t.spent_on)
    print('Date de mise à jour:%s' % t.updated_on)
    print('  user:%d %s' % (t.user.id,t.user.name))
    print('Classification du travail%d %s' % (t.activity.id, t.activity.name))

Enregistrement du temps de travail

Un exemple d'enregistrement du temps de travail est présenté ci-dessous.

import datetime
from redminelib import Redmine

redmine = Redmine('http://192.168.0.200/', key='60076966cebf71506ae3f2391da649235a2b1d46')
time_entry = redmine.time_entry.new()
time_entry.issue_id = 60
time_entry.spent_on = datetime.date(2014, 1, 14)
time_entry.hours = 3
time_entry.activity_id = 4
time_entry.comments = 'hello'
time_entry.activity_id = 8
time_entry.save()

Résumé

Cette fois, nous n'avons vérifié qu'une partie de l'API fournie, mais il a été confirmé que les opérations pouvant être effectuées sur l'écran Web sont couvertes.

En utilisant Python Redmine, vous pouvez vous attendre à pouvoir utiliser Redmine librement avec Python. On peut s'attendre à ce que ce qui suit puisse être réalisé.

-Émission d'un ticket du programme lorsque le test automatique échoue ・ Conversion automatique des documents de conception écrits dans Excel vers Wiki -Agréger les heures de travail et notifier un autre système.

c'est tout

Recommended Posts

Manipuler Redmine à l'aide de Python Redmine
Commencez à utiliser Python
Scraping à l'aide de Python
Essayez d'utiliser Excel en utilisant Python (Xlwings)
Exploitez Filemaker depuis Python
Séquence de Fibonacci utilisant Python
Utiliser Kinesis avec Python
Nettoyage des données à l'aide de Python
Faites fonctionner le neutron de Python!
Utilisation des packages Python #external
Câblage Communication Pi-SPI avec Python
Faire fonctionner Blender avec Python
Calcul de l'âge à l'aide de python
Faire fonctionner LXC depuis Python
Rechercher sur Twitter avec Python
Identification de nom à l'aide de python
Notes sur l'utilisation de sous-processus Python
Essayez d'utiliser Tweepy [Python2.7]
Utiliser Excel avec Python (1)
Utiliser Excel avec Python (2)
Enregistrez des tickets avec l'API de Redmine en utilisant des requêtes Python
mémo python utilisant l'opérateur perl-ternaire
Scraping à l'aide de Python 3.5 async / await
Exploitez Excel avec Python open pyxl
Enregistrer des images à l'aide de requêtes python3
Exploitez TwitterBot avec Lambda, Python
[S3] CRUD avec S3 utilisant Python [Python]
[Python] Essayez d'utiliser le canevas de Tkinter
Utilisation de Quaternion avec Python ~ numpy-quaternion ~
Essayez d'utiliser Kubernetes Client -Python-
notes python pour l'utilisation de variables spéciales perl
[Python] Utilisation d'OpenCV avec Python (basique)
Scraping à l'aide de la syntaxe Python 3.5 Async
Surveillance des changements de site Web à l'aide de python
[Note] Faites fonctionner MongoDB avec Python
Publier sur Twitter en utilisant Python
Commencez à Selenium en utilisant python
Algorithme de recherche utilisant word2vec [python]
Changer la version de python à l'aide de pyenv
python: principes de base de l'utilisation de scikit-learn ①
# 1 [python3] Calcul simple à l'aide de variables
Créer des tickets JIRA en utilisant Python
Contrôle d'instruments à l'aide de Python [pyvisa]
Manipulez les feuilles de calcul localement à l'aide de Python
mémo python utilisant perl --join
Web scraping avec Selenium (Python)
[Python] Validation de JSON avec Voluptuous
[Python] [SQLite3] Exploiter SQLite avec Python (basique)
Diffusion sur LINE en utilisant python
Analyse de données à l'aide de pandas python
Traduit à l'aide de googletrans en Python
Utilisation du mode Python dans le traitement
Utiliser OpenCV avec Python @Mac
[Python] Jeu de tir avec pyxel
Enregistrer le problème Redmine de Python
Envoyer en utilisant Python avec Gmail
Essayez d'exploiter un fichier Excel en utilisant Python (Pandas / XlsxWriter) ①
Essayez d'exploiter un fichier Excel en utilisant Python (Pandas / XlsxWriter) ②