Commit 45d1c770 authored by 20after4's avatar 20after4
Browse files

Resolve PHIDs to Task IDs and other nice stuff.

parent f1a992a1
import re
def version(ver):
"""Validate our version number formats"""
try:
return re.match("(\\d+\\.\\d+(\\.\\d+-)?wmf\\.?\\d+)", ver).group(0)
except Exception:
return None
return None
from __future__ import annotations from __future__ import annotations
import json
import os
from builtins import str from builtins import str
from collections import UserDict, UserList, deque from collections import UserDict, UserList, deque
from collections.abc import Iterable from collections.abc import Iterable
import json
import os
from pprint import pprint from pprint import pprint
from tokenize import Number from tokenize import Number
from typing import Collection, MutableMapping, MutableSequence, Union from typing import Collection, MutableMapping, MutableSequence, Union
from numpy import real
# todo: remove dependency on requests # todo: remove dependency on requests
import requests import requests
from numpy import real
from ddd.data import Data, DataIterator, wrapitem from ddd.data import Data, DataIterator, wrapitem
from ddd.phobjects import PHObject, isPHID from ddd.phobjects import PHObject, isPHID
...@@ -185,17 +184,7 @@ class ConduitCursor(object): ...@@ -185,17 +184,7 @@ class ConduitCursor(object):
self.resolve_phids(data=val) self.resolve_phids(data=val)
if data is self.data and len(PHObject.instances): if data is self.data and len(PHObject.instances):
phids = [phid for phid in PHObject.instances.keys()] PHObject.resolve_phids(self.conduit)
pprint(phids)
res = self.conduit.raw_request(method="phid.query", args={"phids": phids})
pprint(res.text)
objs = res.json()
for key, vals in objs["result"].items():
PHObject.instances[key].update(vals)
# for attr in vals.keys():
# setattr(PHObject.instances[key], attr, vals[attr])
return res
def __iter__(self): def __iter__(self):
return DataIterator(self.data) return DataIterator(self.data)
...@@ -220,6 +209,11 @@ class ConduitException(Exception): ...@@ -220,6 +209,11 @@ class ConduitException(Exception):
self.result = result self.result = result
self.message = message self.message = message
def __repr__(self):
return "ConduitException(message='%s')" % self.message
def __str__(self):
return "ConduitException: " + self.message
def flatten_for_post(h, result=None, kk=None): def flatten_for_post(h, result=None, kk=None):
""" """
......
from __future__ import annotations from __future__ import annotations
from enum import Enum from enum import Enum
from functools import total_ordering from functools import total_ordering
from pydoc import classname from pprint import pprint
from symbol import classdef
import time import time
from typing import ClassVar, Dict, Generic, Mapping, NewType, Type, TypeVar, Union from typing import ClassVar, Dict, Generic, Mapping, NewType, Type, TypeVar, Union
from datetime import datetime from datetime import datetime
...@@ -25,25 +25,14 @@ from datetime import datetime ...@@ -25,25 +25,14 @@ from datetime import datetime
""" """
PHID = NewType("PHID", str) PHID = NewType("PHID", str)
Status = NewType('Status', str)
class PHIDTypes(Enum):
PHOB = "PHObject"
PROJ = "Project"
TASK = "Task"
CMIT = "Commit"
XACT = "Transaction"
STRY = "FeedStory"
APPS = "Application"
PCOL = "ProjectColumn"
USER = "User"
def isPHID(value: str): def isPHID(value: str):
return isinstance(value, str) and value.startswith("PHID-") return isinstance(value, str) and value.startswith("PHID-")
def PHIDType(phid: PHID): def PHIDType(phid: PHID) -> Union[Type[PhabObjectBase], str]:
parts = phid.split("-") parts = phid.split("-")
phidtype = parts[1] phidtype = parts[1]
if phidtype in PHIDTypes.__members__: if phidtype in PHIDTypes.__members__:
...@@ -72,6 +61,17 @@ class SubclassCache(Generic[TID, T]): ...@@ -72,6 +61,17 @@ class SubclassCache(Generic[TID, T]):
@classmethod @classmethod
def byid(cls, id: TID) -> Union[T, None]: def byid(cls, id: TID) -> Union[T, None]:
obj = cls.instances.get(id) obj = cls.instances.get(id)
return obj
@classmethod
def resolve_phids(cls, conduit):
phids = [phid for phid in cls.instances.keys()]
res = conduit.raw_request(method="phid.query", args={"phids": phids})
objs = res.json()
for key, vals in objs["result"].items():
cls.instances[key].update(vals)
class PhabObjectBase(object): class PhabObjectBase(object):
...@@ -82,9 +82,14 @@ class PhabObjectBase(object): ...@@ -82,9 +82,14 @@ class PhabObjectBase(object):
fullName: str fullName: str
dateCreated: datetime dateCreated: datetime
dateModified: datetime dateModified: datetime
status: Status
def __init__(self, phid: PHID): def __init__(self, phid: PHID):
self.phid = phid self.phid = PHID(phid)
self.name = "(Unknown object)"
self.status = Status("unknown")
self.fullName = ""
def update(self, data: Mapping): def update(self, data: Mapping):
self.__dict__.update(data) self.__dict__.update(data)
...@@ -118,7 +123,7 @@ class PHObject(PhabObjectBase, SubclassCache[PHID, PhabObjectBase]): ...@@ -118,7 +123,7 @@ class PHObject(PhabObjectBase, SubclassCache[PHID, PhabObjectBase]):
self.__dict__.update(kwargs) self.__dict__.update(kwargs)
def __str__(self): def __str__(self):
return "%s (%s)" % (self.phid, self.fullName) return self.name if len(self.name) else self.phid
def __repr__(self): def __repr__(self):
# {self.__dict__} # {self.__dict__}
...@@ -139,14 +144,15 @@ class PHObject(PhabObjectBase, SubclassCache[PHID, PhabObjectBase]): ...@@ -139,14 +144,15 @@ class PHObject(PhabObjectBase, SubclassCache[PHID, PhabObjectBase]):
return len(self.__dict__.keys()) > 1 return len(self.__dict__.keys()) > 1
@classmethod @classmethod
def instance(cls, phid: PHID) -> Union[PhabObjectBase, None]: def instance(cls, phid: PHID) -> PhabObjectBase:
if phid in __class__.instances: obj = __class__.byid(phid)
obj = __class__.byid(phid) if obj:
return obj return obj
phidtype = PHIDType(phid) phidtype = PHIDType(phid)
typecls = __class__.subclass(phidtype, cls) if isinstance(phidtype, str):
newinstance = typecls(phid) phidtype = __class__.subclass(phidtype, cls)
newinstance = phidtype(phid)
__class__.instances[phid] = newinstance __class__.instances[phid] = newinstance
return newinstance return newinstance
...@@ -167,6 +173,19 @@ class Task(PHObject): ...@@ -167,6 +173,19 @@ class Task(PHObject):
pass pass
class Commit(PHObject):
pass
class FeedStory(PHObject):
pass
class Application(PHObject):
pass
class Transaction(PHObject): class Transaction(PHObject):
relationships = { relationships = {
...@@ -176,4 +195,21 @@ class Transaction(PHObject): ...@@ -176,4 +195,21 @@ class Transaction(PHObject):
"close-as-duplicate": 63, "close-as-duplicate": 63,
} }
class Event(PHObject):
""" Phabricator Calendar Event """
pass pass
class PHIDTypes(Enum):
PHOB = PHObject
PROJ = Project
TASK = Task
CMIT = Commit
CEVT = Event
XACT = Transaction
STRY = FeedStory
APPS = Application
PCOL = ProjectColumn
USER = User
#!/usr/bin/python3 #!/usr/bin/python3
import json
import sys
from collections import UserDict from collections import UserDict
from typing import Mapping
from ddd.phobjects import PHIDType, Task
from operator import itemgetter from operator import itemgetter
import requests
import sys
import json
from pprint import pprint from pprint import pprint
from typing import Mapping
import pandas as pd
import requests
from IPython.display import display
import ddd import ddd
from ddd.phab import Conduit, ConduitException
from ddd.mw import version from ddd.mw import version
from ddd.phab import Conduit, ConduitException
from ddd.phobjects import PHIDType, Task, PHObject
phab = Conduit() phab = Conduit()
pd.options.display.max_columns = None
pd.options.display.max_rows = None
# find all train blocker tasks # find all train blocker tasks
...@@ -20,6 +25,9 @@ r = phab.request( ...@@ -20,6 +25,9 @@ r = phab.request(
"maniphest.search", "maniphest.search",
{ {
"queryKey": "ZKaMIUs_NEXo", "queryKey": "ZKaMIUs_NEXo",
"constraints": {
'ids': ['249964'],
},
"limit": "50", "limit": "50",
"attachments": {"projects": False, "columns": False}, "attachments": {"projects": False, "columns": False},
}, },
...@@ -68,11 +76,14 @@ def gettransactions(taskids): ...@@ -68,11 +76,14 @@ def gettransactions(taskids):
ov = [key for key in ov.keys()] ov = [key for key in ov.keys()]
# ... we only care about tasks: # ... we only care about tasks:
if len(ov) == 0 and len(nv) == 1 and PHIDType(nv[0]) is Task: if len(ov) == 0 and len(nv) > 0 and PHIDType(nv[0]) is Task:
return ("added", nv[0]) return ("added", [obj for obj in map(PHObject.instance, nv)])
elif len(ov) == 1 and len(nv) == 0 and PHIDType(ov[0]) is Task: elif len(ov) > 0 and len(nv) == 0 and PHIDType(ov[0]) is Task:
return ("removed", nv[0]) return ("removed", [obj for obj in map(PHObject.instance, ov)])
else: else:
print("--- new %s --- old %s ---" % (len(nv), len(ov)))
pprint(nv)
pprint(ov)
# ignore other edge types # ignore other edge types
return None return None
...@@ -83,10 +94,10 @@ def gettransactions(taskids): ...@@ -83,10 +94,10 @@ def gettransactions(taskids):
ov = t["oldValue"] ov = t["oldValue"]
for item in nv.items(): for item in nv.items():
phid, action = item phid, action = item
return (action, phid) return (action, PHObject.instance(phid))
# a comment was added # a comment was added
@ttype("core:comment") #@ttype("core:comment")
def comment(t): def comment(t):
# todo: we could check for the risky revision template here, if we care # todo: we could check for the risky revision template here, if we care
# to count that. # to count that.
...@@ -100,6 +111,15 @@ def gettransactions(taskids): ...@@ -100,6 +111,15 @@ def gettransactions(taskids):
if nv: if nv:
return ('version', nv) return ('version', nv)
#@ttype("core:columns")
def columns(t):
pprint(t)
#@ttype("status")
def status(t):
pprint(t)
transactions = phab.request( transactions = phab.request(
"maniphest.gettasktransactions", "maniphest.gettasktransactions",
{ {
...@@ -116,7 +136,7 @@ def gettransactions(taskids): ...@@ -116,7 +136,7 @@ def gettransactions(taskids):
# Ignore all transactions which do not have a matching formatter # Ignore all transactions which do not have a matching formatter
# you can uncomment the print statement below to see what other # you can uncomment the print statement below to see what other
# transaction types are available: # transaction types are available:
# print(trnstype) print(trnstype)
continue continue
# format the transaction data using the matching formatter function # format the transaction data using the matching formatter function
formatted = formatters[trnstype](tr) formatted = formatters[trnstype](tr)
...@@ -127,12 +147,10 @@ def gettransactions(taskids): ...@@ -127,12 +147,10 @@ def gettransactions(taskids):
# now collect all of the formatted transaction details # now collect all of the formatted transaction details
rows = [row for row in gettransactions(tasks)] rows = [row for row in gettransactions(tasks)]
PHObject.resolve_phids(phab)
columns = ['task', 'timestamp', 'author','action','values']
# now we could write a csv file or output the data to stdout data = pd.DataFrame(rows, columns=columns)
# for now, just output tsv: display(data)
for row in rows:
print("\t".join(row))
if __name__ == "__main__": if __name__ == "__main__":
pass pass
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment