Skip to content

Commit 47229ec

Browse files
committed
Fix type issues (pyright)
1 parent 6275a7c commit 47229ec

11 files changed

Lines changed: 324 additions & 173 deletions

File tree

games/ff12/Archive/Model.py

Lines changed: 50 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from enum import IntEnum, auto
2+
from typing import Any, cast
23

34
from PyQt6.QtCore import QAbstractItemModel, QFileInfo, QModelIndex, Qt
45
from PyQt6.QtWidgets import QFileIconProvider
@@ -7,15 +8,22 @@
78

89

910
class TreeNode:
10-
def __init__(self, name: str, parent=None, is_dir=False, size=0, entry=None):
11+
def __init__(
12+
self,
13+
name: str,
14+
parent: "TreeNode | None" = None,
15+
is_dir: bool = False,
16+
size: int = 0,
17+
entry: Any | None = None,
18+
):
1119
self.name = name
1220
self.parent = parent
1321
self.is_dir = is_dir
1422
self.size = size
15-
self.children = []
23+
self.children: list[TreeNode] = []
1624
self.entry = entry
1725

18-
if parent:
26+
if parent is not None:
1927
parent.children.append(self)
2028

2129
def child_count(self) -> int:
@@ -37,19 +45,19 @@ def path(self) -> str:
3745
return self.parent.path() + "/" + self.name
3846
return self.name
3947

40-
def sort_children(self, column: int, order: Qt.SortOrder):
48+
def sort_children(self, column: int, order: Qt.SortOrder) -> None:
4149
"""Sort children by the specified column and order.
4250
Directories always come before files.
4351
Directories only reorder when column == NAME.
4452
"""
45-
dirs = [i for i in self.children if i.is_dir]
53+
dirs: list[TreeNode] = [i for i in self.children if i.is_dir]
4654
if column == ArchiveColumn.NAME:
4755
dirs.sort(
4856
key=lambda node: node.name.lower(),
4957
reverse=(order == Qt.SortOrder.DescendingOrder),
5058
)
5159

52-
files = [i for i in self.children if not i.is_dir]
60+
files: list[TreeNode] = [i for i in self.children if not i.is_dir]
5361
if column == ArchiveColumn.NAME:
5462
files.sort(
5563
key=lambda node: node.name.lower(),
@@ -78,25 +86,28 @@ class ArchiveColumn(IntEnum):
7886

7987

8088
class ArchiveModel(QAbstractItemModel):
81-
def __init__(self, parent=None):
89+
def __init__(self, parent: Any | None = None):
8290
super().__init__(parent)
83-
self._reader = None
91+
self._reader: ArchiveReader | None = None
8492
self._icon_provider = QFileIconProvider()
8593
self._root_node = TreeNode("", None, True)
8694
self._sort_column = ArchiveColumn.NAME
8795
self._sort_order = Qt.SortOrder.AscendingOrder
8896

89-
def set_data(self, reader: ArchiveReader):
97+
def set_data(self, reader: ArchiveReader) -> None:
9098
self.beginResetModel()
9199
self._reader = reader
92100
self._build_tree()
93101
self._sort_tree()
94102
self.endResetModel()
95103

96-
def _build_tree(self):
104+
def _build_tree(self) -> None:
97105
"""Build the tree structure from archive entries."""
106+
if self._reader is None:
107+
return
108+
98109
dir_nodes: dict[str, TreeNode] = {"": self._root_node}
99-
sorted_entries = sorted(self._reader._entries.items(), key=lambda x: x[0])
110+
sorted_entries = sorted(self._reader._entries.items(), key=lambda x: x[0]) # pyright: ignore[reportPrivateUsage]
100111

101112
for name, entry in sorted_entries:
102113
path_parts = name.split("/")
@@ -119,18 +130,22 @@ def _build_tree(self):
119130
filename = path_parts[-1]
120131
TreeNode(filename, current_node, False, entry.original_size, entry)
121132

122-
def _sort_tree(self):
133+
def _sort_tree(self) -> None:
123134
"""Sort the entire tree."""
124135
self._root_node.sort_children(self._sort_column, self._sort_order)
125136

126-
def sort(self, column: int, order: Qt.SortOrder):
137+
def sort(
138+
self,
139+
column: int,
140+
order: Qt.SortOrder = Qt.SortOrder.AscendingOrder,
141+
) -> None:
127142
"""Implement sorting with proper persistent index handling"""
128143
persistent_indexes = self.persistentIndexList()
129144

130-
old_nodes = []
145+
old_nodes: list[TreeNode | None] = []
131146
for index in persistent_indexes:
132147
if index.isValid():
133-
old_nodes.append(index.internalPointer())
148+
old_nodes.append(cast(TreeNode, index.internalPointer()))
134149
else:
135150
old_nodes.append(None)
136151

@@ -142,7 +157,7 @@ def sort(self, column: int, order: Qt.SortOrder):
142157
self._sort_order = order
143158
self._sort_tree()
144159

145-
new_indexes = []
160+
new_indexes: list[QModelIndex] = []
146161
for node in old_nodes:
147162
if node is not None:
148163
new_index = self._find_index_for_node(node)
@@ -162,9 +177,9 @@ def _find_index_for_node(self, target_node: TreeNode) -> QModelIndex:
162177
if target_node == self._root_node:
163178
return QModelIndex()
164179

165-
path = []
166-
current = target_node
167-
while current and current != self._root_node:
180+
path: list[TreeNode] = []
181+
current: TreeNode | None = target_node
182+
while current is not None and current != self._root_node:
168183
path.append(current)
169184
current = current.parent
170185

@@ -176,49 +191,54 @@ def _find_index_for_node(self, target_node: TreeNode) -> QModelIndex:
176191

177192
return current_index
178193

179-
def rowCount(self, parent: QModelIndex) -> int:
194+
def rowCount(self, parent: QModelIndex = QModelIndex()) -> int:
180195
if not parent.isValid():
181196
parent_node = self._root_node
182197
else:
183-
parent_node = parent.internalPointer()
198+
parent_node = cast(TreeNode, parent.internalPointer())
184199

185200
return parent_node.child_count()
186201

187-
def columnCount(self, parent: QModelIndex) -> int:
202+
def columnCount(self, parent: QModelIndex = QModelIndex()) -> int:
203+
_ = parent
188204
return len(ArchiveColumn)
189205

190-
def index(self, row: int, column: int, parent: QModelIndex) -> QModelIndex:
206+
def index(
207+
self, row: int, column: int, parent: QModelIndex = QModelIndex()
208+
) -> QModelIndex:
191209
if not self.hasIndex(row, column, parent):
192210
return QModelIndex()
193211

194212
if not parent.isValid():
195213
parent_node = self._root_node
196214
else:
197-
parent_node = parent.internalPointer()
215+
parent_node = cast(TreeNode, parent.internalPointer())
198216

199217
child_node = parent_node.child(row)
200218
if child_node:
201219
return self.createIndex(row, column, child_node)
202220

203221
return QModelIndex()
204222

205-
def parent(self, index: QModelIndex) -> QModelIndex:
206-
if not index.isValid():
223+
def parent(self, child: QModelIndex) -> QModelIndex: # pyright: ignore[reportIncompatibleMethodOverride]
224+
if not child.isValid():
207225
return QModelIndex()
208226

209-
child_node = index.internalPointer()
227+
child_node = cast(TreeNode, child.internalPointer())
210228
parent_node = child_node.parent
211229

212230
if parent_node == self._root_node or parent_node is None:
213231
return QModelIndex()
214232

215233
return self.createIndex(parent_node.row(), 0, parent_node)
216234

217-
def data(self, index: QModelIndex, role: int = Qt.ItemDataRole.DisplayRole):
235+
def data(
236+
self, index: QModelIndex, role: int = Qt.ItemDataRole.DisplayRole
237+
) -> Any | None:
218238
if not index.isValid():
219239
return None
220240

221-
node = index.internalPointer()
241+
node = cast(TreeNode, index.internalPointer())
222242
column = index.column()
223243

224244
if role == Qt.ItemDataRole.DisplayRole:
@@ -270,7 +290,7 @@ def headerData(
270290
def get_node(self, index: QModelIndex) -> TreeNode | None:
271291
"""Get the TreeNode for a given index."""
272292
if index.isValid():
273-
return index.internalPointer()
293+
return cast(TreeNode, index.internalPointer())
274294
return None
275295

276296
@staticmethod

games/ff12/Archive/Reader.py

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@
22
import struct
33
import zlib
44
from pathlib import Path
5-
from typing import BinaryIO, Dict, List
5+
from types import TracebackType
6+
from typing import BinaryIO
67

78
from PyQt6.QtCore import qWarning
89

910

1011
class ArchiveEntry:
11-
def __init__(self, original_size: int, data_offset: int, block_sizes: List[int]):
12+
def __init__(self, original_size: int, data_offset: int, block_sizes: list[int]):
1213
self.original_size = original_size
1314
self.data_offset = data_offset
1415
self.block_sizes = block_sizes
@@ -19,7 +20,7 @@ class ArchiveReader:
1920

2021
def __init__(self, path: Path):
2122
self._filename = path
22-
self._entries: Dict[str, ArchiveEntry] = {}
23+
self._entries: dict[str, ArchiveEntry] = {}
2324
self._file_handle: BinaryIO | None = None
2425

2526
self._load_metadata()
@@ -50,20 +51,27 @@ def __enter__(self):
5051
self.open()
5152
return self
5253

53-
def __exit__(self, exc_type, exc_val, exc_tb):
54+
def __exit__(
55+
self,
56+
exc_type: type[BaseException] | None,
57+
exc_val: BaseException | None,
58+
exc_tb: TracebackType | None,
59+
) -> None:
5460
"""Enable 'with' statement to automatically open and close the file handle."""
5561
self.close()
5662

5763
def _load_metadata(self):
5864
"""Load the archive metadata"""
59-
with self as file:
60-
file = file._file_handle
65+
with self:
66+
file = self._file_handle
67+
if file is None:
68+
return
6169
try:
6270
header_data = file.read(16)
6371
if len(header_data) < 16:
6472
raise EOFError("File too short for header")
6573

66-
magic, header_size, file_count = struct.unpack("<IIQ", header_data)
74+
magic, _header_size, file_count = struct.unpack("<IIQ", header_data)
6775
if magic != 0x4B595253:
6876
raise ValueError("Invalid archive format")
6977

@@ -97,10 +105,12 @@ def _load_metadata(self):
97105
except Exception as e:
98106
qWarning(f"Failed to load archive metadata: {e}")
99107

100-
def _read_file_metadata(self, file: BinaryIO, count: int) -> List[tuple]:
108+
def _read_file_metadata(
109+
self, file: BinaryIO, count: int
110+
) -> list[tuple[int, int, int, int]]:
101111
"""Read metadata for file entries"""
102112
file_struct = struct.Struct("<IIQQQ")
103-
file_metadata = []
113+
file_metadata: list[tuple[int, int, int, int]] = []
104114

105115
for _ in range(count):
106116
data = file.read(file_struct.size)
@@ -129,7 +139,7 @@ def _read_file_path_data(self, file: BinaryIO) -> bytes:
129139

130140
return path_data
131141

132-
def _get_block_count(self, file_metadata: List[tuple]) -> int:
142+
def _get_block_count(self, file_metadata: list[tuple[int, int, int, int]]) -> int:
133143
"""Calculate total number of blocks across all files"""
134144
count = 0
135145
for _, original_size, _, _ in file_metadata:
@@ -139,15 +149,15 @@ def _get_block_count(self, file_metadata: List[tuple]) -> int:
139149
count += blocks
140150
return count
141151

142-
def _read_block_sizes(self, file: BinaryIO, count: int) -> List[int]:
152+
def _read_block_sizes(self, file: BinaryIO, count: int) -> list[int]:
143153
"""Read block sizes for all files"""
144154
data = file.read(count * 2)
145155
if len(data) < count * 2:
146156
raise ValueError("Unexpected EOF reading block sizes")
147157

148158
return list(struct.unpack(f"<{count}H", data))
149159

150-
def unpack_file(self, file_path: str, out_path: str):
160+
def unpack_file(self, file_path: str, out_path: str | Path):
151161
"""Unpack a file from the archive"""
152162
if self._file_handle is None:
153163
raise ValueError("Archive file handle is not open")

0 commit comments

Comments
 (0)