Ejemplo n.º 1
0
Archivo: app.py Proyecto: f0rk/cartman
    def run_status(self, ticket_id, status=None):
        """Updates the status of a ticket.

        usage: cm status ticket_id [new_status]

        """
        ticket_id = text.validate_id(ticket_id)

        self.login()

        # Get all the available actions for this ticket
        r = self.get("/ticket/%d" % ticket_id)
        timestamp = text.extract_timestamp(r.content)
        statuses = text.extract_statuses(r.content)

        # A ``status`` was provided, try to find the exact match, else just
        # display the current status for this ticket, and the available ones.
        if status:
            status = text.fuzzy_find(status, statuses)

            if not status:
                raise exceptions.FatalError("bad status (for this ticket: %s)" % \
                                        ", ".join(statuses))
        else:
            status = text.extract_status_from_ticket_page(r.content)
            print("Current status: %s" % status)
            print("Available statuses: %s" % ", ".join(statuses))
            return

        if self.message:
            comment = self.message
        elif self.add_comment:
            comment = self._read_comment()
        else:
            comment = ""

        r = self.post("/ticket/%d" % ticket_id, {
            "ts": timestamp,
            "action": status,
            "comment": comment,
        })

        if "system-message" in r.content or r.status_code != 200:
            raise exceptions.FatalError("unable to set status")
Ejemplo n.º 2
0
Archivo: app.py Proyecto: f0rk/cartman
    def run_new(self, owner=None):
        """Create a new ticket and return its id if successful.

        usage: cm new [owner]

        """
        owner = owner or self.username

        self.login()

        valid = False
        headers = {
            "Subject": "",
            "To": owner,
            "Cc": "",
            "Milestone": "",
            "Component": "",
            "Priority": "2",
            "Type": "defect",
            "Keywords": "",
            "Version": "",
        }
        body = "\n"

        while not valid:
            # Get the properties at each iteration, in case an admin updated
            # the list in the mean time, especially because of this new ticket.
            properties = self._get_properties()

            # Assume the user will produce a valid ticket
            valid = True

            # Load the current values in a temp file for editing
            (fd, filename) = tempfile.mkstemp(suffix=".cm.ticket")
            fp = os.fdopen(fd, "w")
            fp.write(self._format_headers(headers))
            fp.write("\n\n")
            fp.write(body)
            fp.close()
            self._editor(filename)

            # Use the email parser to get the headers.
            ep = email.parser.Parser()
            with open(filename, "r") as fp:
                em = ep.parse(fp)

            os.unlink(filename)

            body = em.get_payload()
            headers.update(em)

            errors = []
            fuzzy_match_fields = ("Milestone", "Component", "Type", "Version",
                                  "Priority")

            # Ensures all the required fields are filled-in
            for key in self.required_fields:
                if key in fuzzy_match_fields:
                    continue
                if not headers[key] or "**ERROR**" in headers[key]:
                    errors.append("Invalid '%s': cannot be blank" % key)

            # Some fields are tolerant to incomplete values, this is where we
            # try to complete them.
            for key in fuzzy_match_fields:
                valid_options = properties[key.lower()]["options"]

                if headers[key] not in valid_options:
                    m = text.fuzzy_find(headers[key], valid_options)
                    if m:
                        headers[key] = m
                    else:
                        if key in self.required_fields:
                            errors.append("Invalid '%s': expected: %s" % \
                                        (key, ", ".join(valid_options)))
                        else:
                            headers[key] = ""

            if errors:
                valid = False
                print("\nFound the following errors:")
                for error in errors:
                    print(" - %s" % error)

                try:
                    self._input("\n-- Hit Enter to return to editor, "\
                              "^C to abort --\n")
                except KeyboardInterrupt:
                    raise exceptions.FatalError("ticket creation interrupted")

        r = self.post("/newticket", {
            "field_summary": headers["Subject"],
            "field_type": headers["Type"],
            "field_version": headers["Version"],
            "field_description": body,
            "field_milestone": headers["Milestone"],
            "field_component": headers["Component"],
            "field_owner": headers["To"],
            "field_keywords": headers["Keywords"],
            "field_cc": headers["Cc"],
            "field_attachment": "",
        })

        if r.status_code != 200:
            raise exceptions.RequestException("unable to create new ticket.")

        try:
            ticket_id = int(r.url.split("/")[-1])
        except:
            raise exceptions.RequestException("returned ticket_id is invalid.")

        self.open_in_browser_on_request(ticket_id)
        print("ticket #%d created" % ticket_id)