### Install pydifact using pip or uv Source: https://context7.com/nerdocs/pydifact/llms.txt Install the pydifact library from PyPI. Recommended to use uv for installation. ```bash pip install pydifact ``` ```bash uv pip install pydifact ``` -------------------------------- ### Install pydifact using pip Source: https://github.com/nerdocs/pydifact/blob/master/README.md Install the pydifact library using pip or uv. It is recommended to use uv for the development process. ```bash uv pip install pydifact # or python -m pip install pydifact ``` ```bash git clone https://github.com/nerdocs/pydifact.git cd pydifact uv sync ``` -------------------------------- ### Get the first matching segment Source: https://context7.com/nerdocs/pydifact/llms.txt Returns the first Segment with a given tag from a container, or None if not found. An optional predicate can filter segments further. ```python from pydifact.segmentcollection import Interchange interchange = Interchange.from_str( "UNA:+.? '" "UNB+UNOC:3+SENDER+RECEIVER+200102:2212+REF001'" "BGM+380+INV001+9'" "DTM+137:20240115:102'" "UNZ+2+REF001'" ) # Get the first BGM segment unconditionally bgm = interchange.get_segment("BGM") if bgm: print(f"Document type: {bgm.elements[0]}") # 380 = Invoice print(f"Document no: {bgm.elements[1]}") # INV001 # Get a DTM segment with a predicate (qualifier 137 = document date) dtm = interchange.get_segment("DTM", predicate=lambda s: s[0][0] == "137") if dtm: print(f"Document date: {dtm[0][1]}") # 20240115 ``` -------------------------------- ### AbstractSegmentsContainer.split_by() Source: https://context7.com/nerdocs/pydifact/llms.txt Splits a flat segment collection into sub-collections, where each sub-collection starts with a specified tag. Any content preceding the first occurrence of the start tag is discarded. This method is particularly useful for processing messages that have multiple line items. ```APIDOC ## `AbstractSegmentsContainer.split_by()` — Split a segment collection by a tag Splits a flat segment collection into sub-collections, each starting at the given tag. Content before the first occurrence of the start tag is discarded. Useful for splitting multi-line-item messages. ```python from pydifact.segmentcollection import RawSegmentCollection collection = RawSegmentCollection.from_str( "LIN+1++5412345678908:SRV'" "QTY+47:10'" "PRI+AAA:9.95'" "LIN+2++5412345000013:SRV'" "QTY+47:5'" "PRI+AAA:14.50'" ) for line_item in collection.split_by("LIN"): lin = line_item.get_segment("LIN") qty = line_item.get_segment("QTY") pri = line_item.get_segment("PRI") print(f"Item {lin[0]}: EAN={lin[2][0]}, qty={qty[1]}, price={pri[1][1]}") # Item 1: EAN=5412345678908, qty=10, price=9.95 # Item 2: EAN=5412345000013, qty=5, price=14.50 ``` ``` -------------------------------- ### Split segment collection by tag with split_by() Source: https://context7.com/nerdocs/pydifact/llms.txt The `split_by()` method divides a flat segment collection into sub-collections, each beginning with a specified tag. This is particularly useful for parsing multi-line item messages, discarding any content preceding the first occurrence of the start tag. ```python from pydifact.segmentcollection import RawSegmentCollection collection = RawSegmentCollection.from_str( "LIN+1++5412345678908:SRV'" "QTY+47:10'" "PRI+AAA:9.95'" "LIN+2++5412345000013:SRV'" "QTY+47:5'" "PRI+AAA:14.50'" ) for line_item in collection.split_by("LIN"): lin = line_item.get_segment("LIN") qty = line_item.get_segment("QTY") pri = line_item.get_segment("PRI") print(f"Item {lin[0]}: EAN={lin[2][0]}, qty={qty[1]}, price={pri[1][1]}") # Item 1: EAN=5412345678908, qty=10, price=9.95 # Item 2: EAN=5412345000013, qty=5, price=14.50 ``` -------------------------------- ### Run All Tests with pytest Source: https://github.com/nerdocs/pydifact/blob/master/README.md Execute all tests using pytest. This is the recommended command for faster testing. ```bash make test ``` -------------------------------- ### Create BGMSegment using SegmentFactory Source: https://context7.com/nerdocs/pydifact/llms.txt Demonstrates how SegmentFactory automatically uses BGMSegment for 'BGM' tags. Ensure the SegmentFactory is initialized before use. ```python factory = SegmentFactory() seg = factory.create_segment("BGM", "380", "INV-2024-001", "9", validate=False) print(type(seg).__name__) # BGMSegment print(seg.document_type) # 380 print(seg.document_number) # INV-2024-001 ``` -------------------------------- ### Create and Serialize EDIFACT Interchange Source: https://github.com/nerdocs/pydifact/blob/master/README.md Create an EDIFACT interchange object on the fly, add segments, and then serialize it to a string. ```python from pydifact.segmentcollection import Interchange from pydifact.segments import Segment interchange = Interchange(syntax_identifier=("IBMA",1), sender="MeMyselfAndIrene", recipient="TheOtherOne", control_reference="KLuzs7c6") interchange.add_segment(Segment("QTY", ["12", "3"])) print(interchange.serialize()) ``` -------------------------------- ### Run Extended Tests for Performance Source: https://github.com/nerdocs/pydifact/blob/master/README.md Include additional tests that check the performance of parsing large files. Use this command for more comprehensive testing. ```bash make test-extended ``` -------------------------------- ### Interchange.from_file() Source: https://context7.com/nerdocs/pydifact/llms.txt Reads an EDI file from disk and returns a fully parsed Interchange object. Supports specifying file encoding. ```APIDOC ## Interchange.from_file() - Parse an EDI interchange from a file ### Description Reads an EDI file from disk and returns a fully parsed `Interchange`. Defaults to ISO-8859-1 encoding, which is standard for EDIFACT, but accepts any Python codec name. ### Method `Interchange.from_file(file_path: str, encoding: str = "iso8859-1")` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```python from pydifact.segmentcollection import Interchange try: interchange = Interchange.from_file("./invoice.edi", encoding="iso8859-1") print(f"Loaded interchange from file, ref: {interchange.control_reference}") except FileNotFoundError: print("EDI file not found.") except LookupError as e: print(f"Unknown encoding: {e}") except Exception as e: print(f"Syntax error in file: {e}") ``` ### Response #### Success Response (Interchange Object) - **control_reference** (str) - The control reference from the UNB segment of the loaded interchange. #### Response Example ``` Loaded interchange from file, ref: ``` #### Error Response - **FileNotFoundError** - Raised if the specified EDI file does not exist. - **LookupError** - Raised if the specified encoding is not recognized by Python. - **Exception** - Raised for any other parsing or syntax errors in the file. ``` -------------------------------- ### Format Code with Black Source: https://github.com/nerdocs/pydifact/blob/master/README.md Format all Python files in the project using the Black code formatter before committing changes. ```bash uv run black . ``` -------------------------------- ### Include or Override Service String Advice (UNA) Source: https://github.com/nerdocs/pydifact/blob/master/README.md Add or modify the Service String Advice segment (UNA) by specifying it as a regular segment during interchange construction. ```python interchange.add_segment(Segment("UNA", ":+.? '")) ``` -------------------------------- ### Read Interchange from File Source: https://github.com/nerdocs/pydifact/blob/master/README.md Use the Interchange.from_file method to read a full Interchange from a file path. ```python from pydifact.segmentcollection import Interchange interchange = Interchange.from_file("./tests/data/wikipedia.edi") interchange = Interchange.from_str( "UNA:+,? '" "UNB+UNOC:1+1234+3333+200102:2212+42'" "UNH+42z42+PAORES:93:1:IA'" "MSG+1:45'" "IFT+3+XYZCOMPANY AVAILABILITY'" "ERC+A7V:1:AMD'" "UNT+5+42z42'UNZ+2+42'" ) for message in interchange.get_messages(): for segment in message.segments: print(f"Segment tag: {segment.tag}, content: {segment.elements}") ``` -------------------------------- ### Parse EDI interchange from file Source: https://context7.com/nerdocs/pydifact/llms.txt Reads an EDIFACT file from disk and returns an Interchange object. Defaults to ISO-8859-1 encoding but accepts any Python codec. ```python from pydifact.segmentcollection import Interchange try: interchange = Interchange.from_file("./invoice.edi", encoding="iso8859-1") print(f"Loaded interchange from file, ref: {interchange.control_reference}") except FileNotFoundError: print("EDI file not found.") except LookupError as e: print(f"Unknown encoding: {e}") except Exception as e: print(f"Syntax error in file: {e}") ``` -------------------------------- ### Build an interchange programmatically with Interchange constructor Source: https://context7.com/nerdocs/pydifact/llms.txt Construct a new `Interchange` object from scratch by providing sender, recipient, control reference, and syntax identifier. Segments and messages can be added subsequently using `add_segment()` or `add_message()`. ```python import datetime from pydifact.segmentcollection import Interchange, Message from pydifact.segments import Segment # Build a minimal ORDERS interchange interchange = Interchange( syntax_identifier=("UNOC", 3), sender="BUYERGLNID", recipient="SUPPLIERGLNID", control_reference="PO20240115", timestamp=datetime.datetime(2024, 1, 15, 10, 30), ) # Add UNA to include the Service String Advice in output interchange.add_segment(Segment("UNA", ":+.? '")) # Build a message and add it msg = Message(reference_number="1", identifier=["ORDERS", "D", "96A", "UN"]) msg.add_segment(Segment("BGM", "220", "BKOD99", "9")) msg.add_segment(Segment("DTM", ["137", "20240115", "102"])) interchange.add_message(msg) print(interchange.serialize()) # UNA:+.? 'UNB+UNOC:3+BUYERGLNID+SUPPLIERGLNID+240115:1030+PO20240115' # UNH+1+ORDERS:D:96A:UN'BGM+220+BKOD99+9'DTM+137:20240115:102'UNT+4+1'UNZ+1+PO20240115' # Pretty-printed (non-standard but widely used): print(interchange.serialize(break_lines=True)) ``` -------------------------------- ### Parse EDI interchange from string Source: https://context7.com/nerdocs/pydifact/llms.txt Parses a UN/EDIFACT interchange string into an Interchange object. Automatically detects syntax version and validates the envelope. ```python from pydifact.segmentcollection import Interchange edi_string = ( "UNA:+.? '" "UNB+UNOC:3+SENDER:1+RECEIVER:1+200102:2212+42'" "UNH+1+ORDERS:D:96A:UN:EAN008'" "BGM+220+BKOD99+9'" "DTM+137:20200102:102'" "UNT+4+1'" "UNZ+1+42'" ) try: interchange = Interchange.from_str(edi_string) print(f"Sender: {interchange.sender}") print(f"Recipient: {interchange.recipient}") print(f"Reference: {interchange.control_reference}") print(f"Syntax: {interchange.syntax_identifier}") # Sender: SENDER # Recipient: RECEIVER # Reference: 42 # Syntax: ('UNOC', 3) except Exception as e: print(f"Parse error: {e}") ``` -------------------------------- ### Segment Source: https://context7.com/nerdocs/pydifact/llms.txt Represents a single EDIFACT segment, allowing for low-level construction and access. The constructor takes the segment tag as the first argument, followed by data elements. Elements can be accessed by index, and composite elements are represented as lists of strings. ```APIDOC ## `Segment` — Low-level EDI segment construction and access Represents a single EDIFACT segment. The first argument to the constructor is the three-letter uppercase tag; subsequent arguments are data elements (strings or lists of strings for composite elements). Elements are accessed by index. ```python from pydifact.segments import Segment # Simple segment qty = Segment("QTY", ["21", "100", "PCE"]) print(qty.tag) # QTY print(qty[0]) # ['21', '100', 'PCE'] print(qty[0][1]) # 100 # Segment with multiple data elements nad = Segment( "NAD", "BY", # qualifier ["5412345000099", "", "9"], # composite: party ID "", # name/address format "", "ACME Corp", "123 Main St", "Cityville", ) print(nad.tag) # NAD print(nad.elements[1]) # ['5412345000099', '', '9'] # Equality check s1 = Segment("BGM", "380", "INV001") s2 = Segment("BGM", "380", "INV001") print(s1 == s2) # True ``` ``` -------------------------------- ### Serialize segments to EDI string with Serializer Source: https://context7.com/nerdocs/pydifact/llms.txt The Serializer converts a list of Segment objects into an EDI string. It can optionally include a UNA Service String Advice header and line breaks between segments. Custom control characters can also be specified. ```python from pydifact.serializer import Serializer from pydifact.segments import Segment from pydifact.control import Characters # Default characters serializer = Serializer() segments = [ Segment("BGM", "380", "INV-001", "9"), Segment("DTM", ["137", "20240115", "102"]), Segment("MOA", ["79", "1500.00"]), ] # With UNA header (default) print(serializer.serialize(segments, with_una_header=True)) # UNA:+,? 'BGM+380+INV-001+9'DTM+137:20240115:102'MOA+79:1500.00' # Without UNA header, with line breaks print(serializer.serialize(segments, with_una_header=False, break_lines=True)) # BGM+380+INV-001+9' # DTM+137:20240115:102' # MOA+79:1500.00' # Custom control characters (e.g., semicolon as segment terminator) custom_chars = Characters(segment_terminator=";") custom_serializer = Serializer(characters=custom_chars) print(custom_serializer.serialize(segments, with_una_header=True)) # UNA:+,? ;BGM+380+INV-001+9;DTM+137:20240115:102;MOA+79:1500.00; ``` -------------------------------- ### Serializer.serialize() Source: https://context7.com/nerdocs/pydifact/llms.txt Converts a list of Segment objects into a standards-compliant EDI string, optionally including a UNA Service String Advice header and optional line breaks between segments. ```APIDOC ## `Serializer.serialize()` — Serialize segments to an EDI string Converts a list of `Segment` objects into a standards-compliant EDI string, optionally including a UNA Service String Advice header and optional line breaks between segments. ```python from pydifact.serializer import Serializer from pydifact.segments import Segment from pydifact.control import Characters # Default characters serializer = Serializer() segments = [ Segment("BGM", "380", "INV-001", "9"), Segment("DTM", ["137", "20240115", "102"]), Segment("MOA", ["79", "1500.00"]), ] # With UNA header (default) print(serializer.serialize(segments, with_una_header=True)) # UNA:+,? 'BGM+380+INV-001+9'DTM+137:20240115:102'MOA+79:1500.00' # Without UNA header, with line breaks print(serializer.serialize(segments, with_una_header=False, break_lines=True)) # BGM+380+INV-001+9' # DTM+137:20240115:102' # MOA+79:1500.00' # Custom control characters (e.g., semicolon as segment terminator) custom_chars = Characters(segment_terminator=";") custom_serializer = Serializer(characters=custom_chars) print(custom_serializer.serialize(segments, with_una_header=True)) # UNA:+,? ;BGM+380+INV-001+9;DTM+137:20240115:102;MOA+79:1500.00; ``` ``` -------------------------------- ### Interchange.from_str() Source: https://context7.com/nerdocs/pydifact/llms.txt Parses a complete UN/EDIFACT interchange string into an Interchange object. It automatically detects the syntax version and validates the envelope. ```APIDOC ## Interchange.from_str() - Parse an EDI interchange from a string ### Description Parses a complete UN/EDIFACT interchange string (including UNA/UNB envelope) into an `Interchange` object. Automatically detects the syntax version from the UNB header and validates the envelope accordingly. ### Method `Interchange.from_str(edi_string: str)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```python from pydifact.segmentcollection import Interchange edi_string = ( "UNA:+.? '" "UNB+UNOC:3+SENDER:1+RECEIVER:1+200102:2212+42'" "UNH+1+ORDERS:D:96A:UN:EAN008'" "BGM+220+BKOD99+9'" "DTM+137:20200102:102'" "UNT+4+1'" "UNZ+1+42'" ) try: interchange = Interchange.from_str(edi_string) print(f"Sender: {interchange.sender}") print(f"Recipient: {interchange.recipient}") print(f"Reference: {interchange.control_reference}") print(f"Syntax: {interchange.syntax_identifier}") except Exception as e: print(f"Parse error: {e}") ``` ### Response #### Success Response (Interchange Object) - **sender** (str) - The sender identifier from the UNB segment. - **recipient** (str) - The recipient identifier from the UNB segment. - **control_reference** (str) - The control reference from the UNB segment. - **syntax_identifier** (tuple) - A tuple containing the syntax identifier and version (e.g., ('UNOC', 3)). #### Response Example ``` Sender: SENDER Recipient: RECEIVER Reference: 42 Syntax: ('UNOC', 3) ``` #### Error Response - **Exception** - Raised if there is a parsing error in the EDI string. ``` -------------------------------- ### Interchange constructor Source: https://context7.com/nerdocs/pydifact/llms.txt Constructs a new Interchange object programmatically. This allows for building EDIFACT interchanges from scratch by specifying sender, recipient, control reference, and syntax identifier. Segments and messages can be added subsequently using `add_segment()` or `add_message()`. ```APIDOC ## `Interchange` constructor — Build an interchange programmatically Creates a new `Interchange` from scratch by supplying sender, recipient, control reference, and syntax identifier. Segments and messages are added using `add_segment()` or `add_message()`. ```python import datetime from pydifact.segmentcollection import Interchange, Message from pydifact.segments import Segment # Build a minimal ORDERS interchange interchange = Interchange( syntax_identifier=("UNOC", 3), sender="BUYERGLNID", recipient="SUPPLIERGLNID", control_reference="PO20240115", timestamp=datetime.datetime(2024, 1, 15, 10, 30), ) # Add UNA to include the Service String Advice in output interchange.add_segment(Segment("UNA", ":+.? '")) # Build a message and add it msg = Message(reference_number="1", identifier=["ORDERS", "D", "96A", "UN"]) msg.add_segment(Segment("BGM", "220", "BKOD99", "9")) msg.add_segment(Segment("DTM", ["137", "20240115", "102"])) interchange.add_message(msg) print(interchange.serialize()) # UNA:+.? 'UNB+UNOC:3+BUYERGLNID+SUPPLIERGLNID+240115:1030+PO20240115' # UNH+1+ORDERS:D:96A:UN'BGM+220+BKOD99+9'DTM+137:20240115:102'UNT+4+1'UNZ+1+PO20240115' # Pretty-printed (non-standard but widely used): print(interchange.serialize(break_lines=True)) ``` ``` -------------------------------- ### SegmentFactory.create_segment() Source: https://context7.com/nerdocs/pydifact/llms.txt Creates a Segment (or registered subclass) by tag name. Optionally validates the segment against the EDIFACT XML schema for the given directory. ```APIDOC ## `SegmentFactory.create_segment()` — Create validated segments Creates a `Segment` (or registered subclass) by tag name. If a registered `Segment` subclass matches the tag and version, it is instantiated; otherwise a generic `Segment` is created. Optionally validates the segment against the EDIFACT XML schema for the given directory. ```python from pydifact.segments import SegmentFactory factory = SegmentFactory() # Create a generic segment with validation disabled seg = factory.create_segment("DTM", ["137", "20240115", "102"], validate=False) print(seg.tag) # DTM print(seg.elements) # [['137', '20240115', '102']] # Create a segment with XML-schema validation against the d21a directory try: seg = factory.create_segment( "BGM", "380", "INV001", "9", validate=True, directory="d21a", ) print("BGM segment is valid.") except Exception as e: print(f"Validation error: {e}") ``` ``` -------------------------------- ### Parse raw EDIFACT segments with RawSegmentCollection.from_str() Source: https://context7.com/nerdocs/pydifact/llms.txt Use `RawSegmentCollection.from_str()` to parse a sequence of EDIFACT segments that are not enclosed within a full interchange envelope (UNA/UNB/UNZ). This is useful for validating or transforming partial EDI payloads. ```python from pydifact.segmentcollection import RawSegmentCollection raw = RawSegmentCollection.from_str( "BGM+380+INV-2024-001+9'" "DTM+137:20240115:102'" "NAD+BY+5412345000099::9++ACME Corp+Street 1+City++12345+DE'" ) for segment in raw.segments: print(f"Tag: {segment.tag:4s} Elements: {segment.elements}") # Tag: BGM Elements: ['380', 'INV-2024-001', '9'] # Tag: DTM Elements: [['137', '20240115', '102']] # Tag: NAD Elements: ['BY', ['5412345000099', '', '9'], '', '', 'ACME Corp', 'Street 1', 'City', '', '12345', 'DE'] ``` -------------------------------- ### Parser.parse() Source: https://context7.com/nerdocs/pydifact/llms.txt Parses an EDI string into an iterator of Segment objects. Automatically detects and applies the UNA control characters. Usable standalone for low-level parsing without constructing an Interchange. ```APIDOC ## `Parser.parse()` — Low-level segment tokenization Parses an EDI string into an iterator of `Segment` objects. Automatically detects and applies the UNA control characters. Usable standalone for low-level parsing without constructing an `Interchange`. ```python from pydifact.parser import Parser parser = Parser() edi = ( "UNA:+.? '" "UNB+UNOC:3+SENDER+RECEIVER+200102:2212+42'" "BGM+220+ORD001+9'" "UNZ+1+42'" ) for segment in parser.parse(edi): print(f"{segment.tag}: {segment.elements}") # UNA: [:+.? '] # UNB: [['UNOC', '3'], 'SENDER', 'RECEIVER', ['200102', '2212'], '42'] # BGM: ['220', 'ORD001', '9'] # UNZ: ['1', '42'] print(f"Detected syntax: {parser.syntax_identifier}, version: {parser.version}") # Detected syntax: UNOC, version: 3 ``` ``` -------------------------------- ### Manage EDIFACT control characters with Characters Source: https://context7.com/nerdocs/pydifact/llms.txt The Characters class encapsulates the six EDIFACT control characters. It can be instantiated with default values, parsed from a UNA string, or modified using the `with_control_character` method. It can be used with Parser and Serializer. ```python from pydifact.control import Characters from pydifact.parser import Parser # Default characters chars = Characters() print(str(chars)) # :+,? ' print(chars.data_separator) # + print(chars.component_separator) # : print(chars.segment_terminator) # ' # Parse from a UNA segment string chars2 = Characters.from_str("UNA:+.? '") print(chars2.decimal_point) # . # Override a single control character (returns a new instance) custom = chars.with_control_character("segment_terminator", "|") print(custom.segment_terminator) # | print(chars.segment_terminator) # ' (original unchanged) # Use in a Parser or Serializer parser = Parser(characters=custom) ``` -------------------------------- ### Parse EDI string into segments with Parser Source: https://context7.com/nerdocs/pydifact/llms.txt The Parser.parse() method tokenizes an EDI string into an iterator of Segment objects. It automatically detects and applies UNA control characters. This can be used for low-level parsing without constructing an Interchange. ```python from pydifact.parser import Parser parser = Parser() edi = ( "UNA:+.? '" "UNB+UNOC:3+SENDER+RECEIVER+200102:2212+42'" "BGM+220+ORD001+9'" "UNZ+1+42'" ) for segment in parser.parse(edi): print(f"{segment.tag}: {segment.elements}") # UNA: [:+.? '] # UNB: [['UNOC', '3'], 'SENDER', 'RECEIVER', ['200102', '2212'], '42'] # BGM: ['220', 'ORD001', '9'] # UNZ: ['1', '42'] print(f"Detected syntax: {parser.syntax_identifier}, version: {parser.version}") # Detected syntax: UNOC, version: 3 ``` -------------------------------- ### Construct and access EDIFACT segments with Segment Source: https://context7.com/nerdocs/pydifact/llms.txt The `Segment` class represents a single EDIFACT segment. The tag is the first argument, followed by data elements which can be strings or lists for composite elements. Elements are accessed by index. ```python from pydifact.segments import Segment # Simple segment qty = Segment("QTY", ["21", "100", "PCE"]) print(qty.tag) # QTY print(qty[0]) # ['21', '100', 'PCE'] print(qty[0][1]) # 100 # Segment with multiple data elements nad = Segment( "NAD", "BY", # qualifier ["5412345000099", "", "9"], # composite: party ID "", # name/address format "", "ACME Corp", "123 Main St", "Cityville", ) print(nad.tag) # NAD print(nad.elements[1]) # ['5412345000099', '', '9'] # Equality check s1 = Segment("BGM", "380", "INV001") s2 = Segment("BGM", "380", "INV001") print(s1 == s2) # True ``` -------------------------------- ### Create custom Segment subclasses for typed segments Source: https://context7.com/nerdocs/pydifact/llms.txt Extend pydifact by subclassing `Segment` and setting the `tag` class attribute. The `SegmentFactory` will automatically discover and use these custom classes when creating segments with a matching tag. Custom validation can be implemented in the `validate` method. ```python from pydifact.segments import Segment, SegmentFactory from pydifact.exceptions import ValidationError class BGMSegment(Segment): """Business document message segment.""" tag = "BGM" __omitted__ = False # must be set to False to register the plugin @property def document_type(self): return self.elements[0] if self.elements else None @property def document_number(self): return self.elements[1] if len(self.elements) > 1 else None def validate(self, syntax_version: str, directory: str) -> None: super().validate(syntax_version, directory) if not self.document_number: raise ValidationError("BGM must have a document number.") ``` -------------------------------- ### Interchange.get_messages() Source: https://context7.com/nerdocs/pydifact/llms.txt Iterates over all `Message` objects within an interchange, yielding each one. ```APIDOC ## Interchange.get_messages() - Iterate over messages in an interchange ### Description Yields each `Message` object (UNH…UNT envelope) found within the interchange. Raises `EDISyntaxError` if a UNH is not properly closed with a UNT or vice versa. ### Method `Interchange.get_messages()` ### Parameters None ### Request Example ```python from pydifact.segmentcollection import Interchange interchange = Interchange.from_str( "UNA:+.? '" "UNB+UNOC:3+1234+3333+200102:2212+42'" "UNH+42z42+PAORES:93:1:IA'" "MSG+1:45'" "IFT+3+XYZCOMPANY AVAILABILITY'" "ERC+A7V:1:AMD'" "UNT+5+42z42'" "UNZ+1+42'" ) for message in interchange.get_messages(): print(f"Message type: {message.type}") # e.g. PAORES print(f"Message version: {message.version}") # e.g. 93.1 print(f"Segment count: {len(message.segments)}") for segment in message.segments: print(f" [{segment.tag}] {segment.elements}") ``` ### Response #### Success Response (Iterator of Message Objects) - **Message Object** - Each yielded object represents a single EDIFACT message. - **type** (str) - The message type identifier (e.g., 'PAORES'). - **version** (str) - The message version number (e.g., '93.1'). - **segments** (list) - A list of `Segment` objects within this message. #### Response Example ``` Message type: PAORES Message version: 93.1 Segment count: 3 [MSG] ['1', '45'] [IFT] ['3', 'XYZCOMPANY AVAILABILITY'] [ERC] ['A7V', '1', 'AMD'] ``` #### Error Response - **EDISyntaxError** - Raised if a UNH segment is not properly closed by a UNT segment, or vice versa. ``` -------------------------------- ### Characters Source: https://context7.com/nerdocs/pydifact/llms.txt Encapsulates the six EDIFACT control characters (component separator, data separator, decimal point, escape character, reserved character, segment terminator). Default values follow the EDIFACT standard. Can be instantiated from a UNA string. ```APIDOC ## `Characters` — Control characters for EDIFACT parsing and serialization Encapsulates the six EDIFACT control characters (component separator, data separator, decimal point, escape character, reserved character, segment terminator). Default values follow the EDIFACT standard. Can be instantiated from a UNA string. ```python from pydifact.control import Characters # Default characters chars = Characters() print(str(chars)) # :+,? ' print(chars.data_separator) # + print(chars.component_separator) # : print(chars.segment_terminator) # ' # Parse from a UNA segment string chars2 = Characters.from_str("UNA:+.? '") print(chars2.decimal_point) # . # Override a single control character (returns a new instance) custom = chars.with_control_character("segment_terminator", "|") print(custom.segment_terminator) # | print(chars.segment_terminator) # ' (original unchanged) # Use in a Parser or Serializer from pydifact.parser import Parser parser = Parser(characters=custom) ``` ``` -------------------------------- ### RawSegmentCollection.from_str() Source: https://context7.com/nerdocs/pydifact/llms.txt Parses a raw sequence of EDIFACT segments that are not enclosed within a full interchange envelope (UNA/UNB/UNZ). This is useful for validating or transforming partial EDI payloads. ```APIDOC ## `RawSegmentCollection.from_str()` — Parse a raw, non-interchange segment bunch Parses an arbitrary sequence of EDIFACT segments that are not wrapped in a full UNA/UNB/UNZ interchange envelope. Useful for validating or transforming partial EDI payloads. ```python from pydifact.segmentcollection import RawSegmentCollection raw = RawSegmentCollection.from_str( "BGM+380+INV-2024-001+9'" "DTM+137:20240115:102'" "NAD+BY+5412345000099::9++ACME Corp+Street 1+City++12345+DE'" ) for segment in raw.segments: print(f"Tag: {segment.tag:4s} Elements: {segment.elements}") # Tag: BGM Elements: ['380', 'INV-2024-001', '9'] # Tag: DTM Elements: [['137', '20240115', '102']] # Tag: NAD Elements: ['BY', ['5412345000099', '', '9'], '', '', 'ACME Corp', 'Street 1', 'City', '', '12345', 'DE'] ``` ``` -------------------------------- ### Iterate over matching segments with get_segments() Source: https://context7.com/nerdocs/pydifact/llms.txt Use `get_segments()` to retrieve all segments matching a specific tag from a collection. This is useful for handling messages with multiple occurrences of the same segment type, such as DTM or LIN. ```python from pydifact.segmentcollection import Interchange interchange = Interchange.from_str( "UNA:+.? '" "UNB+UNOC:3+SENDER+RECEIVER+200102:2212+REF001'" "DTM+137:20240115:102'" "DTM+2:20240120:102'" "DTM+63:20240131:102'" "UNZ+3+REF001'" ) for dtm in interchange.get_segments("DTM"): qualifier = dtm[0][0] date = dtm[0][1] labels = {"137": "Document date", "2": "Delivery date", "63": "Latest delivery"} print(f"{labels.get(qualifier, qualifier)}: {date}") # Document date: 20240115 # Delivery date: 20240120 # Latest delivery: 20240131 ``` -------------------------------- ### AbstractSegmentsContainer.get_segment() Source: https://context7.com/nerdocs/pydifact/llms.txt Retrieves the first segment matching a given tag, optionally filtered by a predicate function. ```APIDOC ## AbstractSegmentsContainer.get_segment() - Get the first matching segment ### Description Returns the first `Segment` with the given tag from the container, or `None` if not found. An optional `predicate` callable can be used to filter segments further. ### Method `AbstractSegmentsContainer.get_segment(tag: str, predicate: callable = None)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```python from pydifact.segmentcollection import Interchange interchange = Interchange.from_str( "UNA:+.? '" "UNB+UNOC:3+SENDER+RECEIVER+200102:2212+REF001'" "BGM+380+INV001+9'" "DTM+137:20240115:102'" "UNZ+2+REF001'" ) # Get the first BGM segment unconditionally bgm = interchange.get_segment("BGM") if bgm: print(f"Document type: {bgm.elements[0]}") # 380 = Invoice print(f"Document no: {bgm.elements[1]}") # INV001 # Get a DTM segment with a predicate (qualifier 137 = document date) dtM = interchange.get_segment("DTM", predicate=lambda s: s[0][0] == "137") if dtm: print(f"Document date: {dtm[0][1]}") # 20240115 ``` ### Response #### Success Response (Segment Object or None) - **Segment Object** - The first `Segment` object matching the tag and predicate. - **tag** (str) - The segment tag (e.g., 'BGM'). - **elements** (list) - A list of strings representing the segment elements. - **None** - If no segment matches the provided tag and predicate. #### Response Example ``` Document type: 380 Document no: INV001 Document date: 20240115 ``` #### Error Response None explicitly mentioned for this method, assuming standard Python behavior for invalid inputs. ``` -------------------------------- ### Create validated segments with SegmentFactory Source: https://context7.com/nerdocs/pydifact/llms.txt Use SegmentFactory to create Segment objects by tag name. It supports instantiation of registered subclasses or generic Segments. Validation against EDIFACT XML schemas is optional. ```python from pydifact.segments import SegmentFactory factory = SegmentFactory() # Create a generic segment with validation disabled seg = factory.create_segment("DTM", ["137", "20240115", "102"], validate=False) print(seg.tag) # DTM print(seg.elements) # [['137', '20240115', '102']] # Create a segment with XML-schema validation against the d21a directory try: seg = factory.create_segment( "BGM", "380", "INV001", "9", validate=True, directory="d21a", ) print("BGM segment is valid.") except Exception as e: print(f"Validation error: {e}") ``` -------------------------------- ### Parse Raw Segment Collection Source: https://github.com/nerdocs/pydifact/blob/master/README.md Use RawSegmentCollection.from_str to parse a string containing only segments, not a full interchange. ```python from pydifact.segmentcollection import RawSegmentCollection collection = RawSegmentCollection.from_str("UNH+1+ORDERS:D:96A:UN:EAN008'") for segment in collection.segments: print(f"Segment tag: {segment.tags}, content: {segment.elements}") ``` -------------------------------- ### AbstractSegmentsContainer.get_segments() Source: https://context7.com/nerdocs/pydifact/llms.txt Iterates over all segments with a given tag within a segment collection. This is useful for messages that contain multiple segments of the same type, such as multiple DTM or LIN lines. ```APIDOC ## `AbstractSegmentsContainer.get_segments()` — Iterate over all matching segments Yields all segments with the given tag. Useful when multiple segments of the same type appear in a message (e.g., multiple `DTM` or `LIN` lines). ```python from pydifact.segmentcollection import Interchange interchange = Interchange.from_str( "UNA:+.? '" "UNB+UNOC:3+SENDER+RECEIVER+200102:2212+REF001'" "DTM+137:20240115:102'" "DTM+2:20240120:102'" "DTM+63:20240131:102'" "UNZ+3+REF001'" ) for dtm in interchange.get_segments("DTM"): qualifier = dtm[0][0] date = dtm[0][1] labels = {"137": "Document date", "2": "Delivery date", "63": "Latest delivery"} print(f"{labels.get(qualifier, qualifier)}: {date}") # Document date: 20240115 # Delivery date: 20240120 # Latest delivery: 20240131 ``` ``` -------------------------------- ### Iterate Directly on Segments Source: https://github.com/nerdocs/pydifact/blob/master/README.md Iterate directly over all segments within an Interchange object after parsing it from a string. ```python from pydifact.segmentcollection import Interchange interchange = Interchange.from_str( "UNA:+,? '" "UNB+UNOC:1+1234+3333+200102:2212+42'" "UNH+42z42+PAORES:93:1:IA'" "MSG+1:45'" "IFT+3+XYZCOMPANY AVAILABILITY'" "ERC+A7V:1:AMD'" "UNT+5+42z42'UNZ+2+42'" ) for segment in interchange.segments: print(f"Segment tag: {segment.tags}, content: {segment.elements}") ``` -------------------------------- ### Custom Segment subclass Source: https://context7.com/nerdocs/pydifact/llms.txt Register domain-specific segment classes by subclassing Segment and setting the tag class attribute. The SegmentFactory automatically discovers and uses registered subclasses when creating segments with a matching tag. ```APIDOC ## Custom `Segment` subclass — Plugin system for typed segments Register domain-specific segment classes by subclassing `Segment` and setting the `tag` class attribute. The `SegmentFactory` automatically discovers and uses registered subclasses when creating segments with a matching tag. ```python from pydifact.segments import Segment, SegmentFactory from pydifact.exceptions import ValidationError class BGMSegment(Segment): """Business document message segment.""" tag = "BGM" __omitted__ = False # must be set to False to register the plugin @property def document_type(self): return self.elements[0] if self.elements else None @property def document_number(self): return self.elements[1] if len(self.elements) > 1 else None def validate(self, syntax_version: str, directory: str) -> None: super().validate(syntax_version, directory) if not self.document_number: raise ValidationError("BGM must have a document number.") ``` ``` -------------------------------- ### Iterate over messages in an interchange Source: https://context7.com/nerdocs/pydifact/llms.txt Yields each Message object within an interchange. Raises EDISyntaxError if UNH is not closed by UNT or vice versa. ```python from pydifact.segmentcollection import Interchange interchange = Interchange.from_str( "UNA:+.? '" "UNB+UNOC:3+1234+3333+200102:2212+42'" "UNH+42z42+PAORES:93:1:IA'" "MSG+1:45'" "IFT+3+XYZCOMPANY AVAILABILITY'" "ERC+A7V:1:AMD'" "UNT+5+42z42'" "UNZ+1+42'" ) for message in interchange.get_messages(): print(f"Message type: {message.type}") # e.g. PAORES print(f"Message version: {message.version}") # e.g. 93.1 print(f"Segment count: {len(message.segments)}") for segment in message.segments: print(f" [{segment.tag}] {segment.elements}") ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.