~brendan-donegan/qakit/export_checkbox_practitest

« back to all changes in this revision

Viewing changes to qakit/lkkb.py

  • Committer: Thomi Richards
  • Date: 2014-11-12 02:33:48 UTC
  • mfrom: (4.1.1 trunk-add-project-backlog)
  • Revision ID: thomi.richards@canonical.com-20141112023348-nzw8bny0fb8c146b
Merge code to retrieve project backlog.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# qakit - tools for UEQA engineers
 
2
# Copyright (C) 2014 Thomi Richards
 
3
#
 
4
# This program is free software; you can redistribute it and/or
 
5
# modify it under the terms of the GNU General Public License
 
6
# as published by the Free Software Foundation; either version 2
 
7
# of the License, or (at your option) any later version.
 
8
#
 
9
# This program is distributed in the hope that it will be useful,
 
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
# GNU General Public License for more details.
 
13
#
 
14
# You should have received a copy of the GNU General Public License
 
15
# along with this program; if not, write to the Free Software
 
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
17
 
 
18
 
 
19
from ConfigParser import RawConfigParser
 
20
import os.path
 
21
import sys
 
22
import csv
 
23
import requests
 
24
from pprint import pprint
 
25
import bleach
 
26
 
 
27
 
 
28
ACCOUNT_URL = 'https://canonical.leankit.com/Kanban/Api/'
 
29
BOARD_ID = '109656104'
 
30
 
 
31
 
 
32
def project_backlog():
 
33
    try:
 
34
        username, password = get_lkkb_auth_pair()
 
35
        resp = requests.get(
 
36
            ACCOUNT_URL + 'boards/' + BOARD_ID,
 
37
            auth=(username, password)
 
38
        )
 
39
        resp.raise_for_status()
 
40
        data = resp.json()
 
41
        (sorted_lane,) = [
 
42
            l for l in data[u'ReplyData'][0][u'Backlog'] if l[u'Title'] == u'Sorted'
 
43
        ]
 
44
 
 
45
        row_keys = [
 
46
            'Title',
 
47
            'Priority',
 
48
            'PriorityText',
 
49
            'Tags',
 
50
            'Description',
 
51
        ]
 
52
        csv_writer = csv.writer(sys.stdout)
 
53
        csv_writer.writerow(row_keys)
 
54
        for card in sorted_lane['Cards']:
 
55
            row = [ clean_text(card[k]) for k in row_keys]
 
56
            csv_writer.writerow(row)
 
57
    except IOError:
 
58
        handle_file_read_error()
 
59
 
 
60
 
 
61
def clean_text(text):
 
62
    text = bleach.clean(
 
63
        text,
 
64
        tags=[],
 
65
        attributes=[],
 
66
        strip=True,
 
67
        strip_comments=True
 
68
    )
 
69
    text = text.replace('\n', '').replace('\r', '').replace('\t', '')
 
70
    return text.encode('utf-8')
 
71
 
 
72
 
 
73
def stripIt(string, tag):
 
74
    soup = BeautifulSoup(string)
 
75
 
 
76
    rmtags = soup.findAll(tag)
 
77
    for t in rmtags:
 
78
        string = string.replace(str(t), '')
 
79
    return string
 
80
 
 
81
 
 
82
def get_lkkb_auth_pair(config_file_path=None):
 
83
    """Return a tuple of (username, password) from the users config file.
 
84
 
 
85
    Raises IOError if the file is not found.
 
86
    Raises ValueError if the required configuration is not set.
 
87
    """
 
88
    if config_file_path is None:
 
89
        config_file_path = os.path.expanduser('~/config/qakit.ini')
 
90
    parser = RawConfigParser()
 
91
    if not parser.read(config_file_path):
 
92
        raise IOError("Could not read file %s" % (config_file_path))
 
93
    if not parser.has_section("LeanKit"):
 
94
        raise ValueError("Could not find 'LeanKit' section in config file.")
 
95
    if not parser.has_option("LeanKit", "Username") or not parser.get("LeanKit", "Username"):
 
96
        raise ValueError("No username set in config file.")
 
97
    if not parser.has_option("LeanKit", "Password") or not parser.get("LeanKit", "Password"):
 
98
        raise ValueError("No password set in config file.")
 
99
    return (
 
100
        parser.get("LeanKit", "Username"),
 
101
        parser.get("LeanKit", "Password"),
 
102
    )
 
103
 
 
104
 
 
105
def handle_file_read_error():
 
106
    path = get_default_config_file_path()
 
107
    os.makedirs(os.path.dirname(path))
 
108
    with open(path, 'w') as f:
 
109
        f.write(
 
110
            "[LeanKit]\n"
 
111
            "# Fill in your LeanKit username and password here:\n"
 
112
            "Username = \n"
 
113
            "Password = \n"
 
114
        )
 
115
    # TODO: Make this file readable by this user only!
 
116
    print("Missing configuration details!")
 
117
    print("A default configuration file has been written to:")
 
118
    print("\t%s" % path)
 
119
    print("Please fill in the values in that file and re-run this command.")
 
120
    sys.exit(2)
 
121
 
 
122
 
 
123
def get_default_config_file_path():
 
124
    return os.path.expanduser('~/config/qakit.ini')