Exemple #1
0
class Mantis(IBugtracker):
    def __init__(self, *args, **kwargs):
        IBugtracker.__init__(self, *args, **kwargs)
        self.soap_client = SoapClient("%s/api/soap/mantisconnect.php" % self.url, namespace="http://futureware.biz/mantisconnect")

    def get_tracker(self, url):
        try:
            match = re.match(r'(?P<url>(?P<name>[^\s/]+).*)/view\.php', url)
            name  = desc = match.group('name')
            url   = 'https://%s' % match.group('url')
#            registerBugtracker(name, url, desc, 'mantis')
            return Mantis(name, url, desc, 'mantis')
        except:
            pass

    def get_bug(self, id):
        url = "%s/api/rest/issues/%d" % (self.url, id)
        try:
            bugjson = utils.web.getUrl(url)
            bug = json.loads(bugjson.decode('utf-8'))['issues'][0]
        except Exception as e:
            # REST API may not be enabled yet
            if 'HTTP Error 404' in str(e):
                return self.get_bug_old(id)
            raise BugtrackerError(self.errget % (self.description, e, url))
        try:
            return (id, bug['project']['name'], bug['summary'], bug['severity']['name'], bug['resolution']['name'], '', url, [], [])
        except Exception as e:
            raise BugtrackerError(self.errparse % (self.description, e, url))

    def get_bug_old(self, id): # Deprecated
        url = "%s/view.php?id=%d" % (self.url, id)
        try:
            raw = self.soap_client.mc_issue_get(username='', password='', issue_id=id)
        except Exception as e:
            if 'Issue #%d not found' % id in str(e):
                raise BugNotFoundError
            # Often SOAP is not enabled
            if '.' in self.name:
                supylog.exception(self.errget % (self.description, e, url))
                return
            raise BugtrackerError(self.errget % (self.description, e, url))
        if not hasattr(raw, 'id'):
            raise BugNotFoundError
        try:
            return (id, str(raw.project.name), str(raw.summary), str(raw.severity.name), str(raw.resolution.name), '', url, [], [])
        except Exception as e:
            raise BugtrackerError(self.errparse % (self.description, e, url))
Exemple #2
0
class MantisBT(object):

    def __init__(self, username, password, url):
        if not url.endswith("?wsdl"):
            if url.endswith("/api/soap/mantisconnect.php"):
                url += "?wdsl"
            elif url.endswith("/"):
                url += "api/soap/mantisconnect.php?wsdl"
            else:
                url += "/api/soap/mantisconnect.php?wsdl"

        self.client = SoapClient(wsdl=url, trace=False)
        self.username = username
        self.password = password
        self._status = None
        self._priorities = None
        self._severities = None
        self._resolutions = None
        self._projects = None

    def comment(self, ticket, content):
        if type(content) is str:
            content = content.decode("utf-8")
        self.client.mc_issue_note_add(
            username=self.username,
            password=self.password,
            issue_id=int(ticket),
            note={
                "text": content
            }
        )

    def issue(self, issue_id):
        return self.client.mc_issue_get(
            username=self.username,
            password=self.password,
            issue_id=int(issue_id)
        )['return']

    @property
    def status(self):
        if not self._status:
            self._status = map(
                lambda n: n.get("item"),
                self.client.mc_enum_status(
                    username=self.username,
                    password=self.password
                )['return']
            )
        return self._status

    @property
    def priorities(self):
        if not self._priorities:
            self._priorities = map(
                lambda n: n.get("item"),
                self.client.mc_enum_priorities(
                    username=self.username,
                    password=self.password
                )['return']
            )
        return self._priorities

    @property
    def severities(self):
        if not self._severities:
            self._severities = map(
                lambda n: n.get("item"),
                self.client.mc_enum_severities(
                    username=self.username,
                    password=self.password
                )['return']
            )
        return self._severities

    @property
    def resolutions(self):
        if not self._resolutions:
            self._resolutions = map(
                lambda n: n.get("item"),
                self.client.mc_enum_resolutions(
                    username=self.username,
                    password=self.password
                )['return']
            )
        return self._resolutions

    @property
    def projects(self):
        if not self._projects:

            def _proj(proj):
                return {
                    "id": int(proj["item"].id),
                    "name": unicode(proj["item"].name)
                }
            projs = self.client.mc_projects_get_user_accessible(
                username=self.username,
                password=self.password
            )['return']
            self._projects = map(_proj, projs)
        return self._projects

    def versions(self, project):
        if type(project) is int or type(project) is long:
            pid = project
        elif any(map(lambda p: p.get("name") == project, self.projects)):
            pid = filter(lambda p: p.get("name") == project, self.projects)[0].get("id")
        else:
            raise Exception("Project: %s does not exist!" % project)
        return self.client.mc_project_get_versions(
            username=self.username,
            password=self.password,
            project_id=pid
        )["return"]

    def customfields(self, project):
        if type(project) is int or type(project) is long:
            pid = project
        elif any(map(lambda p: p.get("name") == project, self.projects)):
            pid = filter(lambda p: p.get("name") == project, self.projects)[0].get("id")
        else:
            raise Exception("Project: %s does not exist!" % project)
        return self.client.mc_project_get_custom_fields(
            username=self.username,
            password=self.password,
            project_id=pid
        )["return"]

    def addversion(self, project, version, date=None, description=None, released=False, obsolete=False):
        if type(project) is int or type(project) is long:
            pid = project
        elif any(map(lambda p: p.get("name") == project, self.projects)):
            pid = filter(lambda p: p.get("name") == project, self.projects)[0].get("id")
        else:
            raise Exception("Project: %s does not exist!" % project)
        return self.client.mc_project_version_add(
            username=self.username,
            password=self.password,
            version={
                "name": version,
                "project_id": pid,
                "date_order": date or datetime.now(),
                "description": description or version,
                "released": released,
                "obsolete": obsolete
            }
        )["return"]

    def value_of(self, prop, name):
        default = "null"
        if not name:
            return default
        m = re.match(r"@(\d+)@", name)
        if m:
            _id = int(m.group(1))
            for v in getattr(self, prop):
                if v.id == _id:
                    return v.name
            else:
                return default
        else:
            return name

    def isTicketResolved(self, status):
        return status >= config.TICKET_RESOLVED_STATUS

    def projectId(self, project_name):
        return self.client.mc_project_get_id_from_name(
            username=self.username,
            password=self.password,
            project_name=project_name
        )['return']

    def maxTicketId(self, proj):
        if type(proj) is str:
            proj = self.projectId(proj)
        return self.client.mc_issue_get_biggest_id(
            username=self.username,
            password=self.password,
            project_id=proj
        )['return']

    def tickets(self, project_names):
        if type(project_names) is not list:
            project_names = [project_names]
        pids = map(lambda n: self.projectId(n), project_names)
        max_id = max(map(lambda proj: self.maxTicketId(proj), pids))
        for i in xrange(max_id):
            try:
                issue = self.client.mc_issue_get(
                    username=self.username,
                    password=self.password,
                    issue_id=i+1
                )['return']
                if issue['project']['id'] in pids:
                    yield issue
            except:
                pass

    def suspend(self, ticket_id):
        issue = self.client.mc_issue_get(
            username=self.username,
            password=self.password,
            issue_id=int(ticket_id)
        )["return"]
        return self.client.mc_issue_update(
            username=self.username,
            password=self.password,
            issueId=int(ticket_id),
            issue={
                "status": {
                    "id": config.TICKET_SUSPEND_STATUS
                },
                "project": {
                    "id": int(issue.get("project").get("id"))
                },
                "reporter": {
                    "id": int(issue.get("reporter").get("id"))
                },
                "handler": {
                    "id": int(issue.get("handler").get("id"))
                },
                "summary": unicode(issue.get("summary")),
                "description": unicode(issue.get("description")),
                "category": unicode(issue.get("category")),
                "due_date": issue.get("due_date") or datetime.now(),
            }
        )["return"]

    def resolve(self, ticket_id):
        issue = self.client.mc_issue_get(
            username=self.username,
            password=self.password,
            issue_id=int(ticket_id)
        )["return"]
        return self.client.mc_issue_update(
            username=self.username,
            password=self.password,
            issueId=int(ticket_id),
            issue={
                "status": {
                    "id": config.TICKET_RESOLVED_STATUS
                },
                "project": {
                    "id": int(issue.get("project").get("id"))
                },
                "reporter": {
                    "id": int(issue.get("reporter").get("id"))
                },
                "handler": {
                    "id": int(issue.get("handler").get("id"))
                },
                "summary": unicode(issue.get("summary")),
                "description": unicode(issue.get("description")),
                "category": unicode(issue.get("category")),
                "due_date": issue.get("due_date") or datetime.now(),
                "resolution": {
                    "id": config.TICKET_FIXED_RESOLUTION,
                },
            }
        )["return"]

    def live_tickets(self, project_name):
        pid = self.projectId(project_name)
        page = 0
        per_page = 100
        while True:
            page += 1
            ts = self.client.mc_project_get_issue_headers(
                username=self.username,
                password=self.password,
                project_id=pid,
                page_number=page,
                per_page=per_page
            )['return']
            for t in ts:
                yield t['item']
            if len(ts) is 0:
                break

    def arrival_summary(self, project_names):
        def default_sum():
            return {
                "total": 0,
                "priority": defaultdict(int),
                "severity": defaultdict(int),
                "category": defaultdict(int),
                "reporter": defaultdict(int),
            }

        def default_proj_sum():
            return {
                "total": 0,
                "priority": defaultdict(int),
                "severity": defaultdict(int),
                "resolution": defaultdict(int),
                "category": defaultdict(int),
                "reporter": defaultdict(int),
                "handler": defaultdict(int),
                "status": defaultdict(int),
                "date": defaultdict(default_sum),
                "week": defaultdict(default_sum),
                "month": defaultdict(default_sum),
            }

        def _replace_invalid_char(s):
            if s:
                return s.replace("$", "#").replace(".", "_")
            else:
                return "null"

        sum = defaultdict(default_proj_sum)
        for t in self.tickets(project_names):
            project = t["project"]["name"]
            category = t["category"]
            severity = self.value_of("severities", t["severity"]["name"])
            priority = self.value_of("priorities", t["priority"]["name"])
            resolution = self.value_of("resolutions", t["resolution"]["name"])
            status = self.value_of("status", t["status"]["name"])
            if "reporter" in t:
                reporter = t["reporter"].get("name") or t["reporter"].get("email")
            else:
                reporter = "null"
            if "handler" in t:
                handler = t["handler"].get("name") or t["handler"].get("email")
            else:
                handler = "null"

            project = _replace_invalid_char(project)
            category = _replace_invalid_char(category)
            severity = _replace_invalid_char(severity)
            priority = _replace_invalid_char(priority)
            resolution = _replace_invalid_char(resolution)
            status = _replace_invalid_char(status)
            reporter = _replace_invalid_char(reporter)
            handler = _replace_invalid_char(handler)

            sum[project]["total"] += 1
            if severity:
                sum[project]["severity"][severity] += 1
            if priority:
                sum[project]["priority"][priority] += 1
            if category:
                sum[project]["category"][category] += 1
            if resolution:
                sum[project]["resolution"][resolution] += 1
            if status:
                sum[project]["status"][status] += 1
            if reporter:
                sum[project]["reporter"][reporter] += 1
            if handler:
                sum[project]["handler"][handler] += 1

            def _update_duration(data):
                data["total"] += 1
                if priority:
                    data["priority"][priority] += 1
                if severity:
                    data["severity"][severity] += 1
                if category:
                    data["category"][category] += 1
                if reporter:
                    data["reporter"][reporter] += 1

            date = toDate(t["date_submitted"])
            _update_duration(sum[project]["date"][date])
            week = toWeek(t["date_submitted"])
            _update_duration(sum[project]["week"][week])
            month = toMonth(t["date_submitted"])
            _update_duration(sum[project]["month"][month])
            # print t["id"], t["version"], t["summary"]
        return sum