blob: 6a60eaf7ed724f2ba1656a24a0f83dc8eb76ffeb (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
# docparse.py
#
# Support doc-string parsing classes
__all__ = ["DocParseMeta"]
class DocParseMeta(type):
'''
Metaclass that processes the class docstring through a parser and
incorporates the result into the resulting class definition. This
allows Python classes to be defined with alternative syntax.
To use this class, you first need to define a lexer and parser:
from sly import Lexer, Parser
class MyLexer(Lexer):
...
class MyParser(Parser):
...
You then need to define a metaclass that inherits from DocParseMeta.
This class must specify the associated lexer and parser classes.
For example:
class MyDocParseMeta(DocParseMeta):
lexer = MyLexer
parser = MyParser
This metaclass is then used as a base for processing user-defined
classes:
class Base(metaclass=MyDocParseMeta):
pass
class Spam(Base):
"""
doc string is parsed
...
"""
It is expected that the MyParser() class would return a dictionary.
This dictionary is used to create the final class Spam in this example.
'''
@staticmethod
def __new__(meta, clsname, bases, clsdict):
if "__doc__" in clsdict:
lexer = meta.lexer()
parser = meta.parser()
lexer.cls_name = parser.cls_name = clsname
lexer.cls_qualname = parser.cls_qualname = clsdict["__qualname__"]
lexer.cls_module = parser.cls_module = clsdict["__module__"]
parsedict = parser.parse(lexer.tokenize(clsdict["__doc__"]))
assert isinstance(parsedict, dict), "Parser must return a dictionary"
clsdict.update(parsedict)
return super().__new__(meta, clsname, bases, clsdict)
@classmethod
def __init_subclass__(cls):
assert hasattr(cls, "parser") and hasattr(cls, "lexer")
|