Skip to content

Commit c4228e5

Browse files
committed
Refactor the documentation of AbstractSegmentsContainer
1 parent 9b4ad96 commit c4228e5

File tree

1 file changed

+65
-57
lines changed

1 file changed

+65
-57
lines changed

pydifact/segmentcollection.py

Lines changed: 65 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,30 @@
3434

3535

3636
class AbstractSegmentsContainer:
37-
"""Represent a collection of EDI Segments for both reading and writing.
37+
"""Abstract base class of subclasses containing collection of segments.
3838
39-
You should not instantiate AbstractSegmentsContainer itself, but subclass it use that.
39+
:class:`AbstractSegmentsContainer` is the superclass of several classes such as
40+
:class:`RawSegmentCollection` and :class:`Interchange` and contains methods common
41+
to them.
4042
41-
The segments list in AbstractSegmentsContainer includes header and footer segments too.
42-
Inheriting envelopes must NOT include these elements in .segments, as get_header_element() and
43-
get_footer_element() should provide these elements on-the-fly.
43+
**Implementation detail:** Subclasses must set :attr:`HEADER_TAG` and
44+
:attr:`FOOTER_TAG`.
4445
45-
Inheriting classes must set HEADER_TAG and FOOTER_TAG
46+
:param extra_header_elements: A list of elements to be appended at the end
47+
of the header segment (same format as :class:`~pydifact.segments.Segment`
48+
constructor elements).
49+
50+
:param characters: The set of control characters
51+
52+
.. attribute:: segments
53+
54+
The segments that comprise the container. This does not include the envelope
55+
(that is, the header and footer) segments. To get the envolope segments, use
56+
as :meth:`get_header_segment` and :meth:`get_footer_segment`.
57+
58+
.. attribute:: characters
59+
60+
The control characters (a :class:`~pydifact.control.Characters` object).
4661
"""
4762

4863
HEADER_TAG: str = None
@@ -53,13 +68,6 @@ def __init__(
5368
extra_header_elements: List[Union[str, List[str]]] = None,
5469
characters: Optional[Characters] = None,
5570
):
56-
"""
57-
:param extra_header_elements: a list of elements to be appended at the end
58-
of the header segment (same format as Segment() constructor *elements).
59-
:param characters: the set of control characters
60-
"""
61-
62-
# The segments that make up this message
6371
self.segments = []
6472

6573
# set of control characters
@@ -81,10 +89,9 @@ def from_str(
8189
) -> "AbstractSegmentsContainer":
8290
"""Create an instance from a string.
8391
84-
This method is intended for usage in inheriting classes, not it AbstractSegmentsContainer itself.
85-
:param string: The EDI content
86-
:param parser: A parser to convert the tokens to segments, defaults to `Parser`
87-
:param characters: the set of control characters
92+
:param string: The EDI content.
93+
:param parser: A parser to convert the tokens to segments; defaults to `Parser`.
94+
:param characters: The set of control characters.
8895
"""
8996
if parser is None:
9097
parser = Parser(characters=characters)
@@ -99,11 +106,12 @@ def from_segments(
99106
segments: Union[List, Iterable],
100107
characters: Optional[Characters] = None,
101108
) -> "AbstractSegmentsContainer":
102-
"""Create a new AbstractSegmentsContainer instance from a iterable list of segments.
109+
"""Create an instance from a list of segments.
103110
104-
:param segments: The segments of the EDI interchange
105-
:param characters: the set of control characters
111+
:param segments: The segments of the EDI interchange.
106112
:type segments: list/iterable of Segment
113+
114+
:param characters: The set of control characters.
107115
"""
108116

109117
# create a new instance of AbstractSegmentsContainer and return it
@@ -115,11 +123,13 @@ def get_segments(
115123
name: str,
116124
predicate: Callable = None, # Python3.9+ Callable[[Segment], bool]
117125
) -> list:
118-
"""Get all the segments that match the requested name.
126+
"""Get all segments that match the requested name.
119127
120-
:param name: The name of the segments to return
121-
:param predicate: Optional predicate callable that returns True if the given segment matches a condition
122-
:rtype: list of Segment
128+
:param name: The name of the segments to return.
129+
:param predicate: Optional callable that returns True if the given
130+
segment matches a condition.
131+
132+
:rtype: list of :class:`Segment` objects.
123133
"""
124134
for segment in self.segments:
125135
if segment.tag == name and (predicate is None or predicate(segment)):
@@ -132,10 +142,11 @@ def get_segment(
132142
) -> Optional[Segment]:
133143
"""Get the first segment that matches the requested name.
134144
135-
:return: The requested segment, or None if not found
136-
:param name: The name of the segment to return
145+
:param name: The name of the segment to return.
137146
:param predicate: Optional predicate that must match on the segments
138-
to return
147+
to return.
148+
149+
:return: The requested segment, or None if not found.
139150
"""
140151
for segment in self.get_segments(name, predicate):
141152
return segment
@@ -146,17 +157,18 @@ def split_by(
146157
self,
147158
start_segment_tag: str,
148159
) -> Iterable: # Python3.9+ Iterable["RawSegmentCollection"]
149-
"""Split a segment collection by tag.
150-
151-
Everything before the first start segment is ignored, so if no matching
152-
start segment is found at all, returned result is empty.
160+
"""Split the segment collection by tag.
153161
162+
Assuming the collection contains tags ``["A", "B", "A", "A", "B", "D"]``,
163+
``split_by("A")`` would return ``[["A", "B"], ["A"], ["A", "B", "D"]]``.
164+
Everything before the first start segment is ignored, so if no matching start
165+
segment is found at all, the returned result is empty.
154166
155167
:param start_segment_tag:
156168
the segment tag we want to use as separator
157169
158-
:return: generator of segment collections. The start tag is included in
159-
each yielded collection
170+
:return: Generator of segment collections. The start tag is included in
171+
each yielded collection.
160172
"""
161173
current_list = None
162174

@@ -176,13 +188,15 @@ def split_by(
176188
def add_segments(
177189
self, segments: Union[List[Segment], Iterable]
178190
) -> "AbstractSegmentsContainer":
179-
"""Add multiple segments to the collection. Passing a UNA segment means setting/overriding the control
180-
characters and setting the serializer to output the Service String Advice. If you wish to change the control
181-
characters from the default and not output the Service String Advice, change self.characters instead,
182-
without passing a UNA Segment.
191+
"""Append a list of segments to the collection.
192+
193+
Passing a ``UNA`` segment means setting/overriding the control characters and
194+
setting the serializer to output the Service String Advice. If you wish to
195+
change the control characters from the default and not output the Service String
196+
Advice, change :attr:`characters` instead, without passing a UNA Segment.
183197
184-
:param segments: The segments to add
185-
:type segments: list or iterable of Segments
198+
:param segments: The segments to add.
199+
:type segments: List or iterable of :class:`~pydifact.segments.Segment` objects.
186200
"""
187201
for segment in segments:
188202
self.add_segment(segment)
@@ -192,31 +206,30 @@ def add_segments(
192206
def add_segment(self, segment: Segment) -> "AbstractSegmentsContainer":
193207
"""Append a segment to the collection.
194208
195-
Note: skips segments that are header or footer tags of this segment container type.
209+
Note: skips segments that are header or footer tags of this segment container
210+
type.
211+
196212
:param segment: The segment to add
197213
"""
198214
if not segment.tag in (self.HEADER_TAG, self.FOOTER_TAG):
199215
self.segments.append(segment)
200216
return self
201217

202218
def get_header_segment(self) -> Optional[Segment]:
203-
"""Craft and return this container header segment (if any)
204-
205-
:returns: None if there is no header for that container
219+
"""Return the header segment or ``None`` if there is no header.
206220
"""
207221
return None
208222

209223
def get_footer_segment(self) -> Optional[Segment]:
210-
"""Craft and return this container footer segment (if any)
211-
212-
:returns: None if there is no footer for that container
224+
"""Return the footer segment or ``None`` if there is no footer.
213225
"""
214226
return None
215227

216228
def serialize(self, break_lines: bool = False) -> str:
217-
"""Serialize all the segments added to this object.
229+
"""Return the string representation of the object.
218230
219-
:param break_lines: if True, insert line break after each segment terminator.
231+
:param break_lines: If ``True``, inserts line break after each segment
232+
terminator.
220233
"""
221234
header = self.get_header_segment()
222235
footer = self.get_footer_segment()
@@ -235,18 +248,13 @@ def serialize(self, break_lines: bool = False) -> str:
235248
)
236249

237250
def validate(self):
238-
"""Validates this container.
251+
"""Validate the object.
239252
240-
This method must be overridden in implementing subclasses, and should make sure that
241-
the container is implemented correctly.
242-
243-
It does not return anything and should raise an Exception in case of errors.
253+
Raises an exception if the object is invalid.
244254
"""
245255
raise NotImplementedError
246256

247257
def __str__(self) -> str:
248-
"""Allow the object to be serialized by casting to a string."""
249-
250258
return self.serialize()
251259

252260

@@ -411,9 +419,9 @@ class Interchange(FileSourcableMixin, UNAHandlingMixin, AbstractSegmentsContaine
411419
412420
Optional features of UNB are not yet supported.
413421
414-
Functional groups are not yet supported
422+
Functional groups are not yet supported.
415423
416-
Messages are supported, see get_message() and get_message(), but are
424+
Messages are supported (see :meth:`get_message`), but are
417425
optional: interchange segments can be accessed without going through
418426
messages.
419427

0 commit comments

Comments
 (0)