1
+ .. _protocol-parsing :
2
+
1
3
===============================================
2
4
Parsley Tutorial Part III: Parsing Network Data
3
5
===============================================
@@ -16,9 +18,8 @@ framing. Fortunately, Parsley can remove all of this tedium.
16
18
17
19
With :func: `parsley.makeProtocol `, Parsley can generate a `Twisted `_
18
20
`IProtocol `_-implementing class which will match incoming network data using
19
- Parsley grammar rules. Before getting started with
20
- :func: `~parsley.makeProtocol `, let's build a grammar for `netstrings `_. The
21
- netstrings protocol is very simple::
21
+ Parsley grammar rules. Before getting started with :func: `.makeProtocol `, let's
22
+ build a grammar for `netstrings `_. The netstrings protocol is very simple::
22
23
23
24
4:spam,4:eggs,
24
25
@@ -30,9 +31,9 @@ prefixed with one or more ASCII digits followed by a ``:``, and suffixed with a
30
31
:start-after: grammar =
31
32
:end-before: receiveNetstring
32
33
33
- :func: `~parsley .makeProtocol ` takes, in addition to a grammar, a factory for a
34
- "sender" and a factory for a "receiver". In the system of objects managed by
35
- the `` ParserProtocol ` `, the sender is in charge of writing data to the wire,
34
+ :func: `.makeProtocol ` takes, in addition to a grammar, a factory for a "sender"
35
+ and a factory for a "receiver". In the system of objects managed by the
36
+ :class: ` . ParserProtocol `, the sender is in charge of writing data to the wire,
36
37
and the receiver has methods called on it by the Parsley rules. To demonstrate
37
38
it, here is the final piece needed in the Parsley grammar for netstrings:
38
39
@@ -43,44 +44,45 @@ it, here is the final piece needed in the Parsley grammar for netstrings:
43
44
The receiver is always available in Parsley rules with the name ``receiver ``,
44
45
allowing Parsley rules to call methods on it.
45
46
46
- When data is received over the wire, the `` ParserProtocol `` tries to match the
47
- received data against the current rule. If the current rule requires more data
48
- to finish matching, the `` ParserProtocol `` stops and waits until more data
49
- comes in, then tries to continue matching. This repeats until the current rule
50
- is completely matched, and then the `` ParserProtocol `` starts matching any
51
- leftover data against the current rule again.
47
+ When data is received over the wire, the :class: ` . ParserProtocol ` tries to
48
+ match the received data against the current rule. If the current rule requires
49
+ more data to finish matching, the :class: ` . ParserProtocol ` stops and waits
50
+ until more data comes in, then tries to continue matching. This repeats until
51
+ the current rule is completely matched, and then the :class: ` . ParserProtocol `
52
+ starts matching any leftover data against the current rule again.
52
53
53
- One specifies the current rule by setting a `` currentRule `` attribute on the
54
- receiver, which the `` ParserProtocol `` looks at before doing any parsing.
55
- Changing the current rule is addressed in the :ref: `Switching rules
54
+ One specifies the current rule by setting a :attr: ` . currentRule ` attribute on
55
+ the receiver, which the :class: ` . ParserProtocol ` looks at before doing any
56
+ parsing. Changing the current rule is addressed in the :ref: `Switching rules
56
57
<switching-rules>` section.
57
58
58
- Since the `` ParserProtocol `` will never modify the `` currentRule `` attribute
59
- itself, the default behavior is to keep using the same rule. Parsing netstrings
60
- doesn't require any rule changing, so, the default behavior of continuing to
61
- use the same rule is fine.
59
+ Since the :class: ` . ParserProtocol ` will never modify the :attr: ` . currentRule `
60
+ attribute itself, the default behavior is to keep using the same rule. Parsing
61
+ netstrings doesn't require any rule changing, so, the default behavior of
62
+ continuing to use the same rule is fine.
62
63
63
64
Both the sender factory and receiver factory are constructed when the
64
- `` ParserProtocol ` `'s connection is established. The sender factory is a
65
- one-argument callable which will be passed the `` ParserProtocol ` `'s
65
+ :class: ` . ParserProtocol `'s connection is established. The sender factory is a
66
+ one-argument callable which will be passed the :class: ` . ParserProtocol `'s
66
67
`Transport `_. This allows the sender to send data over the transport. For
67
68
example:
68
69
69
70
.. literalinclude :: _static/listings/tutorial3-netstrings.py
70
71
:pyobject: NetstringSender
71
72
72
73
The receiver factory is another one-argument callable which is passed the
73
- constructed sender. The returned object must at least have ``prepareParsing ``
74
- and ``finishParsing `` methods. ``prepareParsing `` is called with the
75
- ``ParserProtocol `` instance when a connection is established (i.e. in the
76
- ``connectionMade `` of the ``ParserProtocol ``) and ``finishParsing `` is called
77
- when a connection is closed (i.e. in the ``connectionLost `` of the
78
- ``ParserProtocol ``).
74
+ constructed sender. The returned object must at least have
75
+ :meth: `.prepareParsing ` and :meth: `.finishParsing ` methods.
76
+ :meth: `.prepareParsing ` is called with the :class: `.ParserProtocol ` instance
77
+ when a connection is established (i.e. in the ``connectionMade `` of the
78
+ :class: `.ParserProtocol `) and :meth: `.finishParsing ` is called when a
79
+ connection is closed (i.e. in the ``connectionLost `` of the
80
+ :class: `.ParserProtocol `).
79
81
80
82
.. note ::
81
- Both the receiver factory and its returned object's `` prepareParsing `` are
82
- called at in the `` ParserProtocol `` 's ``connectionMade `` method; this
83
- separation is for ease of testing receivers.
83
+ Both the receiver factory and its returned object's :meth: ` . prepareParsing `
84
+ are called at in the :class: ` . ParserProtocol `'s ``connectionMade `` method;
85
+ this separation is for ease of testing receivers.
84
86
85
87
To demonstrate a receiver, here is a simple receiver that receives netstrings
86
88
and echos the same netstrings back:
@@ -105,8 +107,8 @@ Intermezzo: error reporting
105
107
If an exception is raised from within Parsley during parsing, whether it's due
106
108
to input not matching the current rule or an exception being raised from code
107
109
the grammar calls, the connection will be immediately closed. The traceback
108
- will be captured as a `Failure `_ and passed to the `` finishParsing `` method of
109
- the receiver.
110
+ will be captured as a `Failure `_ and passed to the :meth: ` . finishParsing `
111
+ method of the receiver.
110
112
111
113
At present, there is no way to recover from failure.
112
114
@@ -116,8 +118,8 @@ Composing senders and receivers
116
118
117
119
The design of senders and receivers is intentional to make composition easy: no
118
120
subclassing is required. While the composition is easy enough to do on your
119
- own, Parsley provides a function: :func: `~parsley .stack `. It takes a base
120
- factory followed by zero or more wrappers.
121
+ own, Parsley provides a function: :func: `.stack `. It takes a base factory
122
+ followed by zero or more wrappers.
121
123
122
124
Its use is extremely simple: ``stack(x, y, z) `` will return a callable suitable
123
125
either as a sender or receiver factory which will, when called with an
@@ -172,18 +174,18 @@ data length and the data. The amended grammar would look something like this:
172
174
:start-after: grammar =
173
175
:end-before: """
174
176
175
- Changing the current rule is as simple as changing the `` currentRule ` `
177
+ Changing the current rule is as simple as changing the :attr: ` . currentRule `
176
178
attribute on the receiver. So, the ``netstringReceived `` method could look like
177
179
this:
178
180
179
181
.. literalinclude :: _static/listings/tutorial3-netstrings2.py
180
182
:pyobject: NetstringReceiver.netstringReceived
181
183
182
- While changing the `` currentRule ` ` attribute can be done at any time, the
183
- `` ParserProtocol `` only examines the `` currentRule `` at the beginning of
184
- parsing and after a rule has finished matching. As a result, if the
185
- `` currentRule `` changes, the `` ParserProtocol `` will wait until the current
186
- rule is completely matched before switching rules.
184
+ While changing the :attr: ` . currentRule ` attribute can be done at any time, the
185
+ :class: ` . ParserProtocol ` only examines the :attr: ` . currentRule ` at the
186
+ beginning of parsing and after a rule has finished matching. As a result, if
187
+ the :attr: ` . currentRule ` changes, the :class: ` . ParserProtocol ` will wait until
188
+ the current rule is completely matched before switching rules.
187
189
188
190
:download: `The complete script is also available for download.
189
191
<_static/listings/tutorial3-netstrings2.py>`
0 commit comments