Skip to content

Commit

Permalink
Deprecate SegmentCollection gracefuly
Browse files Browse the repository at this point in the history
- plan its removal for v1.0
- move from_file() method and UNA parsing to Interchange class
- create a replacement RawSegmentCollection class for use cases with lousy
  structured segment bunches.

Ref nerdocs#19
  • Loading branch information
JocelynDelalande committed Sep 28, 2020
1 parent 1ffbe79 commit f19b765
Showing 1 changed file with 93 additions and 28 deletions.
121 changes: 93 additions & 28 deletions pydifact/segmentcollection.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import collections
from typing import List, Optional, Tuple, Union
import datetime
import warnings

from pydifact.parser import Parser
from pydifact.segments import Segment
Expand All @@ -49,23 +50,6 @@ def __init__(self, extra_header_elements: List[Union[str, List[str]]] = []):
# Flag whether the UNA header is present
self.has_una_segment = False

@classmethod
def from_file(cls, file: str, encoding: str = "iso8859-1") -> "SegmentCollection":
"""Create a SegmentCollection instance from a file.
Raises FileNotFoundError if filename is not found.
:param encoding: an optional string which specifies the encoding. Default is "iso8859-1".
:param file: The full path to a file that contains an EDI message.
:rtype: SegmentCollection
"""

# codecs.lookup raises an LookupError if given codec was not found:
codecs.lookup(encoding)

with open(file, encoding=encoding) as f:
collection = f.read()
return cls.from_str(collection)

@classmethod
def from_str(cls, string: str) -> "SegmentCollection":
"""Create a SegmentCollection instance from a string.
Expand Down Expand Up @@ -128,17 +112,10 @@ def add_segments(
return self

def add_segment(self, segment: Segment) -> "SegmentCollection":
"""Append a segment to the collection. Passing a UNA segment means setting/overriding the control
characters and setting the serializer to output the Service String Advice. If you wish to change the control
characters from the default and not output the Service String Advice, change self.characters instead,
without passing a UNA Segment.
"""Append a segment to the collection.
:param segment: The segment to add
"""
if segment.tag == "UNA":
self.has_una_segment = True
self.characters = Characters.from_str(segment.elements[0])
return self
self.segments.append(segment)
return self

Expand Down Expand Up @@ -178,8 +155,96 @@ def __str__(self) -> str:
return self.serialize()


# For backward compatibility
SegmentCollection = AbstractSegmentsContainer
class FileSourcableMixin:
"""
For backward compatibility
For v1.0 drop this class and move from_file() to Interchange class.
"""
@classmethod
def from_file(cls, file: str, encoding: str = "iso8859-1") -> "SegmentCollection":
"""Create a Interchange instance from a file.
Raises FileNotFoundError if filename is not found.
:param encoding: an optional string which specifies the encoding. Default is "iso8859-1".
:param file: The full path to a file that contains an EDI message.
:rtype: SegmentCollection
"""
# codecs.lookup raises an LookupError if given codec was not found:
codecs.lookup(encoding)

with open(file, encoding=encoding) as f:
collection = f.read()
return cls.from_str(collection)

class UNAHandlingMixin:
"""
For backward compatibility
For v1.0 drop this class and move add_segment() to Interchange class.
"""

def add_segment(self, segment: Segment) -> "SegmentCollection":
"""Append a segment to the collection. Passing a UNA segment means setting/overriding the control
characters and setting the serializer to output the Service String Advice. If you wish to change the control
characters from the default and not output the Service String Advice, change self.characters instead,
without passing a UNA Segment.
:param segment: The segment to add
"""
if segment.tag == "UNA":
self.has_una_segment = True
self.characters = Characters.from_str(segment.elements[0])
return self
return super().add_segment(segment)



class SegmentCollection(FileSourcableMixin, UNAHandlingMixin, AbstractSegmentsContainer):
"""
For backward compatibility, drop it in v1.0
Will be replaced by Interchange or RawSegmentCollection depending on the need.
"""
def __init__(self, *args, **kwargs):
warnings.warn(
"SegmentCollection is deprecated and will no longer be available in v1.0, "
"replace it with Interchange or RawSegmentCollection",
DeprecationWarning,
)
super().__init__(*args, **kwargs)

@classmethod
def from_file(cls, *args, **kwargs):
warnings.warn(
"SegmentCollection.from_file will be removed in v1.0, "
"Use Interchange class instead",
DeprecationWarning,
)
return super().from_file(*args, **kwargs)

def add_segment(self, segment):
if segment.tag == "UNA":
warnings.warn(
"SegmentCollection will be removed in v1.0, "
"For UNA handling, use Interchange class instead",
DeprecationWarning,
)
return super().add_segment(segment)


class RawSegmentCollection(AbstractSegmentsContainer):
"""
A way to analyze arbitrary bunch of edifact segments.
Similar to the deprecated SegmentCollection, but lacking from_file() and UNA support.
If you are handling an Interchange or a Message, you may want to prefer
those classes to RawSegmentCollection, as they offer more features and
checks.
"""
pass



class Message(AbstractSegmentsContainer):
Expand Down Expand Up @@ -217,7 +282,7 @@ def get_footer_segment(self) -> Segment:
)


class Interchange(AbstractSegmentsContainer):
class Interchange(FileSourcableMixin, UNAHandlingMixin, AbstractSegmentsContainer):
"""
An interchange (started by UNB segment, ended by UNZ segment)
Expand Down

0 comments on commit f19b765

Please sign in to comment.