legacy-puyo-tools 0.1.0__py3-none-any.whl → 0.2.0__py3-none-any.whl

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.
@@ -1,7 +1,7 @@
1
1
  """A conversion tool for files used by the older Puyo games.
2
2
 
3
- Supports Puyo Puyo 7 and possibly Puyo Puyo! 15th Anniversary `mtx` and
4
- `fpd` files. Puyo Puyo!! 20th Anniversary is still not supported yet.
3
+ Supports Puyo Puyo 7 and possibly Puyo Puyo! 15th Anniversary `mtx` and `fpd` files.
4
+ Puyo Puyo!! 20th Anniversary is still not supported yet.
5
5
 
6
6
  SPDX-FileCopyrightText: 2025 Samuel Wu
7
7
  SPDX-License-Identifier: MIT
@@ -0,0 +1,10 @@
1
+ """Allow the cli to be run from runpy or using `python -m legacy_puyo_tools`.
2
+
3
+ SPDX-FileCopyrightText: 2025 Samuel Wu
4
+ SPDX-License-Identifier: MIT
5
+ """
6
+
7
+ if __name__ == "__main__":
8
+ from legacy_puyo_tools.cli import app
9
+
10
+ app()
legacy_puyo_tools/cli.py CHANGED
@@ -4,6 +4,8 @@ SPDX-FileCopyrightText: 2025 Samuel Wu
4
4
  SPDX-License-Identifier: MIT
5
5
  """
6
6
 
7
+ from __future__ import annotations
8
+
7
9
  from codecs import BOM_UTF16_LE
8
10
  from pathlib import Path
9
11
  from typing import BinaryIO
@@ -19,6 +21,7 @@ from legacy_puyo_tools.mtx import Mtx
19
21
  output_option = option(
20
22
  "--output",
21
23
  "-o",
24
+ "output_file",
22
25
  help="Output file. Defaults to an appropriate filename and extension.",
23
26
  type=cloup.File("wb"),
24
27
  )
@@ -44,11 +47,11 @@ mtx_options = option_group(
44
47
 
45
48
  @cloup.group()
46
49
  @cloup.version_option()
47
- def main() -> None:
50
+ def app() -> None:
48
51
  """A conversion tool for files used by older Puyo games."""
49
52
 
50
53
 
51
- @main.group()
54
+ @app.group()
52
55
  def create() -> None:
53
56
  """Create files to used by older Puyo games."""
54
57
 
@@ -60,21 +63,18 @@ def create() -> None:
60
63
  type=cloup.File("rb"),
61
64
  )
62
65
  @output_option
63
- def create_fpd(input_file: BinaryIO, output: BinaryIO | None) -> None:
64
- """Create a fpd file from a unicode text file."""
66
+ def create_fpd(input_file: BinaryIO, output_file: BinaryIO | None) -> None:
67
+ """Create a fpd file from a unicode text file.""" # noqa: DOC501
65
68
  if input_file.read(2) != BOM_UTF16_LE:
66
69
  raise FileFormatError(
67
70
  f"{input_file.name} is not a UTF-16 little-endian encoded text file."
68
71
  )
69
72
 
70
- if output:
71
- Fpd.read_unicode(input_file).write_fpd(output)
73
+ if output_file:
74
+ Fpd.read_unicode(input_file).write_fpd(output_file)
72
75
  return
73
76
 
74
- path = Path(input_file.name).with_suffix("")
75
-
76
- if path.suffix != ".fpd":
77
- path = path.with_suffix(".fpd")
77
+ path = Path(input_file.name).with_suffix(".fpd")
78
78
 
79
79
  Fpd.read_unicode(input_file).write_fpd_to_path(path)
80
80
 
@@ -88,13 +88,13 @@ def create_fpd(input_file: BinaryIO, output: BinaryIO | None) -> None:
88
88
  @output_option
89
89
  @mtx_options
90
90
  def create_mtx(
91
- input_file: BinaryIO, output: BinaryIO, fpd: Path | None, unicode: Path | None
91
+ input_file: BinaryIO, output_file: BinaryIO, fpd: Path | None, unicode: Path | None
92
92
  ) -> None:
93
93
  """Create a mtx file from a XML file."""
94
94
  raise NotImplementedError("Creating MTX files is currently not implemented yet.")
95
95
 
96
96
 
97
- @main.group()
97
+ @app.group()
98
98
  def convert() -> None:
99
99
  """Convert files used by older Puyo games to an editable format."""
100
100
 
@@ -108,13 +108,10 @@ def convert_fpd(input_file: BinaryIO, output_file: BinaryIO | None) -> None:
108
108
  """Convert a fpd file to a UTF-16 little-endian unicode text file."""
109
109
  if output_file:
110
110
  output_file.write(BOM_UTF16_LE)
111
- Fpd.read_fpd(input_file).write_fpd(output_file)
111
+ Fpd.read_fpd(input_file).write_unicode(output_file)
112
112
  return
113
113
 
114
- path = Path(input_file.name).with_suffix("")
115
-
116
- if path.suffix != ".fpd":
117
- path = path.with_suffix(".fpd")
114
+ path = Path(input_file.name).with_suffix(".txt")
118
115
 
119
116
  Fpd.read_fpd(input_file).write_unicode_to_path(path)
120
117
 
@@ -127,11 +124,11 @@ def convert_fpd(input_file: BinaryIO, output_file: BinaryIO | None) -> None:
127
124
  @mtx_options
128
125
  def convert_mtx(
129
126
  input_file: BinaryIO,
130
- output: BinaryIO | None,
127
+ output_file: BinaryIO | None,
131
128
  fpd: Path | None,
132
129
  unicode: Path | None,
133
130
  ) -> None:
134
- """Convert a mtx file to a XML file."""
131
+ """Convert a mtx file to a XML file.""" # noqa: DOC501
135
132
  if fpd:
136
133
  fpd_data = Fpd.read_fpd_from_path(fpd)
137
134
  elif unicode:
@@ -141,17 +138,14 @@ def convert_mtx(
141
138
  "You must specify a character table using --fpd or --unicode."
142
139
  )
143
140
 
144
- if output:
145
- Mtx.read_mtx(input_file).write_xml(output, fpd_data)
141
+ if output_file:
142
+ Mtx.read_mtx(input_file).write_xml(output_file, fpd_data)
146
143
  return
147
144
 
148
- path = Path(input_file.name).with_suffix("")
149
-
150
- if path.suffix != ".xml":
151
- path = path.with_suffix(".xml")
145
+ path = Path(input_file.name).with_suffix(".xml")
152
146
 
153
147
  Mtx.read_mtx(input_file).write_xml_to_file(path, fpd_data)
154
148
 
155
149
 
156
150
  if __name__ == "__main__":
157
- main()
151
+ app()
@@ -1,5 +1,6 @@
1
1
  """Exceptions that might be thrown when parsing files.
2
2
 
3
+ SPDX-FileCopyrightText: 2021 Nick Woronekin
3
4
  SPDX-FileCopyrightText: 2025 Samuel Wu
4
5
  SPDX-License-Identifier: MIT
5
6
  """
legacy_puyo_tools/fpd.py CHANGED
@@ -7,12 +7,15 @@ SPDX-FileCopyrightText: 2025 Samuel Wu
7
7
  SPDX-License-Identifier: MIT
8
8
  """
9
9
 
10
+ from __future__ import annotations
11
+
10
12
  from codecs import BOM_UTF16_LE
11
- from io import BytesIO
13
+ from io import BytesIO, StringIO
14
+ from os import PathLike
12
15
  from pathlib import Path
13
- from typing import BinaryIO, Self
16
+ from typing import BinaryIO
14
17
 
15
- from attrs import define
18
+ import attrs
16
19
 
17
20
  from legacy_puyo_tools.exceptions import FileFormatError, FormatError
18
21
 
@@ -22,7 +25,7 @@ UTF16_LENGTH = 2
22
25
  WIDTH_ENTRY_OFFSET = 2
23
26
 
24
27
 
25
- @define
28
+ @attrs.define
26
29
  class FpdCharacter:
27
30
  """A fpd character entry.
28
31
 
@@ -53,16 +56,21 @@ class FpdCharacter:
53
56
  self.code_point = code_point.decode(ENCODING)
54
57
  self.width = width
55
58
 
59
+ def __str__(self) -> str:
60
+ """Returns the character as a single character string."""
61
+ return self.code_point
62
+
56
63
  def encode(self) -> bytes:
57
64
  """Encodes the character back to a fpd character entry.
58
65
 
59
66
  Returns:
60
67
  The character in UTF-16 LE format and its width.
61
68
  """
62
- return self.code_point.encode(ENCODING) + self.width.to_bytes()
69
+ # TODO: When updating Python to 3.11, remove arguments from width.to_bytes
70
+ return self.code_point.encode(ENCODING) + self.width.to_bytes(1, "little")
63
71
 
64
72
  @classmethod
65
- def decode(cls, fpd_entry: bytes) -> Self:
73
+ def decode(cls, fpd_entry: bytes) -> FpdCharacter:
66
74
  """Decodes a fpd character into its code point and width.
67
75
 
68
76
  Args:
@@ -82,7 +90,7 @@ class FpdCharacter:
82
90
  return cls(fpd_entry[:UTF16_LENGTH], fpd_entry[WIDTH_ENTRY_OFFSET])
83
91
 
84
92
 
85
- @define
93
+ @attrs.define
86
94
  class Fpd:
87
95
  """A fpd character table.
88
96
 
@@ -110,8 +118,16 @@ class Fpd:
110
118
  """
111
119
  return self.entries[index].code_point
112
120
 
121
+ def __str__(self) -> str:
122
+ """Returns a string representation of the fpd character table."""
123
+ with StringIO() as string_buffer:
124
+ for character in self.entries:
125
+ string_buffer.write(str(character))
126
+
127
+ return string_buffer.getvalue()
128
+
113
129
  @classmethod
114
- def read_fpd_from_path(cls, path: Path) -> Self:
130
+ def read_fpd_from_path(cls, path: str | PathLike[str]) -> Fpd:
115
131
  """Reads and extract characters from a fpd file.
116
132
 
117
133
  Args:
@@ -133,7 +149,7 @@ class Fpd:
133
149
  raise FileFormatError(f"{path} is not a valid fpd file") from e
134
150
 
135
151
  @classmethod
136
- def read_fpd(cls, fp: BinaryIO) -> Self:
152
+ def read_fpd(cls, fp: BinaryIO) -> Fpd:
137
153
  """Reads and extract characters from a file object.
138
154
 
139
155
  Args:
@@ -146,7 +162,7 @@ class Fpd:
146
162
  return cls.decode_fpd(fp.read())
147
163
 
148
164
  @classmethod
149
- def decode_fpd(cls, data: bytes) -> Self:
165
+ def decode_fpd(cls, data: bytes) -> Fpd:
150
166
  """Extracts the fpd character table from a fpd encoded stream.
151
167
 
152
168
  Args:
@@ -161,7 +177,7 @@ class Fpd:
161
177
  for i in range(0, len(data), FPD_ENTRY_LENGTH)
162
178
  ])
163
179
 
164
- def write_fpd_to_path(self, path: Path) -> None:
180
+ def write_fpd_to_path(self, path: str | PathLike[str]) -> None:
165
181
  """Writes the fpd character table to a fpd encoded file.
166
182
 
167
183
  Args:
@@ -193,7 +209,7 @@ class Fpd:
193
209
  return bytes_buffer.getvalue()
194
210
 
195
211
  @classmethod
196
- def read_unicode_from_path(cls, path: Path) -> Self:
212
+ def read_unicode_from_path(cls, path: str | PathLike[str]) -> Fpd:
197
213
  """Reads and convert characters from a UTF-16 little-endian text file.
198
214
 
199
215
  Arguments:
@@ -218,7 +234,7 @@ class Fpd:
218
234
  return cls.read_unicode(fp)
219
235
 
220
236
  @classmethod
221
- def read_unicode(cls, fp: BinaryIO) -> Self:
237
+ def read_unicode(cls, fp: BinaryIO) -> Fpd:
222
238
  """Reads and convert UTF-16 LE characters from a file object.
223
239
 
224
240
  Args:
@@ -232,7 +248,7 @@ class Fpd:
232
248
 
233
249
  # TODO: Somehow allow people to specify the width of the character during decoding
234
250
  @classmethod
235
- def decode_unicode(cls, unicode: bytes) -> Self:
251
+ def decode_unicode(cls, unicode: bytes) -> Fpd:
236
252
  """Converts a UTF-16 LE stream into a fpd character table.
237
253
 
238
254
  Args:
@@ -247,7 +263,7 @@ class Fpd:
247
263
  for i in range(0, len(unicode), UTF16_LENGTH)
248
264
  ])
249
265
 
250
- def write_unicode_to_path(self, path: Path) -> None:
266
+ def write_unicode_to_path(self, path: str | PathLike[str]) -> None:
251
267
  """Writes the fpd character table to a UTF-16 LE text file.
252
268
 
253
269
  Args:
@@ -275,8 +291,4 @@ class Fpd:
275
291
  Returns:
276
292
  A UTF-16 LE encoded text stream with characters from the fpd.
277
293
  """
278
- with BytesIO() as bytes_buffer:
279
- for character in self.entries:
280
- bytes_buffer.write(character.code_point.encode(ENCODING))
281
-
282
- return bytes_buffer.getvalue()
294
+ return str(self).encode(ENCODING)
legacy_puyo_tools/mtx.py CHANGED
@@ -3,21 +3,44 @@
3
3
  This module converts mtx files to and from XML for modding Puyo games. Currently
4
4
  supports Puyo Puyo 7 and might support Puyo Puyo! 15th Anniversary.
5
5
 
6
+ SPDX-FileCopyrightText: 2021 Nick Woronekin
6
7
  SPDX-FileCopyrightText: 2025 Samuel Wu
7
8
  SPDX-License-Identifier: MIT
8
9
  """
9
10
 
11
+ from __future__ import annotations
12
+
13
+ import sys
10
14
  from collections.abc import Callable
11
- from itertools import pairwise
15
+ from os import PathLike
12
16
  from pathlib import Path
13
- from typing import BinaryIO, Literal, Self
17
+ from typing import BinaryIO, Literal
14
18
 
15
- from attrs import define
19
+ import attrs
16
20
  from lxml import etree
17
21
 
18
22
  from legacy_puyo_tools.exceptions import FileFormatError, FormatError
19
23
  from legacy_puyo_tools.fpd import Fpd
20
24
 
25
+ # TODO: When updating to Python 3.10, remove the stub implementation of pairwise
26
+ # from the python documentation:
27
+ # https://docs.python.org/3/library/itertools.html#itertools.pairwise
28
+ if sys.version_info >= (3, 10):
29
+ from itertools import pairwise
30
+ else:
31
+ from collections.abc import Iterable
32
+ from itertools import tee
33
+ from typing import TypeVar
34
+
35
+ T = TypeVar("T")
36
+
37
+ def pairwise(iterable: Iterable[T]) -> Iterable[tuple[T, T]]:
38
+ """Simple pairwise implementation for Python < 3.10.""" # noqa: DOC201
39
+ a, b = tee(iterable)
40
+ next(b, None)
41
+ return zip(a, b)
42
+
43
+
21
44
  CHARACTER_WIDTH = 2
22
45
  ENDIAN = "little"
23
46
 
@@ -48,15 +71,16 @@ def _identify_mtx(data: bytes) -> tuple[Literal[8, 16], Literal[4, 8]]:
48
71
  raise FormatError("The given data is not in a valid `mtx` format")
49
72
 
50
73
 
51
- type MtxString = list[int]
74
+ # TODO: When upgrading to Python 3.12, add type to the beginning of the alias
75
+ MtxString = list[int]
52
76
 
53
77
 
54
- @define
78
+ @attrs.define
55
79
  class Mtx:
56
80
  strings: list[MtxString]
57
81
 
58
82
  @classmethod
59
- def read_mtx_from_file(cls, path: Path) -> Self:
83
+ def read_mtx_from_file(cls, path: str | PathLike[str]) -> Mtx:
60
84
  with Path(path).open("rb") as fp:
61
85
  try:
62
86
  return cls.read_mtx(fp)
@@ -64,11 +88,11 @@ class Mtx:
64
88
  raise FileFormatError(f"{path} is not a valid `mtx` file") from e
65
89
 
66
90
  @classmethod
67
- def read_mtx(cls, fp: BinaryIO) -> Self:
91
+ def read_mtx(cls, fp: BinaryIO) -> Mtx:
68
92
  return cls.decode_mtx(fp.read())
69
93
 
70
94
  @classmethod
71
- def decode_mtx(cls, data: bytes) -> Self:
95
+ def decode_mtx(cls, data: bytes) -> Mtx:
72
96
  length = int.from_bytes(data[:4], ENDIAN)
73
97
 
74
98
  if length != len(data):
@@ -98,7 +122,7 @@ class Mtx:
98
122
 
99
123
  return cls(strings)
100
124
 
101
- def write_xml_to_file(self, path: Path, fpd: Fpd) -> None:
125
+ def write_xml_to_file(self, path: str | PathLike[str], fpd: Fpd) -> None:
102
126
  with Path(path).open("wb") as fp:
103
127
  self.write_xml(fp, fpd)
104
128
 
@@ -114,18 +138,18 @@ class Mtx:
114
138
  dialog.text = "\n"
115
139
 
116
140
  for character in string:
117
- match character:
118
- case 0xF813:
119
- dialog.append(etree.Element("arrow"))
120
- # TODO: Figure out what this control character does
121
- case 0xF883:
122
- dialog.text += "0xF883"
123
- case 0xFFFD:
124
- dialog.text += "\n"
125
- case 0xFFFF:
126
- break
127
- case _:
128
- dialog.text += fpd[character]
141
+ # TODO: When upgrading to Python 3.10, use `match` statements
142
+ if character == 0xF813:
143
+ dialog.append(etree.Element("arrow"))
144
+ # TODO: Figure out what this control character does
145
+ elif character == 0xF883:
146
+ dialog.text += "0xF883"
147
+ elif character == 0xFFFD:
148
+ dialog.text += "\n"
149
+ elif character == 0xFFFF:
150
+ break
151
+ else:
152
+ dialog.text += fpd[character]
129
153
 
130
154
  etree.indent(root)
131
155
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: legacy-puyo-tools
3
- Version: 0.1.0
3
+ Version: 0.2.0
4
4
  Summary: A tool to edit text for older Puyo Puyo games.
5
5
  Project-URL: changelog, https://github.com/wushenrong/legacy-puyo-tools/blob/main/CHANGELOG.md
6
6
  Project-URL: homepage, https://github.com/wushenrong/legacy-puyo-tools
@@ -14,26 +14,32 @@ Classifier: Development Status :: 2 - Pre-Alpha
14
14
  Classifier: Environment :: Console
15
15
  Classifier: Intended Audience :: Other Audience
16
16
  Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: OS Independent
17
18
  Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.9
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
18
23
  Classifier: Programming Language :: Python :: 3.13
19
24
  Classifier: Topic :: File Formats
20
25
  Classifier: Topic :: Games/Entertainment :: Puzzle Games
21
26
  Classifier: Topic :: Utilities
22
- Requires-Python: >=3.13
27
+ Requires-Python: >=3.9
23
28
  Requires-Dist: attrs>=25.3.0
24
- Requires-Dist: click>=8.2.1
29
+ Requires-Dist: click>=8.1.8
25
30
  Requires-Dist: cloup>=3.0.7
26
31
  Requires-Dist: lxml>=6.0.0
27
32
  Description-Content-Type: text/markdown
28
33
 
29
34
  # Legacy Puyo Tools
30
35
 
31
- A command line tool for modding older Puyo Puyo games. (Yes, the name is using a
32
- [reversed naming scheme](https://github.com/microsoft/WSL).)
36
+ A command line tool for modding older Puyo Puyo games (Yes, the name is using a
37
+ [reversed naming scheme](https://github.com/microsoft/WSL)).
33
38
 
34
39
  ## Installation
35
40
 
36
- Install the latest version [Python](https://www.python.org/).
41
+ Install [Python](https://www.python.org/) 3.9 or later, preferably the latest
42
+ version.
37
43
 
38
44
  `legacy-python-tools` is published to
39
45
  [PyPI](https://pypi.org/project/legacy-puyo-tools/). It is recommended to
@@ -62,14 +68,10 @@ And of course, you can use good old pip in a virtual Python environment using
62
68
 
63
69
  ```bash
64
70
  # Create a virtual python environment
65
- virualenv .venv
66
- # Or with the venv library
67
71
  python -m venv .venv
68
72
  # Activate the virtual environment
69
73
  ./.venv/Scripts/activate
70
74
  # Install legacy-python-tools
71
- pip install legacy-python-tools
72
- # Or using the pip module
73
75
  python -m pip install legacy-python-tools
74
76
  ```
75
77
 
@@ -98,21 +100,28 @@ This tool will try to support formats from the following Puyo games:
98
100
  - Puyo Puyo 7
99
101
  - Puyo Puyo!! 20th Annversivery (If there is demand)
100
102
 
101
- See [Formats](formats.md) for detailed information about those formats, and the
102
- current progress on creating and converting them.
103
+ See
104
+ [Formats](https://github.com/wushenrong/legacy-puyo-tools/blob/main/formats.md)
105
+ for detailed information about these formats, and the current progress on
106
+ creating and converting them.
103
107
 
104
108
  ## Why
105
109
 
106
110
  The [Puyo Text Editor][puyo-text-editor] can already do what `legacy-puyo-tools`
107
- does and is the inspiration of this tool, but there are advantages to rewriting
108
- it in Python:
111
+ does and is the inspiration of this tool, but there are advantages to rewrite it
112
+ in Python:
109
113
 
110
114
  [puyo-text-editor]: https://github.com/nickworonekin/puyo-text-editor
111
115
 
112
116
  - Better cross compatibility with Linux.
113
- - Don't have to update the language version every time it becomes End of Life.
117
+ - Easier migration when upgrade away from end of life language versions.
114
118
  - Avoids the rigidness of using a pure object-oriented design.
115
119
 
120
+ ## Contributing
121
+
122
+ If you want to contribute to the project check out
123
+ [Contributing](https://github.com/wushenrong/legacy-puyo-tools/blob/main/CONTRIBUTING.md).
124
+
116
125
  ## License
117
126
 
118
127
  Under the MIT License. Based on [Puyo Text Editor][puyo-text-editor] which is
@@ -0,0 +1,12 @@
1
+ legacy_puyo_tools/__init__.py,sha256=LjS0jFv5pdhJceptQG9WtToZKBMzwCCXRiCa9YofnO0,277
2
+ legacy_puyo_tools/__main__.py,sha256=LCp7zRagZzAyqpsJSzgMlRF36sWvMMNC7Ufq52cUdVQ,232
3
+ legacy_puyo_tools/cli.py,sha256=ql8nEAiojQTpl1ug6VMYIaWEXHko2_JJHk8_w7ZhCac,4128
4
+ legacy_puyo_tools/exceptions.py,sha256=0xT7q1t1r_YSZAv7OUPUgiui1QN3AwBw4cNyxOt_pkA,472
5
+ legacy_puyo_tools/fpd.py,sha256=2_FBRSZjmioYYbZ7govMqtEkXdh1Exl3NmfswvZQ1qY,8763
6
+ legacy_puyo_tools/mtx.py,sha256=3DukplefdG7jnsLaDXoQ68QaUto9qpsmYgMPmF0Pksk,4972
7
+ legacy_puyo_tools/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ legacy_puyo_tools-0.2.0.dist-info/METADATA,sha256=PqX1AU9Jr4lkZ6ynmTWFLlt1qVP0b1wCJEn-oohLMXY,4042
9
+ legacy_puyo_tools-0.2.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
10
+ legacy_puyo_tools-0.2.0.dist-info/entry_points.txt,sha256=U1UoBDFd576Xi_8PuLVUXZcGV6Idk1Bc-UlF9UNYYh0,64
11
+ legacy_puyo_tools-0.2.0.dist-info/licenses/LICENSE,sha256=4G2c45JIaRJFR-0AbNA1uV354akZGEcbnBgpdNokvGE,1117
12
+ legacy_puyo_tools-0.2.0.dist-info/RECORD,,
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ legacy-puyo-tools = legacy_puyo_tools.cli:app
@@ -1,5 +1,6 @@
1
1
  MIT License
2
2
 
3
+ Copyright (c) 2021 Nick Woronekin
3
4
  Copyright (c) 2025 Samuel Wu and contributors
4
5
 
5
6
  Permission is hereby granted, free of charge, to any person obtaining a copy of
@@ -1,11 +0,0 @@
1
- legacy_puyo_tools/__init__.py,sha256=tTzyNju0CFsXWki9ttjO6qnNx4Dlmur-1zgJ-n9toB0,277
2
- legacy_puyo_tools/cli.py,sha256=qYBGmjO2LU5afTcwcGw3WJK-csDbaJF9lr_7mxlDkeA,4207
3
- legacy_puyo_tools/exceptions.py,sha256=o0iH8s9qtt6ra8qaRW470amMszwUofsOMJr0mkCnVjM,428
4
- legacy_puyo_tools/fpd.py,sha256=7pWdfREmNFRiIMsncwUF4h5yFV3TkIPenEagfx_8Hxc,8287
5
- legacy_puyo_tools/mtx.py,sha256=fIRQJzx3UXv5q95k05eH99Ouh56CwpNRfP5uiI5S91k,4145
6
- legacy_puyo_tools/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- legacy_puyo_tools-0.1.0.dist-info/METADATA,sha256=j1yyrc2f-lA-IJCv9EPUlbTPVy7DGqKmzoMnLXO-bwE,3660
8
- legacy_puyo_tools-0.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
9
- legacy_puyo_tools-0.1.0.dist-info/entry_points.txt,sha256=SWkgMVVrmWMKaFJXbb0vx-qAjqMWnxm3_0AVwYCdZLs,65
10
- legacy_puyo_tools-0.1.0.dist-info/licenses/LICENSE,sha256=C-K9I-yQXfd_K7nB9-9HgmhXprEcMcObZsRTv02ZWP8,1083
11
- legacy_puyo_tools-0.1.0.dist-info/RECORD,,
@@ -1,2 +0,0 @@
1
- [console_scripts]
2
- legacy-puyo-tools = legacy_puyo_tools.cli:main