character-encoding-utils 0.0.8__tar.gz → 0.0.9__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- character_encoding_utils-0.0.9/.github/workflows/publish.yml +29 -0
- character_encoding_utils-0.0.9/.github/workflows/test.yml +25 -0
- {character_encoding_utils-0.0.8 → character_encoding_utils-0.0.9}/PKG-INFO +2 -2
- {character_encoding_utils-0.0.8 → character_encoding_utils-0.0.9}/pyproject.toml +1 -1
- character_encoding_utils-0.0.9/requirements.txt +1 -0
- {character_encoding_utils-0.0.8 → character_encoding_utils-0.0.9}/src/character_encoding_utils/big5.py +15 -11
- {character_encoding_utils-0.0.8 → character_encoding_utils-0.0.9}/src/character_encoding_utils/gb2312.py +15 -11
- {character_encoding_utils-0.0.8 → character_encoding_utils-0.0.9}/src/character_encoding_utils/ksx1001.py +16 -12
- {character_encoding_utils-0.0.8 → character_encoding_utils-0.0.9}/src/character_encoding_utils/shiftjis.py +13 -9
- {character_encoding_utils-0.0.8 → character_encoding_utils-0.0.9}/tests/test_big5.py +2 -2
- {character_encoding_utils-0.0.8 → character_encoding_utils-0.0.9}/tests/test_gb2312.py +2 -2
- {character_encoding_utils-0.0.8 → character_encoding_utils-0.0.9}/tests/test_ksx1001.py +2 -2
- {character_encoding_utils-0.0.8 → character_encoding_utils-0.0.9}/tests/test_shiftjis.py +4 -4
- character_encoding_utils-0.0.8/.github/workflows/publish.yml +0 -29
- character_encoding_utils-0.0.8/.github/workflows/test.yml +0 -24
- character_encoding_utils-0.0.8/requirements.txt +0 -1
- {character_encoding_utils-0.0.8 → character_encoding_utils-0.0.9}/.gitignore +0 -0
- {character_encoding_utils-0.0.8 → character_encoding_utils-0.0.9}/LICENSE +0 -0
- {character_encoding_utils-0.0.8 → character_encoding_utils-0.0.9}/README.md +0 -0
- {character_encoding_utils-0.0.8 → character_encoding_utils-0.0.9}/src/character_encoding_utils/__init__.py +0 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
name: Publish
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
publish:
|
|
9
|
+
environment:
|
|
10
|
+
name: pypi
|
|
11
|
+
url: https://pypi.org/project/character-encoding-utils/
|
|
12
|
+
permissions:
|
|
13
|
+
id-token: write
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- name: Checkout
|
|
17
|
+
uses: actions/checkout@v4
|
|
18
|
+
- name: Setup Python
|
|
19
|
+
uses: actions/setup-python@v5
|
|
20
|
+
with:
|
|
21
|
+
python-version: "3.x"
|
|
22
|
+
- name: Install dependencies
|
|
23
|
+
run: |
|
|
24
|
+
python -m pip install pip --upgrade
|
|
25
|
+
python -m pip install build
|
|
26
|
+
- name: Build
|
|
27
|
+
run: python -m build
|
|
28
|
+
- name: Publish
|
|
29
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
name: Test
|
|
2
|
+
|
|
3
|
+
on: [push, pull_request]
|
|
4
|
+
|
|
5
|
+
jobs:
|
|
6
|
+
test:
|
|
7
|
+
strategy:
|
|
8
|
+
matrix:
|
|
9
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
10
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
11
|
+
fail-fast: false
|
|
12
|
+
runs-on: ${{ matrix.os }}
|
|
13
|
+
steps:
|
|
14
|
+
- name: Checkout
|
|
15
|
+
uses: actions/checkout@v4
|
|
16
|
+
- name: Setup Python
|
|
17
|
+
uses: actions/setup-python@v5
|
|
18
|
+
with:
|
|
19
|
+
python-version: ${{ matrix.python-version }}
|
|
20
|
+
- name: Install dependencies
|
|
21
|
+
run: |
|
|
22
|
+
python -m pip install pip --upgrade
|
|
23
|
+
python -m pip install -r requirements.txt
|
|
24
|
+
- name: Test
|
|
25
|
+
run: python -m pytest
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: character-encoding-utils
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.9
|
|
4
4
|
Summary: Some character encoding utils.
|
|
5
5
|
Project-URL: homepage, https://github.com/TakWolf/character-encoding-utils
|
|
6
6
|
Project-URL: source, https://github.com/TakWolf/character-encoding-utils
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pytest==8.3.4
|
|
@@ -4,31 +4,35 @@ class Big5Exception(Exception):
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
class Big5EncodeError(Big5Exception):
|
|
7
|
-
|
|
7
|
+
obj: str
|
|
8
8
|
position: int
|
|
9
9
|
reason: str
|
|
10
10
|
|
|
11
11
|
def __init__(self, obj: str, position: int, reason: str):
|
|
12
|
-
|
|
13
|
-
self.object = obj
|
|
12
|
+
self.obj = obj
|
|
14
13
|
self.position = position
|
|
15
14
|
self.reason = reason
|
|
16
15
|
|
|
16
|
+
def __str__(self) -> str:
|
|
17
|
+
return f"'big5' codec can't encode character '\\u{ord(self.obj):x}' in position {self.position}: {self.reason}"
|
|
18
|
+
|
|
17
19
|
|
|
18
20
|
class Big5DecodeError(Big5Exception):
|
|
19
|
-
|
|
21
|
+
obj: bytes
|
|
20
22
|
position: int
|
|
21
23
|
reason: str
|
|
22
24
|
|
|
23
25
|
def __init__(self, obj: bytes, position: int, reason: str):
|
|
24
|
-
|
|
25
|
-
super().__init__(f"'big5' codec can't decode byte 0x{obj[0]:x} in position {position}: {reason}")
|
|
26
|
-
else:
|
|
27
|
-
super().__init__(f"'big5' codec can't decode bytes in position {position}-{position + len(obj) - 1}: {reason}")
|
|
28
|
-
self.object = obj
|
|
26
|
+
self.obj = obj
|
|
29
27
|
self.position = position
|
|
30
28
|
self.reason = reason
|
|
31
29
|
|
|
30
|
+
def __str__(self) -> str:
|
|
31
|
+
if len(self.obj) <= 1:
|
|
32
|
+
return f"'big5' codec can't decode byte 0x{self.obj[0]:x} in position {self.position}: {self.reason}"
|
|
33
|
+
else:
|
|
34
|
+
return f"'big5' codec can't decode bytes in position {self.position}-{self.position + len(self.obj) - 1}: {self.reason}"
|
|
35
|
+
|
|
32
36
|
|
|
33
37
|
def encode(cs: str) -> bytes:
|
|
34
38
|
bs = bytearray()
|
|
@@ -110,9 +114,9 @@ def query_code(c: str) -> int:
|
|
|
110
114
|
try:
|
|
111
115
|
bs = encode(c)
|
|
112
116
|
except Big5EncodeError as e:
|
|
113
|
-
raise Big5Exception(f"'{c}' is not a 'big5' character") from e
|
|
117
|
+
raise Big5Exception(f"'\\u{ord(c):x}' is not a 'big5' character") from e
|
|
114
118
|
if len(bs) == 1:
|
|
115
|
-
raise Big5Exception(f"'{c}' is a ascii character")
|
|
119
|
+
raise Big5Exception(f"'\\u{ord(c):x}' is a ascii character")
|
|
116
120
|
code = int(f'{bs[0]:02x}{bs[1]:02x}', 16)
|
|
117
121
|
return code
|
|
118
122
|
|
|
@@ -7,31 +7,35 @@ class GB2312Exception(Exception):
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class GB2312EncodeError(GB2312Exception):
|
|
10
|
-
|
|
10
|
+
obj: str
|
|
11
11
|
position: int
|
|
12
12
|
reason: str
|
|
13
13
|
|
|
14
14
|
def __init__(self, obj: str, position: int, reason: str):
|
|
15
|
-
|
|
16
|
-
self.object = obj
|
|
15
|
+
self.obj = obj
|
|
17
16
|
self.position = position
|
|
18
17
|
self.reason = reason
|
|
19
18
|
|
|
19
|
+
def __str__(self) -> str:
|
|
20
|
+
return f"'gb2312' codec can't encode character '\\u{ord(self.obj):x}' in position {self.position}: {self.reason}"
|
|
21
|
+
|
|
20
22
|
|
|
21
23
|
class GB2312DecodeError(GB2312Exception):
|
|
22
|
-
|
|
24
|
+
obj: bytes
|
|
23
25
|
position: int
|
|
24
26
|
reason: str
|
|
25
27
|
|
|
26
28
|
def __init__(self, obj: bytes, position: int, reason: str):
|
|
27
|
-
|
|
28
|
-
super().__init__(f"'gb2312' codec can't decode byte 0x{obj[0]:x} in position {position}: {reason}")
|
|
29
|
-
else:
|
|
30
|
-
super().__init__(f"'gb2312' codec can't decode bytes in position {position}-{position + len(obj) - 1}: {reason}")
|
|
31
|
-
self.object = obj
|
|
29
|
+
self.obj = obj
|
|
32
30
|
self.position = position
|
|
33
31
|
self.reason = reason
|
|
34
32
|
|
|
33
|
+
def __str__(self) -> str:
|
|
34
|
+
if len(self.obj) <= 1:
|
|
35
|
+
return f"'gb2312' codec can't decode byte 0x{self.obj[0]:x} in position {self.position}: {self.reason}"
|
|
36
|
+
else:
|
|
37
|
+
return f"'gb2312' codec can't decode bytes in position {self.position}-{self.position + len(self.obj) - 1}: {self.reason}"
|
|
38
|
+
|
|
35
39
|
|
|
36
40
|
def encode(cs: str) -> bytes:
|
|
37
41
|
bs = bytearray()
|
|
@@ -72,9 +76,9 @@ def query_coord(c: str) -> tuple[int, int]:
|
|
|
72
76
|
try:
|
|
73
77
|
bs = encode(c)
|
|
74
78
|
except GB2312EncodeError as e:
|
|
75
|
-
raise GB2312Exception(f"'{c}' is not a 'gb2312' character") from e
|
|
79
|
+
raise GB2312Exception(f"'\\u{ord(c):x}' is not a 'gb2312' character") from e
|
|
76
80
|
if len(bs) == 1:
|
|
77
|
-
raise GB2312Exception(f"'{c}' is a ascii character")
|
|
81
|
+
raise GB2312Exception(f"'\\u{ord(c):x}' is a ascii character")
|
|
78
82
|
row = bs[0] - _EUC_OFFSET
|
|
79
83
|
col = bs[1] - _EUC_OFFSET
|
|
80
84
|
return row, col
|
|
@@ -7,31 +7,35 @@ class KSX1001Exception(Exception):
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class KSX1001EncodeError(KSX1001Exception):
|
|
10
|
-
|
|
10
|
+
obj: str
|
|
11
11
|
position: int
|
|
12
12
|
reason: str
|
|
13
13
|
|
|
14
14
|
def __init__(self, obj: str, position: int, reason: str):
|
|
15
|
-
|
|
16
|
-
self.object = obj
|
|
15
|
+
self.obj = obj
|
|
17
16
|
self.position = position
|
|
18
17
|
self.reason = reason
|
|
19
18
|
|
|
19
|
+
def __str__(self) -> str:
|
|
20
|
+
return f"'ksx1001' codec can't encode character '\\u{ord(self.obj):x}' in position {self.position}: {self.reason}"
|
|
21
|
+
|
|
20
22
|
|
|
21
23
|
class KSX1001DecodeError(KSX1001Exception):
|
|
22
|
-
|
|
24
|
+
obj: bytes
|
|
23
25
|
position: int
|
|
24
26
|
reason: str
|
|
25
27
|
|
|
26
28
|
def __init__(self, obj: bytes, position: int, reason: str):
|
|
27
|
-
|
|
28
|
-
super().__init__(f"'ksx1001' codec can't decode byte 0x{obj[0]:x} in position {position}: {reason}")
|
|
29
|
-
else:
|
|
30
|
-
super().__init__(f"'ksx1001' codec can't decode bytes in position {position}-{position + len(obj) - 1}: {reason}")
|
|
31
|
-
self.object = obj
|
|
29
|
+
self.obj = obj
|
|
32
30
|
self.position = position
|
|
33
31
|
self.reason = reason
|
|
34
32
|
|
|
33
|
+
def __str__(self) -> str:
|
|
34
|
+
if len(self.obj) <= 1:
|
|
35
|
+
return f"'ksx1001' codec can't decode byte 0x{self.obj[0]:x} in position {self.position}: {self.reason}"
|
|
36
|
+
else:
|
|
37
|
+
return f"'ksx1001' codec can't decode bytes in position {self.position}-{self.position + len(self.obj) - 1}: {self.reason}"
|
|
38
|
+
|
|
35
39
|
|
|
36
40
|
def encode(cs: str) -> bytes:
|
|
37
41
|
bs = bytearray()
|
|
@@ -86,11 +90,11 @@ def query_coord(c: str) -> tuple[int, int]:
|
|
|
86
90
|
try:
|
|
87
91
|
bs = encode(c)
|
|
88
92
|
except KSX1001EncodeError as e:
|
|
89
|
-
raise KSX1001Exception(f"'{c}' is not a 'ksx1001' character") from e
|
|
93
|
+
raise KSX1001Exception(f"'\\u{ord(c):x}' is not a 'ksx1001' character") from e
|
|
90
94
|
if len(bs) == 1:
|
|
91
|
-
raise KSX1001Exception(f"'{c}' is a ascii character")
|
|
95
|
+
raise KSX1001Exception(f"'\\u{ord(c):x}' is a ascii character")
|
|
92
96
|
elif bs.startswith(b'\xa4\xd4') and len(bs) > 2:
|
|
93
|
-
raise KSX1001Exception(f"'{c}' is not a 'ksx1001' character")
|
|
97
|
+
raise KSX1001Exception(f"'\\u{ord(c):x}' is not a 'ksx1001' character")
|
|
94
98
|
row = bs[0] - _EUC_OFFSET
|
|
95
99
|
col = bs[1] - _EUC_OFFSET
|
|
96
100
|
return row, col
|
|
@@ -6,31 +6,35 @@ class ShiftJISException(Exception):
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class ShiftJISEncodeError(ShiftJISException):
|
|
9
|
-
|
|
9
|
+
obj: str
|
|
10
10
|
position: int
|
|
11
11
|
reason: str
|
|
12
12
|
|
|
13
13
|
def __init__(self, obj: str, position: int, reason: str):
|
|
14
|
-
|
|
15
|
-
self.object = obj
|
|
14
|
+
self.obj = obj
|
|
16
15
|
self.position = position
|
|
17
16
|
self.reason = reason
|
|
18
17
|
|
|
18
|
+
def __str__(self) -> str:
|
|
19
|
+
return f"'shift-jis' codec can't encode character '\\u{ord(self.obj):x}' in position {self.position}: {self.reason}"
|
|
20
|
+
|
|
19
21
|
|
|
20
22
|
class ShiftJISDecodeError(ShiftJISException):
|
|
21
|
-
|
|
23
|
+
obj: bytes
|
|
22
24
|
position: int
|
|
23
25
|
reason: str
|
|
24
26
|
|
|
25
27
|
def __init__(self, obj: bytes, position: int, reason: str):
|
|
26
|
-
|
|
27
|
-
super().__init__(f"'shift-jis' codec can't decode byte 0x{obj[0]:x} in position {position}: {reason}")
|
|
28
|
-
else:
|
|
29
|
-
super().__init__(f"'shift-jis' codec can't decode bytes in position {position}-{position + len(obj) - 1}: {reason}")
|
|
30
|
-
self.object = obj
|
|
28
|
+
self.obj = obj
|
|
31
29
|
self.position = position
|
|
32
30
|
self.reason = reason
|
|
33
31
|
|
|
32
|
+
def __str__(self) -> str:
|
|
33
|
+
if len(self.obj) <= 1:
|
|
34
|
+
return f"'shift-jis' codec can't decode byte 0x{self.obj[0]:x} in position {self.position}: {self.reason}"
|
|
35
|
+
else:
|
|
36
|
+
return f"'shift-jis' codec can't decode bytes in position {self.position}-{self.position + len(self.obj) - 1}: {self.reason}"
|
|
37
|
+
|
|
34
38
|
|
|
35
39
|
def encode(cs: str) -> bytes:
|
|
36
40
|
bs = bytearray()
|
|
@@ -10,13 +10,13 @@ def test_codec():
|
|
|
10
10
|
|
|
11
11
|
with pytest.raises(Big5EncodeError) as info:
|
|
12
12
|
big5.encode('abc가')
|
|
13
|
-
assert info.value.
|
|
13
|
+
assert info.value.obj == '가'
|
|
14
14
|
assert info.value.position == 3
|
|
15
15
|
assert info.value.reason == 'illegal multibyte sequence'
|
|
16
16
|
|
|
17
17
|
with pytest.raises(Big5DecodeError) as info:
|
|
18
18
|
big5.decode(b'abc\xa4\xa4\xb0')
|
|
19
|
-
assert info.value.
|
|
19
|
+
assert info.value.obj == b'\xb0'
|
|
20
20
|
assert info.value.position == 5
|
|
21
21
|
assert info.value.reason == 'incomplete multibyte sequence'
|
|
22
22
|
|
|
@@ -10,13 +10,13 @@ def test_codec():
|
|
|
10
10
|
|
|
11
11
|
with pytest.raises(GB2312EncodeError) as info:
|
|
12
12
|
gb2312.encode('abc가')
|
|
13
|
-
assert info.value.
|
|
13
|
+
assert info.value.obj == '가'
|
|
14
14
|
assert info.value.position == 3
|
|
15
15
|
assert info.value.reason == 'illegal multibyte sequence'
|
|
16
16
|
|
|
17
17
|
with pytest.raises(GB2312DecodeError) as info:
|
|
18
18
|
gb2312.decode(b'abc\xd6\xd0\xb9')
|
|
19
|
-
assert info.value.
|
|
19
|
+
assert info.value.obj == b'\xb9'
|
|
20
20
|
assert info.value.position == 5
|
|
21
21
|
assert info.value.reason == 'incomplete multibyte sequence'
|
|
22
22
|
|
|
@@ -10,13 +10,13 @@ def test_codec():
|
|
|
10
10
|
|
|
11
11
|
with pytest.raises(KSX1001EncodeError) as info:
|
|
12
12
|
ksx1001.encode('abc😈')
|
|
13
|
-
assert info.value.
|
|
13
|
+
assert info.value.obj == '😈'
|
|
14
14
|
assert info.value.position == 3
|
|
15
15
|
assert info.value.reason == 'illegal multibyte sequence'
|
|
16
16
|
|
|
17
17
|
with pytest.raises(KSX1001DecodeError) as info:
|
|
18
18
|
ksx1001.decode(b'abc\xb0\xa1\xc3')
|
|
19
|
-
assert info.value.
|
|
19
|
+
assert info.value.obj == b'\xc3'
|
|
20
20
|
assert info.value.position == 5
|
|
21
21
|
assert info.value.reason == 'incomplete multibyte sequence'
|
|
22
22
|
|
|
@@ -10,26 +10,26 @@ def test_codec():
|
|
|
10
10
|
|
|
11
11
|
with pytest.raises(ShiftJISEncodeError) as info:
|
|
12
12
|
shiftjis.encode('abc가')
|
|
13
|
-
assert info.value.
|
|
13
|
+
assert info.value.obj == '가'
|
|
14
14
|
assert info.value.position == 3
|
|
15
15
|
assert info.value.reason == 'illegal multibyte sequence'
|
|
16
16
|
|
|
17
17
|
with pytest.raises(ShiftJISDecodeError) as info:
|
|
18
18
|
shiftjis.decode(b'abc\x93\xfa\x96')
|
|
19
|
-
assert info.value.
|
|
19
|
+
assert info.value.obj == b'\x96'
|
|
20
20
|
assert info.value.position == 5
|
|
21
21
|
assert info.value.reason == 'incomplete multibyte sequence'
|
|
22
22
|
|
|
23
23
|
with pytest.raises(ShiftJISEncodeError) as info:
|
|
24
24
|
shiftjis.encode('\\')
|
|
25
|
-
assert info.value.
|
|
25
|
+
assert info.value.obj == '\\'
|
|
26
26
|
assert info.value.position == 0
|
|
27
27
|
assert '\\' in info.value.reason
|
|
28
28
|
assert '¥' in info.value.reason
|
|
29
29
|
|
|
30
30
|
with pytest.raises(ShiftJISEncodeError) as info:
|
|
31
31
|
shiftjis.encode('~')
|
|
32
|
-
assert info.value.
|
|
32
|
+
assert info.value.obj == '~'
|
|
33
33
|
assert info.value.position == 0
|
|
34
34
|
assert '~' in info.value.reason
|
|
35
35
|
assert '‾' in info.value.reason
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
name: Publish
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
release:
|
|
5
|
-
types: [published]
|
|
6
|
-
|
|
7
|
-
jobs:
|
|
8
|
-
publish:
|
|
9
|
-
runs-on: ubuntu-latest
|
|
10
|
-
environment:
|
|
11
|
-
name: pypi
|
|
12
|
-
url: https://pypi.org/project/character-encoding-utils/
|
|
13
|
-
permissions:
|
|
14
|
-
id-token: write
|
|
15
|
-
steps:
|
|
16
|
-
- name: Checkout
|
|
17
|
-
uses: actions/checkout@v4
|
|
18
|
-
- name: Setup Python
|
|
19
|
-
uses: actions/setup-python@v5
|
|
20
|
-
with:
|
|
21
|
-
python-version: '3.x'
|
|
22
|
-
- name: Install dependencies
|
|
23
|
-
run: |
|
|
24
|
-
python -m pip install pip --upgrade
|
|
25
|
-
python -m pip install build
|
|
26
|
-
- name: Build
|
|
27
|
-
run: python -m build
|
|
28
|
-
- name: Publish
|
|
29
|
-
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
name: Test
|
|
2
|
-
|
|
3
|
-
on: [push, pull_request]
|
|
4
|
-
|
|
5
|
-
jobs:
|
|
6
|
-
test:
|
|
7
|
-
runs-on: ubuntu-latest
|
|
8
|
-
strategy:
|
|
9
|
-
fail-fast: false
|
|
10
|
-
matrix:
|
|
11
|
-
python-version: ["3.10", "3.11", "3.12"]
|
|
12
|
-
steps:
|
|
13
|
-
- name: Checkout
|
|
14
|
-
uses: actions/checkout@v4
|
|
15
|
-
- name: Setup Python
|
|
16
|
-
uses: actions/setup-python@v5
|
|
17
|
-
with:
|
|
18
|
-
python-version: ${{ matrix.python-version }}
|
|
19
|
-
- name: Install dependencies
|
|
20
|
-
run: |
|
|
21
|
-
python -m pip install pip --upgrade
|
|
22
|
-
python -m pip install -r requirements.txt
|
|
23
|
-
- name: Test
|
|
24
|
-
run: python -m pytest
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
pytest==8.2.0
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|