6
6
7
7
import datetime
8
8
import glob
9
- import json
10
9
import logging
11
10
import os
12
11
import sys
13
12
import time
14
13
import traceback
15
14
import xml .etree .ElementTree as ET
16
15
from enum import Enum
16
+ from pathlib import Path
17
+ from typing import cast , Generator
18
+
19
+ from typing_extensions import Self
20
+
17
21
import ujson
18
22
19
23
from src .core .json_typing import JsonCollation , JsonEntry , JsonLibary , JsonTag
@@ -42,7 +46,7 @@ def __init__(self, id: int, filename: str, path: str, fields: list[dict]) -> Non
42
46
self .id = int (id )
43
47
self .filename = filename
44
48
self .path = path
45
- self .fields = fields
49
+ self .fields : list [ dict ] = fields
46
50
self .type = None
47
51
48
52
# Optional Fields ======================================================
@@ -75,6 +79,7 @@ def __repr__(self) -> str:
75
79
return self .__str__ ()
76
80
77
81
def __eq__ (self , __value : object ) -> bool :
82
+ __value = cast (Self , object )
78
83
if os .name == "nt" :
79
84
return (
80
85
int (self .id ) == int (__value .id )
@@ -129,18 +134,16 @@ def remove_tag(self, library: "Library", tag_id: int, field_index=-1):
129
134
)
130
135
t .remove (tag_id )
131
136
elif field_index < 0 :
132
- t : list [ int ] = library .get_field_attr (f , "content" )
137
+ t = library .get_field_attr (f , "content" )
133
138
while tag_id in t :
134
139
t .remove (tag_id )
135
140
136
141
def add_tag (
137
- self , library : "Library" , tag_id : int , field_id : int , field_index : int = None
142
+ self , library : "Library" , tag_id : int , field_id : int , field_index : int = - 1
138
143
):
139
- # field_index: int = -1
140
144
# if self.fields:
141
145
# if field_index != -1:
142
146
# logging.info(f'[LIBRARY] ADD TAG to E:{self.id}, F-DI:{field_id}, F-INDEX:{field_index}')
143
- field_index = - 1 if field_index is None else field_index
144
147
for i , f in enumerate (self .fields ):
145
148
if library .get_field_attr (f , "id" ) == field_id :
146
149
field_index = i
@@ -183,7 +186,7 @@ def __init__(
183
186
self .shorthand = shorthand
184
187
self .aliases = aliases
185
188
# Ensures no duplicates while retaining order.
186
- self .subtag_ids = []
189
+ self .subtag_ids : list [ int ] = []
187
190
for s in subtags_ids :
188
191
if int (s ) not in self .subtag_ids :
189
192
self .subtag_ids .append (int (s ))
@@ -276,18 +279,19 @@ def __repr__(self) -> str:
276
279
return self .__str__ ()
277
280
278
281
def __eq__ (self , __value : object ) -> bool :
282
+ __value = cast (Self , __value )
279
283
if os .name == "nt" :
280
284
return (
281
- int (self .id ) == int (__value .id_ )
282
- and self .filename .lower () == __value .filename .lower ()
283
- and self .path .lower () == __value .path .lower ()
285
+ int (self .id ) == int (__value .id )
286
+ and self .filename .lower () == __value .filename .lower () # type: ignore
287
+ and self .path .lower () == __value .path .lower () # type: ignore
284
288
and self .fields == __value .fields
285
289
)
286
290
else :
287
291
return (
288
- int (self .id ) == int (__value .id_ )
289
- and self .filename == __value .filename
290
- and self .path == __value .path
292
+ int (self .id ) == int (__value .id )
293
+ and self .filename == __value .filename # type: ignore
294
+ and self .path == __value .path # type: ignore
291
295
and self .fields == __value .fields
292
296
)
293
297
@@ -342,7 +346,7 @@ def __init__(self) -> None:
342
346
self .files_not_in_library : list [str ] = []
343
347
self .missing_files : list [str ] = []
344
348
self .fixed_files : list [str ] = [] # TODO: Get rid of this.
345
- self .missing_matches = {}
349
+ self .missing_matches : dict = {}
346
350
# Duplicate Files
347
351
# Defined by files that are exact or similar copies to others. Generated by DupeGuru.
348
352
# (Filepath, Matched Filepath, Match Percentage)
@@ -393,7 +397,7 @@ def __init__(self) -> None:
393
397
# Tag(id=1, name='Favorite', shorthand='', aliases=['Favorited, Favorites, Likes, Liked, Loved'], subtags_ids=[], color='yellow'),
394
398
# ]
395
399
396
- self .default_fields = [
400
+ self .default_fields : list [ dict ] = [
397
401
{"id" : 0 , "name" : "Title" , "type" : "text_line" },
398
402
{"id" : 1 , "name" : "Author" , "type" : "text_line" },
399
403
{"id" : 2 , "name" : "Artist" , "type" : "text_line" },
@@ -512,8 +516,8 @@ def open_library(self, path: str) -> int:
512
516
),
513
517
"r" ,
514
518
encoding = "utf-8" ,
515
- ) as f :
516
- json_dump : JsonLibary = ujson .load (f )
519
+ ) as file :
520
+ json_dump : JsonLibary = ujson .load (file )
517
521
self .library_dir = str (path )
518
522
self .verify_ts_folders ()
519
523
major , minor , patch = json_dump ["ts-version" ].split ("." )
@@ -591,7 +595,7 @@ def open_library(self, path: str) -> int:
591
595
592
596
filename = entry .get ("filename" , "" )
593
597
e_path = entry .get ("path" , "" )
594
- fields = []
598
+ fields : list = []
595
599
if "fields" in entry :
596
600
# Cast JSON str keys to ints
597
601
for f in entry ["fields" ]:
@@ -688,14 +692,14 @@ def open_library(self, path: str) -> int:
688
692
self ._next_collation_id = id + 1
689
693
690
694
title = collation .get ("title" , "" )
691
- e_ids_and_pages = collation .get ("e_ids_and_pages" , "" )
692
- sort_order = collation .get ("sort_order" , [] )
693
- cover_id = collation .get ("cover_id" , [] )
695
+ e_ids_and_pages = collation .get ("e_ids_and_pages" , [] )
696
+ sort_order = collation .get ("sort_order" , "" )
697
+ cover_id = collation .get ("cover_id" , - 1 )
694
698
695
699
c = Collation (
696
700
id = id ,
697
701
title = title ,
698
- e_ids_and_pages = e_ids_and_pages ,
702
+ e_ids_and_pages = e_ids_and_pages , # type: ignore
699
703
sort_order = sort_order ,
700
704
cover_id = cover_id ,
701
705
)
@@ -861,33 +865,33 @@ def clear_internal_vars(self):
861
865
self .is_legacy_library = False
862
866
863
867
self .entries .clear ()
864
- self ._next_entry_id : int = 0
868
+ self ._next_entry_id = 0
865
869
# self.filtered_entries.clear()
866
870
self ._entry_id_to_index_map .clear ()
867
871
868
872
self ._collation_id_to_index_map .clear ()
869
873
870
874
self .missing_matches = {}
871
- self .dir_file_count : int = - 1
875
+ self .dir_file_count = - 1
872
876
self .files_not_in_library .clear ()
873
877
self .missing_files .clear ()
874
878
self .fixed_files .clear ()
875
- self .filename_to_entry_id_map : dict [ str , int ] = {}
879
+ self .filename_to_entry_id_map = {}
876
880
self .ignored_extensions = self .default_ext_blacklist
877
881
878
882
self .tags .clear ()
879
- self ._next_tag_id : int = 1000
880
- self ._tag_strings_to_id_map : dict [ str , list [ int ]] = {}
881
- self ._tag_id_to_cluster_map : dict [ int , list [ int ]] = {}
882
- self ._tag_id_to_index_map : dict [ int , int ] = {}
883
+ self ._next_tag_id = 1000
884
+ self ._tag_strings_to_id_map = {}
885
+ self ._tag_id_to_cluster_map = {}
886
+ self ._tag_id_to_index_map = {}
883
887
self ._tag_entry_ref_map .clear ()
884
888
885
- def refresh_dir (self ):
889
+ def refresh_dir (self ) -> Generator :
886
890
"""Scans a directory for files, and adds those relative filenames to internal variables."""
887
891
888
892
# Reset file interfacing variables.
889
893
# -1 means uninitialized, aka a scan like this was never attempted before.
890
- self .dir_file_count : int = 0
894
+ self .dir_file_count = 0
891
895
self .files_not_in_library .clear ()
892
896
893
897
# Scans the directory for files, keeping track of:
@@ -1210,7 +1214,8 @@ def fix_missing_files(self):
1210
1214
# (int, str)
1211
1215
1212
1216
self ._map_filenames_to_entry_ids ()
1213
- self .remove_missing_matches (fixed_indices )
1217
+ # TODO - the type here doesnt match but I cant reproduce calling this
1218
+ self .remove_missing_matches (fixed_indices ) # type: ignore
1214
1219
1215
1220
# for i in fixed_indices:
1216
1221
# # print(json_dump[i])
@@ -1330,10 +1335,11 @@ def get_collation(self, collation_id: int) -> Collation:
1330
1335
return self .collations [self ._collation_id_to_index_map [int (collation_id )]]
1331
1336
1332
1337
# @deprecated('Use new Entry ID system.')
1333
- def get_entry_from_index (self , index : int ) -> Entry :
1338
+ def get_entry_from_index (self , index : int ) -> Entry | None :
1334
1339
"""Returns a Library Entry object given its index in the unfiltered Entries list."""
1335
1340
if self .entries :
1336
1341
return self .entries [int (index )]
1342
+ return None
1337
1343
1338
1344
# @deprecated('Use new Entry ID system.')
1339
1345
def get_entry_id_from_filepath (self , filename ):
@@ -1368,7 +1374,7 @@ def search_library(
1368
1374
1369
1375
if query :
1370
1376
# start_time = time.time()
1371
- query : str = query .strip ().lower ()
1377
+ query = query .strip ().lower ()
1372
1378
query_words : list [str ] = query .split (" " )
1373
1379
all_tag_terms : list [str ] = []
1374
1380
only_untagged : bool = "untagged" in query or "no tags" in query
@@ -1548,7 +1554,7 @@ def search_library(
1548
1554
else :
1549
1555
for entry in self .entries :
1550
1556
added = False
1551
- allowed_ext : bool = (
1557
+ allowed_ext = (
1552
1558
os .path .splitext (entry .filename )[1 ][1 :].lower ()
1553
1559
not in self .ignored_extensions
1554
1560
)
@@ -1756,7 +1762,7 @@ def search_tags(
1756
1762
1757
1763
# if context and id_weights:
1758
1764
# time.sleep(3)
1759
- [final .append (idw [0 ]) for idw in id_weights if idw [0 ] not in final ]
1765
+ [final .append (idw [0 ]) for idw in id_weights if idw [0 ] not in final ] # type: ignore
1760
1766
# print(f'Final IDs: \"{[self.get_tag_from_id(id).display_name(self) for id in final]}\"')
1761
1767
# print('')
1762
1768
return final
@@ -1774,7 +1780,7 @@ def get_all_child_tag_ids(self, tag_id: int) -> list[int]:
1774
1780
1775
1781
return subtag_ids
1776
1782
1777
- def filter_field_templates (self : str , query ) -> list [int ]:
1783
+ def filter_field_templates (self , query : str ) -> list [int ]:
1778
1784
"""Returns a list of Field Template IDs returned from a string query."""
1779
1785
1780
1786
matches : list [int ] = []
@@ -2127,12 +2133,12 @@ def add_field_to_entry(self, entry_id: int, field_id: int) -> None:
2127
2133
def mirror_entry_fields (self , entry_ids : list [int ]) -> None :
2128
2134
"""Combines and mirrors all fields across a list of given Entry IDs."""
2129
2135
2130
- all_fields = []
2131
- all_ids = [] # Parallel to all_fields
2136
+ all_fields : list = []
2137
+ all_ids : list = [] # Parallel to all_fields
2132
2138
# Extract and merge all fields from all given Entries.
2133
2139
for id in entry_ids :
2134
2140
if id :
2135
- entry : Entry = self .get_entry (id )
2141
+ entry = self .get_entry (id )
2136
2142
if entry and entry .fields :
2137
2143
for field in entry .fields :
2138
2144
# First checks if their are matching tag_boxes to append to
@@ -2153,7 +2159,7 @@ def mirror_entry_fields(self, entry_ids: list[int]) -> None:
2153
2159
2154
2160
# Replace each Entry's fields with the new merged ones.
2155
2161
for id in entry_ids :
2156
- entry : Entry = self .get_entry (id )
2162
+ entry = self .get_entry (id )
2157
2163
if entry :
2158
2164
entry .fields = all_fields
2159
2165
@@ -2181,7 +2187,7 @@ def mirror_entry_fields(self, entry_ids: list[int]) -> None:
2181
2187
# pass
2182
2188
# # TODO: Implement.
2183
2189
2184
- def get_field_attr (self , entry_field , attribute : str ):
2190
+ def get_field_attr (self , entry_field : dict , attribute : str ):
2185
2191
"""Returns the value of a specified attribute inside an Entry field."""
2186
2192
if attribute .lower () == "id" :
2187
2193
return list (entry_field .keys ())[0 ]
@@ -2236,7 +2242,7 @@ def _map_tag_strings_to_tag_id(self, tag: Tag) -> None:
2236
2242
self ._tag_strings_to_id_map [shorthand ].append (tag .id )
2237
2243
2238
2244
for alias in tag .aliases :
2239
- alias : str = strip_punctuation (alias ).lower ()
2245
+ alias = strip_punctuation (alias ).lower ()
2240
2246
if alias not in self ._tag_strings_to_id_map :
2241
2247
self ._tag_strings_to_id_map [alias ] = []
2242
2248
self ._tag_strings_to_id_map [alias ].append (tag .id )
0 commit comments