123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- # Copyright (c) Twisted Matrix Laboratories.
- # See LICENSE for details.
- """
- Generic sentence handling tools: hopefully reusable.
- """
- from typing import Set
-
-
- class _BaseSentence:
- """
- A base sentence class for a particular protocol.
-
- Using this base class, specific sentence classes can almost automatically
- be created for a particular protocol.
- To do this, fill the ALLOWED_ATTRIBUTES class attribute using
- the C{getSentenceAttributes} class method of the producer::
-
- class FooSentence(BaseSentence):
- \"\"\"
- A sentence for integalactic transmodulator sentences.
-
- @ivar transmogrificationConstant: The value used in the
- transmogrifier while producing this sentence, corrected for
- gravitational fields.
- @type transmogrificationConstant: C{Tummy}
- \"\"\"
- ALLOWED_ATTRIBUTES = FooProtocol.getSentenceAttributes()
-
- @ivar presentAttributes: An iterable containing the names of the
- attributes that are present in this sentence.
- @type presentAttributes: iterable of C{str}
-
- @cvar ALLOWED_ATTRIBUTES: A set of attributes that are allowed in this
- sentence.
- @type ALLOWED_ATTRIBUTES: C{set} of C{str}
- """
-
- ALLOWED_ATTRIBUTES: Set[str] = set()
-
- def __init__(self, sentenceData):
- """
- Initializes a sentence with parsed sentence data.
-
- @param sentenceData: The parsed sentence data.
- @type sentenceData: C{dict} (C{str} -> C{str} or L{None})
- """
- self._sentenceData = sentenceData
-
- @property
- def presentAttributes(self):
- """
- An iterable containing the names of the attributes that are present in
- this sentence.
-
- @return: The iterable of names of present attributes.
- @rtype: iterable of C{str}
- """
- return iter(self._sentenceData)
-
- def __getattr__(self, name):
- """
- Gets an attribute of this sentence.
- """
- if name in self.ALLOWED_ATTRIBUTES:
- return self._sentenceData.get(name, None)
- else:
- className = self.__class__.__name__
- msg = f"{className} sentences have no {name} attributes"
- raise AttributeError(msg)
-
- def __repr__(self) -> str:
- """
- Returns a textual representation of this sentence.
-
- @return: A textual representation of this sentence.
- @rtype: C{str}
- """
- items = self._sentenceData.items()
- data = [f"{k}: {v}" for k, v in sorted(items) if k != "type"]
- dataRepr = ", ".join(data)
-
- typeRepr = self._sentenceData.get("type") or "unknown type"
- className = self.__class__.__name__
-
- return f"<{className} ({typeRepr}) {{{dataRepr}}}>"
-
-
- class _PositioningSentenceProducerMixin:
- """
- A mixin for certain protocols that produce positioning sentences.
-
- This mixin helps protocols that store the layout of sentences that they
- consume in a C{_SENTENCE_CONTENTS} class variable provide all sentence
- attributes that can ever occur. It does this by providing a class method,
- C{getSentenceAttributes}, which iterates over all sentence types and
- collects the possible sentence attributes.
- """
-
- @classmethod
- def getSentenceAttributes(cls):
- """
- Returns a set of all attributes that might be found in the sentences
- produced by this protocol.
-
- This is basically a set of all the attributes of all the sentences that
- this protocol can produce.
-
- @return: The set of all possible sentence attribute names.
- @rtype: C{set} of C{str}
- """
- attributes = {"type"}
- for attributeList in cls._SENTENCE_CONTENTS.values():
- for attribute in attributeList:
- if attribute is None:
- continue
- attributes.add(attribute)
-
- return attributes
|