kobo-highlights 1.0.2__py3-none-any.whl → 1.0.4__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.
kobo_highlights/config.py CHANGED
@@ -15,7 +15,7 @@ but a valid `Config` object can't be created.
15
15
  from __future__ import annotations
16
16
  from pathlib import Path
17
17
 
18
- from pydantic import BaseModel, Extra, ValidationError
18
+ from pydantic import BaseModel, ValidationError
19
19
  from rich.prompt import Prompt
20
20
  from rich.table import Table
21
21
  import toml
@@ -24,7 +24,7 @@ from kobo_highlights.console import console
24
24
 
25
25
 
26
26
  # Definitions
27
- class Config(BaseModel, extra=Extra.forbid):
27
+ class Config(BaseModel, extra="forbid"):
28
28
  """
29
29
  Config: Class that holds the configuration of the program. It is based on pydantic
30
30
  to ensure a correct structure and facilitate parsing. It used as a singleton in the
@@ -74,7 +74,7 @@ class Config(BaseModel, extra=Extra.forbid):
74
74
  Config: `Config` object representing the config file.
75
75
  """
76
76
  try:
77
- return cls.parse_obj(toml.load(config_path))
77
+ return cls.model_validate(toml.load(config_path))
78
78
 
79
79
  except FileNotFoundError:
80
80
  raise ConfigError(f"No config file was found in: {config_path}")
@@ -145,10 +145,11 @@ class Config(BaseModel, extra=Extra.forbid):
145
145
  """
146
146
  # Convert the path attributes to strings:
147
147
  toml_representation: dict[str, str] = {
148
- field: str(path) for field, path in self.dict().items()
148
+ field: str(path) for field, path in self.model_dump().items()
149
149
  }
150
150
 
151
- config_filepath.write_text(toml.dumps(toml_representation))
151
+ config_filepath.parent.mkdir(parents=True, exist_ok=True)
152
+ config_filepath.write_text(toml.dumps(toml_representation), encoding="utf-8")
152
153
  return self
153
154
 
154
155
  def __rich__(self) -> Table:
@@ -49,7 +49,6 @@ def setup_missing_config(config_path: Path) -> Config:
49
49
 
50
50
  error_console.print("[bold]No valid configuration file was found")
51
51
  if Confirm.ask("would you like to create one?"):
52
-
53
52
  try:
54
53
  config = Config.create_interactively().save_file(config_path)
55
54
  console.print(
@@ -122,7 +121,6 @@ def query_bookmarks_from_ereader(
122
121
  all_bookmarks: list[Bookmark] = []
123
122
 
124
123
  for bookmark_data in cursor_bookmark.execute(BM_QUERY):
125
-
126
124
  current_bookmark: dict = {
127
125
  "id": bookmark_data[0],
128
126
  "text": bookmark_data[1].strip(),
@@ -146,13 +144,15 @@ def query_bookmarks_from_ereader(
146
144
 
147
145
  # Query string used on the "content" table.
148
146
  CONTENT_QUERY: str = (
149
- f"SELECT Title, Attribution FROM content WHERE ContentID = '{volume_id}'"
147
+ "SELECT Title, Attribution FROM content WHERE ContentID = ?"
150
148
  " AND ContentType = '6' LIMIT 1;"
151
149
  )
152
150
 
153
151
  # The same book can appear multiple times on the "content" table, but in order
154
152
  # to retrieve the data there's no need to query more than one result.
155
- content_query_result: tuple = cursor_content.execute(CONTENT_QUERY).fetchone()
153
+ content_query_result: tuple = cursor_content.execute(
154
+ CONTENT_QUERY, (volume_id,)
155
+ ).fetchone()
156
156
 
157
157
  current_bookmark["title"] = content_query_result[0]
158
158
 
@@ -188,9 +188,8 @@ def query_bookmark_ids_from_json(json_filepath: Path) -> list[Bookmark_id]:
188
188
  list[Bookmark_id]: List of bookamrk IDs.
189
189
  """
190
190
  try:
191
-
192
191
  json_content: dict[str, list[Bookmark_id]] = json.loads(
193
- json_filepath.read_text()
192
+ json_filepath.read_text(encoding="utf-8")
194
193
  )
195
194
 
196
195
  # The JSON file should correspond to a dictionary with the key
@@ -202,9 +201,8 @@ def query_bookmark_ids_from_json(json_filepath: Path) -> list[Bookmark_id]:
202
201
 
203
202
  # If no JSON file exists, create one.
204
203
  except FileNotFoundError:
205
-
206
204
  json_content: dict[str, list[Bookmark_id]] = {"imported_bookmark_ids": []}
207
- json_filepath.write_text(json.dumps(json_content))
205
+ json_filepath.write_text(json.dumps(json_content), encoding="utf-8")
208
206
 
209
207
  # If there is a JSON file but the structure is wrong, the user will be asked if
210
208
  # they want to create a new one.
@@ -221,7 +219,7 @@ def query_bookmark_ids_from_json(json_filepath: Path) -> list[Bookmark_id]:
221
219
  console=error_console,
222
220
  ):
223
221
  json_content: dict[str, list[Bookmark_id]] = {"imported_bookmark_ids": []}
224
- json_filepath.write_text(json.dumps(json_content))
222
+ json_filepath.write_text(json.dumps(json_content), encoding="utf-8")
225
223
 
226
224
  else:
227
225
  raise typer.Abort()
@@ -242,7 +240,9 @@ def write_bookmark_id_to_json(json_filepath: Path, id: Bookmark_id):
242
240
  if id not in stored_ids:
243
241
  stored_ids.append(id)
244
242
 
245
- json_filepath.write_text(json.dumps({"imported_bookmark_ids": stored_ids}))
243
+ json_filepath.write_text(
244
+ json.dumps({"imported_bookmark_ids": stored_ids}), encoding="utf-8"
245
+ )
246
246
 
247
247
 
248
248
  def add_bookmark_to_md(bookmark: Bookmark, md_dir: Path):
@@ -283,8 +283,8 @@ def add_bookmark_to_md(bookmark: Bookmark, md_dir: Path):
283
283
  text_existing_file: str = f"\n\n***\n\n{md_blockquote}"
284
284
 
285
285
  if md_filepath.is_file():
286
- with md_filepath.open("a") as md_file:
286
+ with md_filepath.open("a", encoding="utf-8") as md_file:
287
287
  md_file.write(text_existing_file)
288
288
 
289
289
  else:
290
- md_filepath.write_text(text_new_file)
290
+ md_filepath.write_text(text_new_file, encoding="utf-8")
kobo_highlights/main.py CHANGED
@@ -1,6 +1,7 @@
1
1
  """This module contains the typer app (the CLI app) and the definitions for all the
2
2
  programs commands.
3
3
  """
4
+
4
5
  # Imports:
5
6
  from pathlib import Path
6
7
 
@@ -34,6 +35,7 @@ app = typer.Typer(
34
35
  config_app = typer.Typer(help="Manage the program configuration.")
35
36
  app.add_typer(config_app, name="config")
36
37
 
38
+
37
39
  # Initial setup:
38
40
  @app.callback()
39
41
  def setup():
@@ -142,8 +144,8 @@ def import_highlights(
142
144
  JSON_PATH
143
145
  )
144
146
 
145
- # Filter the bookmark to print to include only those that are in the ereader
146
- # but not on the markdown files.
147
+ # Filter the bookmarks to import only those that are in the ereader but
148
+ # not on the markdown files.
147
149
  bookmarks_to_save = [
148
150
  bm for bm in ereader_bookmarks if bm["id"] not in md_bookmarks_ids
149
151
  ]
@@ -157,13 +159,14 @@ def import_highlights(
157
159
  case "all":
158
160
  for bookmark in ereader_bookmarks:
159
161
  add_bookmark_to_md(bookmark, config.target_dir)
162
+ write_bookmark_id_to_json(JSON_PATH, bookmark["id"])
160
163
 
161
164
  console.print("[cyan]All Bookmarks have been imported")
162
165
 
163
166
  case _:
164
167
 
165
- # If the value is neither all nor new, the program checks in order if it is
166
- # a id, or a list of ids, a book title or a book author.
168
+ # If the value is neither all nor new, the program checks in order to see if
169
+ # it is an id, a list of ids, a book title, or a book author.
167
170
 
168
171
  all_ids, all_titles, all_authors = [], [], []
169
172
 
@@ -172,13 +175,14 @@ def import_highlights(
172
175
  all_titles.append(bookmark["title"])
173
176
  all_authors.append(bookmark["author"])
174
177
 
175
- # Check first if it is a list of ids:
178
+ # Check first if the input is composed of ids:
176
179
  selected_ids: list = bookmark_selection.split()
177
180
  if all(id in all_ids for id in selected_ids):
178
181
 
179
182
  for bookmark in ereader_bookmarks:
180
183
  if bookmark["id"] in selected_ids:
181
184
  add_bookmark_to_md(bookmark, config.target_dir)
185
+ write_bookmark_id_to_json(JSON_PATH, bookmark["id"])
182
186
 
183
187
  # To print to the console:
184
188
  id_list_to_print: str = "\n".join(selected_ids)
@@ -192,6 +196,7 @@ def import_highlights(
192
196
  for bookmark in ereader_bookmarks:
193
197
  if bookmark["title"] == bookmark_selection:
194
198
  add_bookmark_to_md(bookmark, config.target_dir)
199
+ write_bookmark_id_to_json(JSON_PATH, bookmark["id"])
195
200
  console.print(
196
201
  f"[green]All bookmarks from the book {bookmark_selection} have"
197
202
  " been imported"
@@ -202,6 +207,7 @@ def import_highlights(
202
207
  for bookmark in ereader_bookmarks:
203
208
  if bookmark["author"] == bookmark_selection:
204
209
  add_bookmark_to_md(bookmark, config.target_dir)
210
+ write_bookmark_id_to_json(JSON_PATH, bookmark["id"])
205
211
  console.print(
206
212
  f"[green]All bookmarks from the Author {bookmark_selection} have"
207
213
  " been imported"
@@ -1,20 +1,16 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: kobo-highlights
3
- Version: 1.0.2
3
+ Version: 1.0.4
4
4
  Summary: Kobo Highlights is a CLI application to manage the bookmarks of your Kobo ereader. It can import them into a human-friendly markdown database.
5
- Home-page: https://github.com/videbar/kobo-highlights
6
5
  License: GPL-3.0-only
7
6
  Author: Pedro Videgain Barranco
8
- Requires-Python: >=3.10,<4.0
7
+ Author-email: pedro@vide.bar
8
+ Requires-Python: ~=3.10
9
9
  Classifier: Environment :: Console
10
- Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
11
10
  Classifier: Operating System :: POSIX :: Linux
12
- Classifier: Programming Language :: Python :: 3
13
- Classifier: Programming Language :: Python :: 3.10
14
- Classifier: Programming Language :: Python :: 3.11
15
11
  Classifier: Topic :: Multimedia
16
- Requires-Dist: pydantic (>=1.9.0,<2.0.0)
17
- Requires-Dist: rich (>=12.2.0,<13.0.0)
12
+ Requires-Dist: pydantic (>=2.0,<3.0)
13
+ Requires-Dist: rich (>=12.4.0,<12.5.0)
18
14
  Requires-Dist: toml (>=0.10.2,<0.11.0)
19
15
  Requires-Dist: typer[all] (>=0.4.1,<0.5.0)
20
16
  Description-Content-Type: text/markdown
@@ -0,0 +1,10 @@
1
+ kobo_highlights/__init__.py,sha256=IMjkMO3twhQzluVTo8Z6rE7Eg-9U79_LGKMcsWLKBkY,22
2
+ kobo_highlights/config.py,sha256=uuzXRD-eK4Q_rc0mfHkmeGJqmO-lPx4FKxum2IqOWiM,6445
3
+ kobo_highlights/console.py,sha256=wwsT6W7sqANfMW91YAzA0EN2BJhNDxunG8ooZJ06Zys,228
4
+ kobo_highlights/functions.py,sha256=0gazUqPeMK3crUgr10dbkLblbNG77ug1LYa6ik0FnTI,11223
5
+ kobo_highlights/main.py,sha256=ngrEUjS6maiQVn3VaIiSrXiUEkUurAAK1OAfFra-zqo,8078
6
+ kobo_highlights-1.0.4.dist-info/LICENSE,sha256=5X8cMguM-HmKfS_4Om-eBqM6A1hfbgZf6pfx2G24QFI,35150
7
+ kobo_highlights-1.0.4.dist-info/METADATA,sha256=WMEiuK3aLF2X9IyfBKqwbi_05n8pwrNMHuYZ5nearPs,5765
8
+ kobo_highlights-1.0.4.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
9
+ kobo_highlights-1.0.4.dist-info/entry_points.txt,sha256=IDy9Bk-Jd6f-mcG6Dm7DJ9Ad-scSwGa2zcUqQbUDodY,47
10
+ kobo_highlights-1.0.4.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.3.2
2
+ Generator: poetry-core 2.1.3
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,10 +0,0 @@
1
- kobo_highlights/__init__.py,sha256=IMjkMO3twhQzluVTo8Z6rE7Eg-9U79_LGKMcsWLKBkY,22
2
- kobo_highlights/config.py,sha256=yOPeYcSovJEhFPSTT1wHVElwgVc8M2gKFdW5zC1f-kM,6361
3
- kobo_highlights/console.py,sha256=wwsT6W7sqANfMW91YAzA0EN2BJhNDxunG8ooZJ06Zys,228
4
- kobo_highlights/functions.py,sha256=8DY2eTEMKWQ84xyMjze0RrxUo7EYF2oV-OEDVT-OrL0,11084
5
- kobo_highlights/main.py,sha256=RLDz0XWI00lukcffHYgLvlLhpnklLsSP_VXBtQjYmUA,7770
6
- kobo_highlights-1.0.2.dist-info/entry_points.txt,sha256=IDy9Bk-Jd6f-mcG6Dm7DJ9Ad-scSwGa2zcUqQbUDodY,47
7
- kobo_highlights-1.0.2.dist-info/LICENSE,sha256=5X8cMguM-HmKfS_4Om-eBqM6A1hfbgZf6pfx2G24QFI,35150
8
- kobo_highlights-1.0.2.dist-info/WHEEL,sha256=vxFmldFsRN_Hx10GDvsdv1wroKq8r5Lzvjp6GZ4OO8c,88
9
- kobo_highlights-1.0.2.dist-info/METADATA,sha256=efb_Sn34blzn5X6AK2AWlfncv9Es0m_UAJgx4Qa7j1o,6026
10
- kobo_highlights-1.0.2.dist-info/RECORD,,