import json
import logging
import mimetypes
+import pydantic
import urllib.parse
from . import base
# Setup logging
log = logging.getLogger("pbs.bugzilla")
-TIME_FORMAT = "%Y-%m-%dT%H:%M:%SZ"
-
class BugzillaError(Exception):
pass
response = await self._request("GET", "/rest/bug", data=kwargs)
# Parse the response
- bugs = [Bug(self.backend, self, data) for data in response.get("bugs")]
+ bugs = [self._make_bug(**data)for data in response.get("bugs")]
# Sort and return in reverse order
return sorted(bugs, reverse=True)
+ def _make_bug(self, id, creation_time, url=None, **kwargs):
+ """
+ Creates a new Bug object, but renames a couple of fields on the way.
+ """
+ # Make the URL
+ url = self.make_url("/show_bug.cgi", id=id)
+
+ # Return the Bug
+ return Bug(
+ id = id,
+ url = url,
+ created_at = creation_time,
+ **kwargs,
+ )
+
async def get_bugs(self, bugs):
"""
Fetches multiple bugs concurrently
async with asyncio.TaskGroup() as tg:
for bug in bugs:
- tg.create_task(
+ task = tg.create_task(
self.get_bug(bug),
)
+ tasks.append(task)
# Return the result from all tasks
return [task.result() for task in tasks]
response = await self._request("GET", "/rest/bug/%s" % bug)
for data in response.get("bugs"):
- return Bug(self.backend, self, data)
+ return self._make_bug(**data)
async def create_bug(self, product, component, version, summary, **kwargs):
data = {
return await self.get_bug(id)
-class Bug(base.Object):
- def init(self, bugzilla, data):
- self.bugzilla = bugzilla
- self.data = data
-
+class Bug(pydantic.BaseModel):
def __repr__(self):
return "<%s #%s>" % (self.__class__.__name__, self.id)
raise NotImplemented
- @property
- def id(self):
- return self.data.get("id")
+ # ID
- @property
- def url(self):
- return self.bugzilla.make_url("/show_bug.cgi", id=self.id)
+ id: int
- @property
- def created_at(self):
- t = self.data.get("creation_time")
+ # URL
- return datetime.datetime.strptime(t, TIME_FORMAT)
+ url: str
- @property
- def summary(self):
- return self.data.get("summary")
+ # Created At
- @property
- def component(self):
- return self.data.get("component")
+ created_at: datetime.datetime
+
+ # Summary
+
+ summary: str
+
+ # Component
+
+ component: str
# Creator
+ # XXX TODO
async def get_creator(self):
creator = self.data.get("creator")
# Assignee
+ # XXX TODO
async def get_assignee(self):
assignee = self.data.get("assigned_to")
return await self.backend.users.get_by_email(assignee)
- @property
- def status(self):
- return self.data.get("status")
+ # Status
- @property
- def resolution(self):
- return self.data.get("resolution")
+ status: str
- @property
- def severity(self):
- return self.data.get("severity")
+ # Resolution
- def is_closed(self):
- return not self.data["is_open"]
+ resolution: str
- @property
- def keywords(self):
- return self.data.get("keywords")
+ # Severity
+
+ severity: str
+
+ # Keywords
+
+ keywords: list[str] = []
# Update