Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions .github/workflows/check_format.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@ on:
- all
pull_request: { }
jobs:
black:
ruff:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Install uv
uses: astral-sh/setup-uv@v7
- name: "Black Code Formatter"
- name: "Ruff format check"
run: |
uv run black . --check
uv run ruff format --check .
- name: "Ruff import sorting check"
run: |
uv run ruff check .
3 changes: 2 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ Rules are easy. You can
Writing code
------------

All files must be formatted using [Black](https://black.readthedocs.io). Easier is not possible.
All files must be formatted using [ruff](https://docs.astral.sh/ruff/)
(`ruff format` for code style, `ruff check` for import sorting). Easier is not possible.
For bigger features it is recommended to create an own branch.
8 changes: 8 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,13 @@ test:
mypy:
uv run mypy --pretty pydifact

format:
uv run ruff format .
uv run ruff check --fix .

check-format:
uv run ruff format --check .
uv run ruff check .

test-extended:
uv run pytest
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,10 +134,12 @@ This installs all the python packages needed for development and testing.

### Code formatting

Format all python files using [black](https://black.readthedocs.io) before committing:
Format all python files and sort imports using [ruff](https://docs.astral.sh/ruff/)
before committing:

```bash
uv run black .
uv run ruff format .
uv run ruff check --fix .
```

Happy coding, PR are more than welcome to make this library better, or to add a feature that matches your needs.
Expand Down
1 change: 0 additions & 1 deletion pydifact/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
class EDISyntaxError(Exception):

def __init__(
self, message: str, line_number: int = None, column_number: int = None
):
Expand Down
1 change: 0 additions & 1 deletion pydifact/generator/create_directory_urls.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import sys

import black
from bs4 import BeautifulSoup

# This file parses the https://unece.org/trade/uncefact/unedifact/download page
Expand Down
4 changes: 2 additions & 2 deletions pydifact/generator/edcd.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import re
from os import PathLike
from xml.etree import ElementTree
from pathlib import Path
from typing import List, Dict, Any
from typing import Any, Dict, List
from xml.etree import ElementTree

from pydifact.generator.base import UntidBaseParser

Expand Down
2 changes: 1 addition & 1 deletion pydifact/generator/eded.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import re
from os import PathLike
from xml.etree import ElementTree
from pathlib import Path
from xml.etree import ElementTree

from pydifact.generator.base import UntidBaseParser

Expand Down
5 changes: 2 additions & 3 deletions pydifact/generator/edmd.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import re
from os import PathLike
from xml.etree import ElementTree
from pathlib import Path
from typing import List, Dict, Any, Optional
from typing import Any, Dict, List, Optional
from xml.etree import ElementTree

from pydifact.generator.base import UntidBaseParser

Expand Down Expand Up @@ -207,7 +207,6 @@ def _process(self, file_path: PathLike | str) -> None:

# Handle level changes
if parts[1] != "" and "Segment group" not in parts[2] and "-" in parts[5]:

level = parts[5].replace("-", "")
levels_to_remove = level.count("+")
current_level -= levels_to_remove
Expand Down
4 changes: 2 additions & 2 deletions pydifact/generator/edsd.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import re
from os import PathLike
from xml.etree import ElementTree
from pathlib import Path
from typing import List, Dict, Any
from typing import Any, Dict, List
from xml.etree import ElementTree

from pydifact.generator.base import UntidBaseParser

Expand Down
30 changes: 13 additions & 17 deletions pydifact/generator/runner.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,26 @@
import sys
import os
import re
import sys
import zipfile
from xml.etree import ElementTree
from os import PathLike
from pathlib import Path
import re

from xml.etree import ElementTree

from pydifact.generator.base import UntidBaseParser
from pydifact.generator.edsd import EDSDParser
from pydifact.generator.edcd import EDCDParser
from pydifact.generator.eded import EDEDParser
from pydifact.generator.uncl import UNCLParser
from pydifact.generator.edmd import EDMDParser
from pydifact.generator.unsl import UNSLParser
from pydifact.generator.constants import (
directories_urls,
V3_SERVICE_CODE_LISTS,
V4_SERVICE_CODE_LISTS,
services_map,
directories_urls,
renames,
services_map,
)
from pydifact.generator.utils import is_prehistoric, download_file

from os import PathLike
from pydifact.generator.edcd import EDCDParser
from pydifact.generator.eded import EDEDParser
from pydifact.generator.edmd import EDMDParser
from pydifact.generator.edsd import EDSDParser
from pydifact.generator.uncl import UNCLParser
from pydifact.generator.unsl import UNSLParser
from pydifact.generator.utils import download_file, is_prehistoric

V4_RELEASE_NUMBER = "40219"
zips_directory = Path(__file__).parent / "zips"
Expand Down Expand Up @@ -189,7 +187,6 @@ def extract_edifact_data(
"""
print(f"Parsing {parser.name}... for release '{release}'")
try:

with open(output_file, "w", encoding="utf-8") as f:
f.write(parser.get_xml())

Expand Down Expand Up @@ -313,7 +310,6 @@ def parse_messages(source_dir, target_dir) -> None:
def generate_service_codes(
syntax_version: str, extended_syntax_version: str, service_subrelease: str
):

specific_release = service_subrelease.lower()
version_dir = f"v{extended_syntax_version}"
generator_base_dir = Path(__file__).parent
Expand Down
3 changes: 1 addition & 2 deletions pydifact/generator/uncl.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import re
from os import PathLike
from xml.etree import ElementTree
from pathlib import Path
from typing import List
from xml.etree import ElementTree

from pydifact.generator.base import UntidBaseParser
from pydifact.generator.constants import MAX_LINE_LENGTH
Expand Down Expand Up @@ -249,7 +249,6 @@ def _process(self, file_path: PathLike | str) -> None:
else: # no additional line found, break
break
else:

match2 = re.match(r"^[\s]{14}(.*)", lines[i])
if match2:
if value_description:
Expand Down
4 changes: 2 additions & 2 deletions pydifact/generator/unsl.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import re
from os import PathLike
from xml.etree import ElementTree
from pathlib import Path
from typing import List, Dict
from typing import Dict, List
from xml.etree import ElementTree

from pydifact.generator.base import UntidBaseParser

Expand Down
16 changes: 8 additions & 8 deletions pydifact/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,21 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

from collections.abc import Iterator, Iterable
import logging
from collections.abc import Iterable, Iterator

from pydifact.constants import (
EDI_DEFAULT_VERSION,
EDI_DEFAULT_DIRECTORY,
EDI_DEFAULT_SYNTAX,
EDI_DEFAULT_VERSION,
Element,
Elements,
EDI_DEFAULT_DIRECTORY,
)
from pydifact.control import Characters
from pydifact.exceptions import EDISyntaxError
from pydifact.tokenizer import Tokenizer
from pydifact.token import Token
from pydifact.segments import Segment, SegmentFactory
from pydifact.control import Characters
import logging
from pydifact.token import Token
from pydifact.tokenizer import Tokenizer

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -122,7 +122,7 @@ def parse(
if una_found:
idx_begin = idx_una + len(una_pattern)
idx_end = idx_begin + 6
characters = Characters.from_str(f"UNA{message[idx_begin: idx_end]}")
characters = Characters.from_str(f"UNA{message[idx_begin:idx_end]}")

# remove the UNA segment from the string,
# ignore everything before UNA because it should be the first segment if una_found.
Expand Down
4 changes: 2 additions & 2 deletions pydifact/segmentcollection.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@
from collections.abc import Callable, Iterable, Iterator, Sequence
from typing import Type, TypeVar

from pydifact.exceptions import EDISyntaxError, ValidationError
from pydifact.constants import Element, Elements
from pydifact.control import Characters
from pydifact.exceptions import EDISyntaxError, ValidationError
from pydifact.parser import Parser
from pydifact.segments import Segment
from pydifact.constants import Element, Elements
from pydifact.serializer import Serializer

T = TypeVar("T", bound="AbstractSegmentsContainer")
Expand Down
18 changes: 9 additions & 9 deletions pydifact/segments.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,27 @@
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
import warnings
import logging
from typing import overload
import warnings
import xml.etree.ElementTree as ET
from functools import lru_cache
from pathlib import Path
import xml.etree.ElementTree as ET
from typing import overload

from pydifact.constants import (
EDI_DEFAULT_VERSION,
M,
EDI_DEFAULT_DIRECTORY,
EDI_DEFAULT_SYNTAX,
EDI_DEFAULT_VERSION,
Element,
EDI_DEFAULT_DIRECTORY,
M,
service_segments,
)
from pydifact.exceptions import (
ValidationError,
MissingImplementationWarning,
EDISyntaxError,
MissingImplementationWarning,
ValidationError,
)
from pydifact.syntax.common import DataElement, CompositeDataElement
from pydifact.syntax.common import CompositeDataElement, DataElement
from pydifact.utils import get_syntax_release_version

logger = logging.getLogger(__name__)
Expand Down
2 changes: 1 addition & 1 deletion pydifact/serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
from pydifact.control.characters import Characters
import re

from pydifact.control.characters import Characters
from pydifact.segments import Segment


Expand Down
5 changes: 2 additions & 3 deletions pydifact/syntax/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,13 @@

import re
import warnings
from typing import Optional, Type, TypeAlias, TypeVar, NamedTuple
from typing import NamedTuple, Optional, Type, TypeAlias, TypeVar

from pydifact.constants import EDI_DEFAULT_VERSION, M
from pydifact.exceptions import ValidationError

allowed_alphanum_chars = set(
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789*-./:()'&=+\"?,"
"!_\\ "
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789*-./:()'&=+\"?,!_\\ "
)


Expand Down
8 changes: 4 additions & 4 deletions pydifact/syntax/v1/__init__.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
from pydifact.constants import C, M
from pydifact.segments import Segment
from pydifact.syntax.common import (
DataElement,
CompositeDataElement,
DataElement,
SyntaxVersionNumber,
)
from pydifact.constants import M, C
from pydifact.segments import Segment

__version__ = 1

from .data import partner_identification_codes
from ... import Characters
from .data import partner_identification_codes


class ServiceStringAdvice(DataElement):
Expand Down
7 changes: 4 additions & 3 deletions pydifact/syntax/v4/__init__.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
from typing import NamedTuple

from pydifact.constants import M, C
from pydifact.constants import C, M
from pydifact.syntax import v1, v2, v3
from pydifact.syntax.common import (
DataElement,
CompositeDataElement,
DataElement,
SyntaxVersionNumber,
)
from .data import partner_identification_codes

from ... import Segment
from .data import partner_identification_codes

__version__ = 4

Expand Down
2 changes: 1 addition & 1 deletion pydifact/tokenizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@
# THE SOFTWARE.
from collections.abc import Iterator

from pydifact.control.characters import Characters
from pydifact.exceptions import EDISyntaxError
from pydifact.token import Token
from pydifact.control.characters import Characters


class Tokenizer:
Expand Down
11 changes: 8 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,20 @@ dev = [
"Sphinx>=7.2.0",
"setuptools>=69.1.0",
"wheel>=0.42.0",
"black>=25.1.0",
"ruff>=0.11.0",
"sphinx-rtd-theme>=2.0.0",
"build",
"twine",
"mypy>=1.15.0"
]

[tool.black]
target_version = ["py310", "py311", "py312", "py313"]
[tool.ruff]
target-version = "py310"

[tool.ruff.lint]
# Limit linting to import sorting (isort) for now; ruff format handles
# code style. Additional rule sets (e.g. "F" for pyflakes) can be enabled later.
select = ["I"]

[project.urls]
Documentation = "https://pydifact.readthedocs.io"
Expand Down
Loading
Loading