absfuyu 3.1.1__py3-none-any.whl → 3.3.3__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.
Potentially problematic release.
This version of absfuyu might be problematic. Click here for more details.
- absfuyu/__init__.py +3 -10
- absfuyu/__main__.py +5 -250
- absfuyu/cli/__init__.py +51 -0
- absfuyu/cli/color.py +24 -0
- absfuyu/cli/config_group.py +56 -0
- absfuyu/cli/do_group.py +76 -0
- absfuyu/cli/game_group.py +109 -0
- absfuyu/config/__init__.py +117 -100
- absfuyu/config/config.json +0 -7
- absfuyu/core.py +5 -66
- absfuyu/everything.py +7 -9
- absfuyu/extensions/beautiful.py +30 -23
- absfuyu/extensions/dev/__init__.py +11 -8
- absfuyu/extensions/dev/password_hash.py +4 -2
- absfuyu/extensions/dev/passwordlib.py +7 -5
- absfuyu/extensions/dev/project_starter.py +4 -2
- absfuyu/extensions/dev/shutdownizer.py +148 -0
- absfuyu/extensions/extra/__init__.py +1 -2
- absfuyu/extensions/extra/data_analysis.py +182 -107
- absfuyu/fun/WGS.py +50 -26
- absfuyu/fun/__init__.py +6 -7
- absfuyu/fun/tarot.py +1 -1
- absfuyu/game/__init__.py +75 -81
- absfuyu/game/game_stat.py +36 -0
- absfuyu/game/sudoku.py +41 -48
- absfuyu/game/tictactoe.py +303 -548
- absfuyu/game/wordle.py +56 -47
- absfuyu/general/__init__.py +17 -7
- absfuyu/general/content.py +16 -15
- absfuyu/general/data_extension.py +282 -90
- absfuyu/general/generator.py +67 -67
- absfuyu/general/human.py +74 -78
- absfuyu/logger.py +94 -68
- absfuyu/pkg_data/__init__.py +29 -25
- absfuyu/py.typed +0 -0
- absfuyu/sort.py +61 -47
- absfuyu/tools/__init__.py +0 -1
- absfuyu/tools/converter.py +80 -62
- absfuyu/tools/keygen.py +62 -67
- absfuyu/tools/obfuscator.py +57 -53
- absfuyu/tools/stats.py +24 -24
- absfuyu/tools/web.py +10 -9
- absfuyu/util/__init__.py +71 -33
- absfuyu/util/api.py +53 -43
- absfuyu/util/json_method.py +25 -27
- absfuyu/util/lunar.py +20 -24
- absfuyu/util/path.py +362 -241
- absfuyu/util/performance.py +217 -135
- absfuyu/util/pkl.py +8 -8
- absfuyu/util/zipped.py +17 -19
- absfuyu/version.py +160 -147
- absfuyu-3.3.3.dist-info/METADATA +124 -0
- absfuyu-3.3.3.dist-info/RECORD +59 -0
- {absfuyu-3.1.1.dist-info → absfuyu-3.3.3.dist-info}/WHEEL +1 -2
- {absfuyu-3.1.1.dist-info → absfuyu-3.3.3.dist-info}/entry_points.txt +1 -0
- {absfuyu-3.1.1.dist-info → absfuyu-3.3.3.dist-info/licenses}/LICENSE +1 -1
- absfuyu/extensions/dev/pkglib.py +0 -98
- absfuyu/game/tictactoe2.py +0 -318
- absfuyu-3.1.1.dist-info/METADATA +0 -215
- absfuyu-3.1.1.dist-info/RECORD +0 -55
- absfuyu-3.1.1.dist-info/top_level.txt +0 -1
absfuyu/game/wordle.py
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
Game: Wordle Solver
|
|
3
3
|
-------------------
|
|
4
4
|
|
|
5
|
-
Version: 1.1.
|
|
6
|
-
Date updated:
|
|
5
|
+
Version: 1.1.4
|
|
6
|
+
Date updated: 14/04/2024 (dd/mm/yyyy)
|
|
7
7
|
|
|
8
8
|
Usage:
|
|
9
9
|
------
|
|
10
|
-
>>> Wordle.solve()
|
|
10
|
+
>>> Wordle().solve()
|
|
11
11
|
|
|
12
12
|
Credit:
|
|
13
13
|
-------
|
|
@@ -15,21 +15,16 @@ Credit:
|
|
|
15
15
|
- [Words](https://raw.githubusercontent.com/dwyl/english-words/master/words_dictionary.json)
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
|
+
__all__ = ["Wordle"]
|
|
18
19
|
|
|
19
|
-
# Library
|
|
20
|
-
###########################################################################
|
|
21
|
-
from collections import Counter
|
|
22
|
-
from itertools import chain
|
|
23
20
|
import operator
|
|
24
21
|
import string
|
|
22
|
+
from collections import Counter
|
|
23
|
+
from itertools import chain
|
|
24
|
+
from typing import List, Set, Tuple
|
|
25
25
|
|
|
26
26
|
import requests
|
|
27
27
|
|
|
28
|
-
from absfuyu.logger import logger
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
# Settings
|
|
32
|
-
###########################################################################
|
|
33
28
|
OFFLINE_WORDS = """\
|
|
34
29
|
aahed,aalii,aargh,aaron,abaca,abaci,aback,abada,abaff,abaft,abaka,abama,abamp,aband,abase,abash,abask,abate,abaue,abave,abaze,abbas,abbes,abbey,abbie,abbot,abdal,abdat,abdom,abeam,abear,abede,abele,abend,aberr,abets,abhor,abide,abidi,abies,abilo,abime,abkar,abler,ables,ablet,ablow,abmho,abner,abnet,abode,abody,abohm,aboil,aboma,aboon,abord,abort,abote,about,above,abram,abray,abret,abrim,abrin,abris,abrus,absee,absey,absis,absit,abstr,abuna,abune,abura,abuse,abush,abuta,abuts,abuzz,abwab,abyes,abysm,abyss,acale,acana,acapu,acara,acari,acast,acate,accel,accoy,accra,accts,accum,accur,accus,acedy,acerb,aceta,achar,ached,achen,acher,aches,achoo,achor,acids,acidy,acier,acies,acing,acini,ackee,acker,ackey,aclys,acmes,acmic,acned,acnes,acock,acoin,acold,acoma,acone,acool,acorn,acost,acoup,acrab,acred,acres,acrid,acroa,acron,acrux,acryl,acted,actin,acton,actor,actos,actus,acuan,acute,acyls,adage,adagy,adams,adapa,adapt,adati,adaty,adawe,adawn,adays,adcon,addax,addda,added,adder,addie,addio,addis,addle,addnl,adead,adeem,adeep,adela,adeps,adept,adfix,adiel,adieu,adion,adios,adits,adjag,adlai,adlay,adlet,adman,admen,admin,admit,admix,admov,admrx,adnex,adobe,adobo,adolf,adopt,adore,adorn,adown,adoxa,adoxy,adoze,adpao,adrad,adret,adrip,adrop,adrue,adsum,adult,adunc,adure,adusk,adust,adyta,adzer,adzes,aecia,aedes,aeger,aegir,aegis,aegle,aeons,aequi,aeric,aerie,aeron,aesir,aesop,aetat,aevia,aevum,aface,afara,afars,afear,affix,afgod,afifi,afire,aflat,afley,aflow,afoam,afoot,afore,afoul,afray,afret,afric,afrit,afros,after,agada,agade,again,agama,agami,agamy,agape,agars,agasp,agast,agata,agate,agaty,agave,agaze,agena,agend,agene,agent,agers,agete,agger,aggie,aggro,aggry,aggur,aghan,aghas,agiel,agile,aging,agios,agism,agist,aglee,aglet,agley,aglow,agmas,agnat,agnel,agnes,agnus,agoge,agoho,agone,agons,agony,agora,agrah,agral,agree,agria,agric,agrin,agrom,agron,agsam,agues,aguey,agura,agush,agust,ahead,aheap,ahems,ahind,ahint,ahmed,ahmet,ahold,aholt,ahong,ahsan,ahull,ahunt,ahura,ahush,ahwal,aided,aider,aides,aiery,aiger,aigre,ailed,ailie,aillt,aimak,aimed,aimee,aimer,ainee,ainoi,ainus,aioli,airan,aired,airer,airns,airth,airts,aisle,aitch,aitis,aiver,aiwan,aizle,ajaja,ajari,ajava,ajhar,ajiva,ajuga,akala,akali,akasa,akebi,akees,akeki,akela,akene,aking,akkad,aknee,aknow,akpek,akron,akule,akund,alack,alada,alain,alaki,alala,alamo,aland,alane,alang,alani,alans,alant,alapa,alarm,alary,alate,alawi,alban,albas,albee,albin,album,albus,albyn,alcae,alces,alcid,alcor,alday,aldea,alden,alder,aldim,aldol,aldus,aleak,
|
|
35
30
|
aleck,alecs,alefs,aleft,alenu,aleph,alert,aleut,alfas,alfet,alfin,alfur,algae,algal,algas,algic,algid,algin,algol,algor,algum,alhet,alias,alibi,alice,alick,alida,alids,alien,aliet,alife,alifs,align,alike,alima,aline,alish,aliso,alisp,alist,alite,ality,alive,aliya,alkes,alkin,alkyd,alkyl,allah,allan,allay,allen,aller,alley,allez,allie,allis,allod,alloo,allot,allow,alloy,allyl,almah,alman,almas,almeh,almes,almon,almud,almug,alnus,alody,aloed,aloes,aloft,alogy,aloha,aloid,aloin,alois,aloma,alone,along,aloof,alosa,alose,aloud,alout,alowe,alpax,alpen,alpha,alpid,altar,alter,altho,altin,altos,altun,altus,aluco,alula,alums,alure,aluta,alvah,alvan,alvar,alvia,alvin,alvus,alway,amaas,amadi,amaga,amahs,amain,amala,amalg,amang,amani,amant,amapa,amara,amass,amate,amati,amaut,amaze,amban,ambar,ambas,ambay,amber,ambit,amble,ambon,ambos,ambry,ameba,ameed,ameen,ameer,amelu,amend,amene,amens,ament,amess,amhar,amias,amice,amici,amide,amido,amids,amies,amiga,amigo,amine,amini,amino,amins,amire,amirs,amish,amiss,amita,amity,amlet,amman,ammer,ammos,amnia,amnic,amoke,amoks,amole,among,amora,amort,amour,amove,amowt,amper,amphi,ample,amply,ampul,ampyx,amrit,amsel,amuck,amula,amuse,amuze,amvis,amylo,amyls,amzel,anabo,anack,anama,anana,anasa,ancha,ancle,ancon,ancor,ancre,andes,andia,andor,andre,anear,anele,anend,anent,angas,angel,anger,angia,angie,angka,angle,anglo,angor,angry,angst,angus,anhyd,aniba,anice,anigh,anile,anils,anima,anime,animi,animo,anion,anise,anita,anjan,anjou,ankee,anker,ankhs,ankle,ankou,ankus,anlas,anlet,anlia,anmia,annal,annam,annas,annat,annet,annex,annie,anniv,annot,annoy,annul,annum,annus,anoas,anode,anoia,anoil,anole,anoli,anomy,anorn,anour,anous,anova,ansae,ansar,ansel,anser,antae,antal,antar,antas,anted,antes,antic,antiq,antis,anton,antra,antre,antsy,antum,anura,anury,anvil,anzac,aoife,aorta,aotea,aotes,aotus,aouad,apace,apaid,apair,apama,apart,apass,apast,apeak,apeek,apers,apert,aperu,apery,aphid,aphis,aphra,apian,apiin,apili,apina,aping,apiol,apios,apish,apism,apium,apnea,apoda,apods,apoop,aport,apout,appal,appar,appay,appel,appet,apple,apply,appmt,appro,apptd,appui,apres,april,apron,apses,apsid,apsis,aptal,apter,aptly,aquae,aquas,araba,arabs,araby,araca,arace,arach,arado,arage,arain,arake,araks,aramu,arank,arara,araru,arase,arati,araua,arawa,arber,arbor,arcae,arced,arces,archd,arche,archt,archy,arcos,arcus,ardea,ardeb,arder,ardor,ardri,aread,areae,areal,arean,arear,areas,areca,areek,areel,arefy,areic,arena,arend,areng,arent,arere,arest,arete,argal,argan,argas,argel,argid,argil,
|
|
@@ -84,27 +79,20 @@ zabra,zabti,zaire,zakah,zakat,zaman,zambo,zamia,zande,zante,zanza,zanze,zapas,za
|
|
|
84
79
|
"""
|
|
85
80
|
|
|
86
81
|
|
|
87
|
-
# Class
|
|
88
|
-
###########################################################################
|
|
89
82
|
class Wordle:
|
|
90
83
|
"""
|
|
91
84
|
Wordle class
|
|
92
85
|
|
|
93
86
|
Use: ``Wordle.solve()``
|
|
94
87
|
"""
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
*,
|
|
98
|
-
green: str = "G",
|
|
99
|
-
yellow: str = "Y",
|
|
100
|
-
gray: str = "?"
|
|
101
|
-
) -> None:
|
|
88
|
+
|
|
89
|
+
def __init__(self, *, green: str = "G", yellow: str = "Y", gray: str = "?") -> None:
|
|
102
90
|
# Setting
|
|
103
91
|
self._ALLOWABLE_CHARACTERS = set(string.ascii_letters)
|
|
104
92
|
self._ALLOWED_ATTEMPTS = 6
|
|
105
93
|
self._WORD_LENGTH = 5
|
|
106
94
|
|
|
107
|
-
self._WORDS = set(OFFLINE_WORDS.replace("\n", "").split(","))
|
|
95
|
+
self._WORDS: List[str] = list(set(OFFLINE_WORDS.replace("\n", "").split(",")))
|
|
108
96
|
|
|
109
97
|
self._LETTER_COUNTER = Counter(chain.from_iterable(self._WORDS))
|
|
110
98
|
|
|
@@ -117,11 +105,13 @@ class Wordle:
|
|
|
117
105
|
self._GREEN = green
|
|
118
106
|
self._YELLOW = yellow
|
|
119
107
|
self._GRAY = gray
|
|
108
|
+
|
|
120
109
|
def __str__(self) -> str:
|
|
121
|
-
|
|
110
|
+
return self.__repr__()
|
|
111
|
+
|
|
122
112
|
def __repr__(self) -> str:
|
|
123
|
-
return self.
|
|
124
|
-
|
|
113
|
+
return self.__class__.__name__
|
|
114
|
+
|
|
125
115
|
def update_words(self) -> None:
|
|
126
116
|
"""
|
|
127
117
|
Try to fetch words list from online source
|
|
@@ -129,74 +119,94 @@ class Wordle:
|
|
|
129
119
|
try:
|
|
130
120
|
dict_link = "https://raw.githubusercontent.com/dwyl/english-words/master/words_dictionary.json"
|
|
131
121
|
res = requests.get(dict_link)
|
|
132
|
-
word_list = list(res.json().keys())
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
122
|
+
word_list: list[str] = list(res.json().keys())
|
|
123
|
+
self._WORDS = list(
|
|
124
|
+
{
|
|
125
|
+
word.lower()
|
|
126
|
+
for word in word_list
|
|
127
|
+
if len(word) == self._WORD_LENGTH
|
|
128
|
+
and set(word) < self._ALLOWABLE_CHARACTERS
|
|
129
|
+
}
|
|
130
|
+
)
|
|
131
|
+
except Exception:
|
|
140
132
|
pass
|
|
141
133
|
|
|
142
134
|
# Logic
|
|
143
|
-
def _calculate_word_commonality(self, word):
|
|
135
|
+
def _calculate_word_commonality(self, word: str) -> float:
|
|
144
136
|
score = 0.0
|
|
145
137
|
for char in word:
|
|
146
138
|
score += self._LETTER_FREQUENCY[char]
|
|
147
139
|
return score / (self._WORD_LENGTH - len(set(word)) + 1)
|
|
148
140
|
|
|
149
|
-
def _sort_by_word_commonality(self):
|
|
141
|
+
def _sort_by_word_commonality(self) -> List[Tuple[str, float]]:
|
|
150
142
|
sort_by = operator.itemgetter(1)
|
|
151
143
|
return sorted(
|
|
152
144
|
[(word, self._calculate_word_commonality(word)) for word in self._WORDS],
|
|
153
145
|
key=sort_by,
|
|
154
146
|
reverse=True,
|
|
155
147
|
)
|
|
156
|
-
|
|
157
|
-
def _display_word_table(self, word_commonalities):
|
|
158
|
-
for
|
|
148
|
+
|
|
149
|
+
def _display_word_table(self, word_commonalities: List[Tuple[str, float]]) -> None:
|
|
150
|
+
for word, freq in word_commonalities:
|
|
159
151
|
print(f"{word:<10} | {freq:<5.2}")
|
|
160
152
|
|
|
161
|
-
def _input_word(self):
|
|
153
|
+
def _input_word(self) -> str:
|
|
162
154
|
while True:
|
|
163
155
|
word = input("Input the word you entered> ")
|
|
164
156
|
if len(word) == self._WORD_LENGTH and word.lower() in self._WORDS:
|
|
165
157
|
break
|
|
166
158
|
return word.lower()
|
|
167
|
-
|
|
168
|
-
def _input_response(self):
|
|
159
|
+
|
|
160
|
+
def _input_response(self) -> str:
|
|
169
161
|
print("Type the color-coded reply from Wordle:")
|
|
170
162
|
print(f" {self._GREEN} for Green")
|
|
171
163
|
print(f" {self._YELLOW} for Yellow")
|
|
172
164
|
print(f" {self._GRAY} for Gray")
|
|
173
165
|
while True:
|
|
174
166
|
response = input("Response from Wordle> ")
|
|
175
|
-
if len(response) == self._WORD_LENGTH and set(response) <= {
|
|
167
|
+
if len(response) == self._WORD_LENGTH and set(response) <= {
|
|
168
|
+
self._GREEN,
|
|
169
|
+
self._YELLOW,
|
|
170
|
+
self._GRAY,
|
|
171
|
+
}:
|
|
176
172
|
break
|
|
177
173
|
else:
|
|
178
174
|
print(f"Error - invalid answer {response}")
|
|
175
|
+
if response == self._GREEN * 5: # Win
|
|
176
|
+
return "win"
|
|
179
177
|
return response
|
|
180
178
|
|
|
181
|
-
def _match_word_vector(self, word, word_vector):
|
|
179
|
+
def _match_word_vector(self, word: str, word_vector: List[Set[str]]) -> bool:
|
|
182
180
|
assert len(word) == len(word_vector)
|
|
183
181
|
for letter, v_letter in zip(word, word_vector):
|
|
184
182
|
if letter not in v_letter:
|
|
185
183
|
return False
|
|
186
184
|
return True
|
|
187
185
|
|
|
188
|
-
def _match(
|
|
189
|
-
|
|
190
|
-
|
|
186
|
+
def _match(
|
|
187
|
+
self, word_vector: List[Set[str]], possible_words: List[str]
|
|
188
|
+
) -> List[str]:
|
|
189
|
+
return [
|
|
190
|
+
word
|
|
191
|
+
for word in possible_words
|
|
192
|
+
if self._match_word_vector(word, word_vector)
|
|
193
|
+
]
|
|
194
|
+
|
|
191
195
|
# Main
|
|
192
196
|
def solve(self) -> None:
|
|
193
197
|
"""Solve Wordle"""
|
|
194
198
|
word_vector = [set(string.ascii_lowercase) for _ in range(self._WORD_LENGTH)]
|
|
199
|
+
|
|
195
200
|
for attempt in range(1, self._ALLOWED_ATTEMPTS + 1):
|
|
196
201
|
print(f"Attempt {attempt} with {len(self._WORDS)} possible words")
|
|
197
202
|
self._display_word_table(self._sort_by_word_commonality()[:15])
|
|
198
203
|
word = self._input_word()
|
|
204
|
+
|
|
199
205
|
response = self._input_response()
|
|
206
|
+
if response == "win":
|
|
207
|
+
print("You Won!")
|
|
208
|
+
break
|
|
209
|
+
|
|
200
210
|
for idx, letter in enumerate(response):
|
|
201
211
|
if letter == self._GREEN:
|
|
202
212
|
word_vector[idx] = {word[idx]}
|
|
@@ -217,6 +227,5 @@ class Wordle:
|
|
|
217
227
|
# Run
|
|
218
228
|
###########################################################################
|
|
219
229
|
if __name__ == "__main__":
|
|
220
|
-
logger.setLevel(10) # DEBUG
|
|
221
230
|
test = Wordle()
|
|
222
231
|
test.solve()
|
absfuyu/general/__init__.py
CHANGED
|
@@ -3,8 +3,8 @@ Absfuyu: General
|
|
|
3
3
|
----------------
|
|
4
4
|
Collection of useful classes
|
|
5
5
|
|
|
6
|
-
Version: 1.1.
|
|
7
|
-
Date updated:
|
|
6
|
+
Version: 1.1.4
|
|
7
|
+
Date updated: 15/03/2024 (dd/mm/yyyy)
|
|
8
8
|
|
|
9
9
|
Features:
|
|
10
10
|
---------
|
|
@@ -16,6 +16,8 @@ Features:
|
|
|
16
16
|
|
|
17
17
|
# Libary
|
|
18
18
|
###########################################################################
|
|
19
|
+
from typing import Any, Dict, Optional
|
|
20
|
+
|
|
19
21
|
from absfuyu.general import content, data_extension, generator, human
|
|
20
22
|
|
|
21
23
|
|
|
@@ -28,10 +30,10 @@ class Dummy:
|
|
|
28
30
|
Update attribute through dict
|
|
29
31
|
"""
|
|
30
32
|
|
|
31
|
-
def __init__(self, data:
|
|
33
|
+
def __init__(self, data: Optional[Dict[Any, Any]] = None) -> None:
|
|
32
34
|
try:
|
|
33
|
-
self.__dict__.update(data)
|
|
34
|
-
except:
|
|
35
|
+
self.__dict__.update(data) # type: ignore
|
|
36
|
+
except Exception:
|
|
35
37
|
pass
|
|
36
38
|
|
|
37
39
|
def __str__(self) -> str:
|
|
@@ -45,7 +47,7 @@ class Dummy:
|
|
|
45
47
|
"""List ``property``"""
|
|
46
48
|
return [x for x in self.__dir__() if not x.startswith("_")]
|
|
47
49
|
|
|
48
|
-
def update(self, data:
|
|
50
|
+
def update(self, data: Dict[Any, Any]) -> None:
|
|
49
51
|
"""
|
|
50
52
|
Update with dict data
|
|
51
53
|
|
|
@@ -76,9 +78,17 @@ class ClassBase:
|
|
|
76
78
|
"""
|
|
77
79
|
keys = self.__dict__.keys()
|
|
78
80
|
temp = filter(lambda x: not x.startswith("_"), keys)
|
|
79
|
-
out = [f"{x}={self.__dict__[x]}" for x in temp]
|
|
81
|
+
# out = [f"{x}={self.__dict__[x]}" for x in temp]
|
|
82
|
+
out = [f"{x}={self.__dict__.get(x)}" for x in temp]
|
|
80
83
|
return sep.join(out)
|
|
81
84
|
|
|
85
|
+
# def _get_new_available_method(self) -> List[str]:
|
|
86
|
+
# """
|
|
87
|
+
# Return all new available methods in this particular class
|
|
88
|
+
# """
|
|
89
|
+
# available = set(dir(self.__class__)).difference(set(dir(self.__class__.__base__)))
|
|
90
|
+
# return sorted(list(available))
|
|
91
|
+
|
|
82
92
|
|
|
83
93
|
# Run
|
|
84
94
|
###########################################################################
|
absfuyu/general/content.py
CHANGED
|
@@ -3,15 +3,14 @@ Absfuyu: Content
|
|
|
3
3
|
----------------
|
|
4
4
|
Handle .txt file
|
|
5
5
|
|
|
6
|
-
Version: 1.2.
|
|
7
|
-
Date updated:
|
|
6
|
+
Version: 1.2.6
|
|
7
|
+
Date updated: 05/04/2024 (dd/mm/yyyy)
|
|
8
8
|
|
|
9
9
|
Usage:
|
|
10
10
|
------
|
|
11
11
|
>>> from absfuyu.general.content import ContentLoader
|
|
12
12
|
"""
|
|
13
13
|
|
|
14
|
-
|
|
15
14
|
# Module level
|
|
16
15
|
###########################################################################
|
|
17
16
|
__all__ = ["ContentLoader", "Content", "LoadedContent"]
|
|
@@ -19,12 +18,12 @@ __all__ = ["ContentLoader", "Content", "LoadedContent"]
|
|
|
19
18
|
|
|
20
19
|
# Library
|
|
21
20
|
###########################################################################
|
|
22
|
-
from collections import Counter
|
|
23
|
-
from itertools import chain
|
|
24
21
|
import json
|
|
25
|
-
from pathlib import Path
|
|
26
22
|
import random
|
|
27
23
|
import re
|
|
24
|
+
from collections import Counter
|
|
25
|
+
from itertools import chain
|
|
26
|
+
from pathlib import Path
|
|
28
27
|
from typing import List, Optional
|
|
29
28
|
|
|
30
29
|
from unidecode import unidecode
|
|
@@ -63,7 +62,7 @@ class Content:
|
|
|
63
62
|
Content
|
|
64
63
|
``unidecoded`` Content
|
|
65
64
|
"""
|
|
66
|
-
return __class__([unidecode(self.data), list(map(unidecode, self.tag))])
|
|
65
|
+
return self.__class__([unidecode(self.data), list(map(unidecode, self.tag))])
|
|
67
66
|
|
|
68
67
|
def to_text(self) -> str:
|
|
69
68
|
"""
|
|
@@ -140,7 +139,7 @@ class Content:
|
|
|
140
139
|
self.tag = list(set(self.tag + new_tag))
|
|
141
140
|
logger.debug(f"Final tags: {self.tag} Len: {len(self.tag)}")
|
|
142
141
|
|
|
143
|
-
return __class__([self.data, self.tag])
|
|
142
|
+
return self.__class__([self.data, self.tag])
|
|
144
143
|
|
|
145
144
|
|
|
146
145
|
class LoadedContent(List[Content]):
|
|
@@ -163,7 +162,7 @@ class LoadedContent(List[Content]):
|
|
|
163
162
|
:type func: Callable
|
|
164
163
|
:rtype: LoadedContent
|
|
165
164
|
"""
|
|
166
|
-
return __class__(func(x.data) for x in self)
|
|
165
|
+
return self.__class__(func(x.data) for x in self)
|
|
167
166
|
|
|
168
167
|
@classmethod
|
|
169
168
|
def load_from_json(cls, file: Path) -> "LoadedContent":
|
|
@@ -222,7 +221,7 @@ class LoadedContent(List[Content]):
|
|
|
222
221
|
f"Available tags: {_avail_tag},..."
|
|
223
222
|
f"\nMore tag at: `{self.__class__.__name__}.tags`"
|
|
224
223
|
)
|
|
225
|
-
return __class__([x for x in self if tag in x.tag])
|
|
224
|
+
return self.__class__([x for x in self if tag in x.tag])
|
|
226
225
|
|
|
227
226
|
def find(self, keyword: str) -> "LoadedContent":
|
|
228
227
|
"""
|
|
@@ -232,7 +231,9 @@ class LoadedContent(List[Content]):
|
|
|
232
231
|
:type keyword: str
|
|
233
232
|
:rtype: LoadedContent
|
|
234
233
|
"""
|
|
235
|
-
temp =
|
|
234
|
+
temp = self.__class__(
|
|
235
|
+
[x for x in self if x.data.lower().find(keyword.lower()) >= 0]
|
|
236
|
+
)
|
|
236
237
|
if temp:
|
|
237
238
|
logger.debug(f"Found {len(temp)} {'entries' if len(temp) > 1 else 'entry'}")
|
|
238
239
|
else:
|
|
@@ -306,7 +307,7 @@ class LoadedContent(List[Content]):
|
|
|
306
307
|
>>> # After handle_address(first_item_not_address = False)
|
|
307
308
|
["22 ABC Street", "DEF District", "GHI City"]
|
|
308
309
|
"""
|
|
309
|
-
return __class__(
|
|
310
|
+
return self.__class__(
|
|
310
311
|
[
|
|
311
312
|
x.handle_address(
|
|
312
313
|
address_separator=address_separator,
|
|
@@ -373,7 +374,7 @@ class ContentLoader:
|
|
|
373
374
|
self,
|
|
374
375
|
file_path: Path,
|
|
375
376
|
characteristic_detect: bool = True,
|
|
376
|
-
tag_dictionary: dict = None,
|
|
377
|
+
tag_dictionary: Optional[dict] = None,
|
|
377
378
|
*,
|
|
378
379
|
comment_symbol: str = "#",
|
|
379
380
|
split_symbol: str = "|",
|
|
@@ -423,7 +424,7 @@ class ContentLoader:
|
|
|
423
424
|
f"({len(set(tag_dictionary.values()))} unique "
|
|
424
425
|
f"{'tags' if len(set(tag_dictionary.values())) > 1 else 'tag'})"
|
|
425
426
|
)
|
|
426
|
-
self.tag_dictionary
|
|
427
|
+
self.tag_dictionary = tag_dictionary
|
|
427
428
|
|
|
428
429
|
# symbol stuff
|
|
429
430
|
assert (
|
|
@@ -528,7 +529,7 @@ class ContentLoader:
|
|
|
528
529
|
tag.strip() for tag in temp[1].strip().lower().split(",")
|
|
529
530
|
] # separate and strip tags
|
|
530
531
|
logger.debug(f"Tags: {tags}")
|
|
531
|
-
except:
|
|
532
|
+
except Exception:
|
|
532
533
|
logger.warning("No tag found in the original string")
|
|
533
534
|
if additional_tags:
|
|
534
535
|
tags = additional_tags
|