Implement dependency system for CAPs

This commit is contained in:
jesopo 2019-06-21 18:05:11 +01:00
parent 8a0d99f969
commit 90c90e5bbd
2 changed files with 50 additions and 3 deletions

View file

@ -16,13 +16,58 @@ CAPABILITIES = [
utils.irc.Capability(None, "draft/setname", alias="setname")
]
def _cap_depend_sort(caps, server_caps):
sorted_caps = []
caps_copy = {alias: cap.copy() for alias, cap in caps.items()}
for cap in caps.values():
if not cap.available(server_caps):
del caps_copy[cap.alias]
while True:
remove = []
for alias, cap in caps_copy.items():
for depend_alias in cap.depends_on:
if not depend_alias in caps_copy:
remove.append(alias)
if remove:
for alias in remove:
del caps_copy[alias]
else:
break
while caps_copy:
fulfilled = []
for cap in caps_copy.values():
remove = []
for depend_alias in cap.depends_on:
if depend_alias in sorted_caps:
remove.append(depend_alias)
for remove_cap in remove:
cap.depends_on.remove(remove_cap)
if not cap.depends_on:
fulfilled.append(cap.alias)
for fulfilled_cap in fulfilled:
del caps_copy[fulfilled_cap]
sorted_caps.append(fulfilled_cap)
return [caps[alias] for alias in sorted_caps]
def _cap_match(server, caps):
matched_caps = {}
blacklist = server.get_setting("blacklisted-caps", [])
cap_aliases = {}
for cap in caps:
if not cap.alias in blacklist:
cap_aliases[cap.alias] = cap
sorted_caps = _cap_depend_sort(cap_aliases, server.server_capabilities)
for cap in sorted_caps:
available = cap.available(server.server_capabilities)
if (available and not server.has_capability(cap) and
not available in blacklist):
if available and not server.has_capability(cap):
matched_caps[available] = cap
return matched_caps

View file

@ -291,6 +291,7 @@ class Capability(object):
depends_on: typing.List[str]=None):
self.alias = alias or ratified_name
self._caps = set([ratified_name, draft_name])
self.depends_on = depends_on or []
self._on_ack_callbacks = [
] # type: typing.List[typing.Callable[[], None]]
@ -304,7 +305,8 @@ class Capability(object):
return cap[0] if cap else None
def copy(self):
return Capability(*self._caps)
return Capability(*self._caps, alias=self.alias,
depends_on=self.depends_on)
def on_ack(self, callback: typing.Callable[[], None]):
self._on_ack_callbacks.append(callback)