source: trunk/src/allmydata/web/introweb.py

Last change on this file was e6630b5, checked in by Itamar Turner-Trauring <itamar@…>, at 2023-11-17T16:22:06Z

Fix mypy complaints, simplifying code while we're at it

  • Property mode set to 100644
File size: 5.0 KB
Line 
1"""
2Ported to Python 3.
3"""
4import time
5from twisted.web.template import Element, XMLFile, renderElement, renderer
6from twisted.python.filepath import FilePath
7import allmydata
8from allmydata.util import idlib, jsonbytes as json
9from allmydata.web.common import (
10    render_time,
11    MultiFormatResource,
12    SlotsSequenceElement,
13    add_static_children,
14)
15
16
17class IntroducerRoot(MultiFormatResource):
18    """
19    A ``Resource`` intended as the root resource for introducers.
20
21    :param _IntroducerNode introducer_node: The introducer node to template
22        information about.
23    """
24
25    def __init__(self, introducer_node):
26        super(IntroducerRoot, self).__init__()
27        self.introducer_node = introducer_node
28        self.introducer_service = introducer_node.getServiceNamed("introducer")
29        # necessary as a root Resource
30        self.putChild(b"", self)
31        add_static_children(self)
32
33    def _create_element(self):
34        """
35        Create a ``IntroducerRootElement`` which can be flattened into an HTML
36        response.
37        """
38        return IntroducerRootElement(
39            self.introducer_node, self.introducer_service)
40
41    def render_HTML(self, req):
42        """
43        Render an HTML template describing this introducer node.
44        """
45        return renderElement(req, self._create_element())
46
47    def render_JSON(self, req):
48        """
49        Render JSON describing this introducer node.
50        """
51        res = {}
52
53        counts = {}
54        for s in self.introducer_service.get_subscribers():
55            if s.service_name not in counts:
56                counts[s.service_name] = 0
57            counts[s.service_name] += 1
58        res[u"subscription_summary"] = counts
59
60        announcement_summary = {}
61        for ad in self.introducer_service.get_announcements():
62            service_name = ad.service_name
63            if service_name not in announcement_summary:
64                announcement_summary[service_name] = 0
65            announcement_summary[service_name] += 1
66        res[u"announcement_summary"] = announcement_summary
67
68        return (json.dumps(res, indent=1) + "\n").encode("utf-8")
69
70
71class IntroducerRootElement(Element):
72    """
73    An ``Element`` HTML template which can be flattened to describe this
74    introducer node.
75
76    :param _IntroducerNode introducer_node: The introducer node to describe.
77    :param IntroducerService introducer_service: The introducer service created
78        by the node.
79    """
80
81    loader = XMLFile(FilePath(__file__).sibling("introducer.xhtml"))
82
83    def __init__(self, introducer_node, introducer_service):
84        super(IntroducerRootElement, self).__init__()
85        self.introducer_node = introducer_node
86        self.introducer_service = introducer_service
87        self.node_data_dict = {
88            "my_nodeid": idlib.nodeid_b2a(self.introducer_node.nodeid),
89            "version": allmydata.__full_version__,
90            "import_path": str(allmydata).replace("/", "/ "),  # XXX kludge for wrapping
91            "rendered_at": render_time(time.time()),
92        }
93
94    @renderer
95    def node_data(self, req, tag):
96        return tag.fillSlots(**self.node_data_dict)
97
98    @renderer
99    def announcement_summary(self, req, tag):
100        services = {}
101        for ad in self.introducer_service.get_announcements():
102            if ad.service_name not in services:
103                services[ad.service_name] = 0
104            services[ad.service_name] += 1
105        service_names = list(services.keys())
106        service_names.sort()
107        return u", ".join(u"{}: {}".format(service_name, services[service_name])
108                          for service_name in service_names)
109
110    @renderer
111    def client_summary(self, req, tag):
112        counts = {}
113        for s in self.introducer_service.get_subscribers():
114            if s.service_name not in counts:
115                counts[s.service_name] = 0
116            counts[s.service_name] += 1
117        return u", ".join(u"{}: {}".format(name, counts[name])
118                          for name in sorted(counts.keys()))
119
120    @renderer
121    def services(self, req, tag):
122        services = self.introducer_service.get_announcements()
123        services.sort(key=lambda ad: (ad.service_name, ad.nickname))
124        services = [{
125            "serverid": ad.serverid,
126            "nickname": ad.nickname,
127            "connection-hints":
128                u"connection hints: " + u" ".join(ad.connection_hints),
129            "connected": u"?",
130            "announced": render_time(ad.when),
131            "version": ad.version,
132            "service_name": ad.service_name,
133        } for ad in services]
134        return SlotsSequenceElement(tag, services)
135
136    @renderer
137    def subscribers(self, req, tag):
138        subscribers = [{
139            "nickname": s.nickname,
140            "tubid": s.tubid,
141            "connected": s.remote_address,
142            "since": render_time(s.when),
143            "version": s.version,
144            "service_name": s.service_name,
145        } for s in self.introducer_service.get_subscribers()]
146        return SlotsSequenceElement(tag, subscribers)
Note: See TracBrowser for help on using the repository browser.