showtime-cli 0.3.19__tar.gz → 0.3.22__tar.gz
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.
- {showtime-cli-0.3.19/showtime_cli.egg-info → showtime_cli-0.3.22}/PKG-INFO +19 -7
- {showtime-cli-0.3.19 → showtime_cli-0.3.22}/pyproject.toml +23 -20
- showtime_cli-0.3.22/requirements.txt +7 -0
- {showtime-cli-0.3.19 → showtime_cli-0.3.22}/setup.py +5 -5
- {showtime-cli-0.3.19 → showtime_cli-0.3.22}/showtime/__init__.py +1 -1
- {showtime-cli-0.3.19 → showtime_cli-0.3.22}/showtime/api.py +2 -1
- {showtime-cli-0.3.19 → showtime_cli-0.3.22}/showtime/command.py +19 -1
- {showtime-cli-0.3.19 → showtime_cli-0.3.22}/showtime/database.py +21 -3
- {showtime-cli-0.3.19 → showtime_cli-0.3.22}/showtime/output.py +24 -1
- {showtime-cli-0.3.19 → showtime_cli-0.3.22}/showtime/showtime.py +9 -3
- {showtime-cli-0.3.19 → showtime_cli-0.3.22}/showtime/types.py +9 -1
- {showtime-cli-0.3.19 → showtime_cli-0.3.22/showtime_cli.egg-info}/PKG-INFO +19 -7
- {showtime-cli-0.3.19 → showtime_cli-0.3.22}/showtime_cli.egg-info/SOURCES.txt +0 -1
- showtime_cli-0.3.22/showtime_cli.egg-info/requires.txt +10 -0
- showtime-cli-0.3.19/requirements.txt +0 -7
- showtime-cli-0.3.19/showtime_cli.egg-info/requires.txt +0 -10
- {showtime-cli-0.3.19 → showtime_cli-0.3.22}/LICENSE +0 -0
- {showtime-cli-0.3.19 → showtime_cli-0.3.22}/MANIFEST.in +0 -0
- {showtime-cli-0.3.19 → showtime_cli-0.3.22}/README.md +0 -0
- {showtime-cli-0.3.19 → showtime_cli-0.3.22}/setup.cfg +0 -0
- {showtime-cli-0.3.19 → showtime_cli-0.3.22}/showtime/config.py +0 -0
- {showtime-cli-0.3.19 → showtime_cli-0.3.22}/showtime_cli.egg-info/dependency_links.txt +0 -0
- {showtime-cli-0.3.19 → showtime_cli-0.3.22}/showtime_cli.egg-info/entry_points.txt +0 -0
- {showtime-cli-0.3.19 → showtime_cli-0.3.22}/showtime_cli.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: showtime-cli
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.22
|
|
4
4
|
Summary: Command line show tracker using the TVMaze public API
|
|
5
5
|
Home-page: https://github.com/aquilax/showtime
|
|
6
6
|
Author: Evgeniy Vasilev
|
|
@@ -16,15 +16,27 @@ Classifier: Programming Language :: Python :: 3 :: Only
|
|
|
16
16
|
Classifier: Topic :: Utilities
|
|
17
17
|
Description-Content-Type: text/markdown
|
|
18
18
|
License-File: LICENSE
|
|
19
|
-
Requires-Dist: cmd2==2.
|
|
20
|
-
Requires-Dist: urllib3==2.0
|
|
19
|
+
Requires-Dist: cmd2==2.5.11
|
|
20
|
+
Requires-Dist: urllib3==2.5.0
|
|
21
21
|
Requires-Dist: ratelimit==2.2.1
|
|
22
|
-
Requires-Dist: tinydb==4.8.
|
|
22
|
+
Requires-Dist: tinydb==4.8.2
|
|
23
23
|
Requires-Dist: terminaltables==3.1.10
|
|
24
|
-
Requires-Dist: python-dateutil==2.
|
|
25
|
-
Requires-Dist: typing-extensions==4.
|
|
24
|
+
Requires-Dist: python-dateutil==2.9.0.post0
|
|
25
|
+
Requires-Dist: typing-extensions==4.12.2
|
|
26
26
|
Provides-Extra: test
|
|
27
27
|
Requires-Dist: tox; extra == "test"
|
|
28
|
+
Dynamic: author
|
|
29
|
+
Dynamic: author-email
|
|
30
|
+
Dynamic: classifier
|
|
31
|
+
Dynamic: description
|
|
32
|
+
Dynamic: description-content-type
|
|
33
|
+
Dynamic: home-page
|
|
34
|
+
Dynamic: keywords
|
|
35
|
+
Dynamic: license
|
|
36
|
+
Dynamic: license-file
|
|
37
|
+
Dynamic: provides-extra
|
|
38
|
+
Dynamic: requires-dist
|
|
39
|
+
Dynamic: summary
|
|
28
40
|
|
|
29
41
|
# showtime
|
|
30
42
|
|
|
@@ -13,26 +13,29 @@ max_line_length = 120
|
|
|
13
13
|
|
|
14
14
|
[tool.tox]
|
|
15
15
|
legacy_tox_ini = """
|
|
16
|
-
[tox]
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
mypy
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
16
|
+
[tox]
|
|
17
|
+
env_list = py311,mypy,doc
|
|
18
|
+
|
|
19
|
+
[testenv]
|
|
20
|
+
deps =
|
|
21
|
+
pytest
|
|
22
|
+
pytest-cov
|
|
23
|
+
cmd2_ext_test
|
|
24
|
+
commands = pytest
|
|
25
|
+
|
|
26
|
+
[testenv:mypy]
|
|
27
|
+
deps =
|
|
28
|
+
mypy
|
|
29
|
+
ratelimit-stubs
|
|
30
|
+
types-python-dateutil
|
|
31
|
+
types-requests
|
|
32
|
+
types-urllib3
|
|
33
|
+
commands = mypy -p showtime
|
|
34
|
+
|
|
35
|
+
[testenv:doc]
|
|
36
|
+
deps = interrogate
|
|
37
|
+
skip_install = true
|
|
38
|
+
commands = interrogate --quiet --fail-under 80 showtime
|
|
36
39
|
"""
|
|
37
40
|
|
|
38
41
|
[tool.interrogate]
|
|
@@ -35,13 +35,13 @@ setup(
|
|
|
35
35
|
'Topic :: Utilities',
|
|
36
36
|
],
|
|
37
37
|
install_requires=[
|
|
38
|
-
'cmd2==2.
|
|
39
|
-
'urllib3==2.0
|
|
38
|
+
'cmd2==2.5.11',
|
|
39
|
+
'urllib3==2.5.0',
|
|
40
40
|
'ratelimit==2.2.1',
|
|
41
|
-
'tinydb==4.8.
|
|
41
|
+
'tinydb==4.8.2',
|
|
42
42
|
'terminaltables==3.1.10',
|
|
43
|
-
'python-dateutil==2.
|
|
44
|
-
'typing-extensions==4.
|
|
43
|
+
'python-dateutil==2.9.0.post0',
|
|
44
|
+
'typing-extensions==4.12.2',
|
|
45
45
|
],
|
|
46
46
|
extras_require={
|
|
47
47
|
'test': ['tox'],
|
|
@@ -152,7 +152,18 @@ class Showtime(Cmd):
|
|
|
152
152
|
self.output.pfeedback('Syncing shows...')
|
|
153
153
|
self.app.sync(on_show_sync=self.output.status_on_show_sync,
|
|
154
154
|
on_episode_insert=self.output.status_on_episode_insert,
|
|
155
|
-
on_episode_update=self.output.status_on_episode_update
|
|
155
|
+
on_episode_update=self.output.status_on_episode_update,
|
|
156
|
+
all=False)
|
|
157
|
+
self.output.pfeedback('Done')
|
|
158
|
+
|
|
159
|
+
@cmd2.with_category(EPISODE_CATEGORY)
|
|
160
|
+
def do_sync_all(self, _: Statement) -> None:
|
|
161
|
+
"""Synchronize episodes with TVMaze [sync]"""
|
|
162
|
+
self.output.pfeedback('Syncing shows...')
|
|
163
|
+
self.app.sync(on_show_sync=self.output.status_on_show_sync,
|
|
164
|
+
on_episode_insert=self.output.status_on_episode_insert,
|
|
165
|
+
on_episode_update=self.output.status_on_episode_update,
|
|
166
|
+
all=True)
|
|
156
167
|
self.output.pfeedback('Done')
|
|
157
168
|
|
|
158
169
|
@cmd2.with_category(EPISODE_CATEGORY)
|
|
@@ -344,6 +355,13 @@ class Showtime(Cmd):
|
|
|
344
355
|
summary_table = self.output.summary_table(month_totals)
|
|
345
356
|
self.output.ppaged(summary_table)
|
|
346
357
|
|
|
358
|
+
@cmd2.with_category(SHOW_CATEGORY)
|
|
359
|
+
def do_unfinished(self, _: Statement) -> None:
|
|
360
|
+
"""Show list of unfinished shows"""
|
|
361
|
+
unfinished_shows = self.app.show_get_unfinished()
|
|
362
|
+
unfinished_shows_table = self.output.unfinished_shows_table(unfinished_shows)
|
|
363
|
+
self.output.ppaged(unfinished_shows_table)
|
|
364
|
+
|
|
347
365
|
|
|
348
366
|
def main() -> None:
|
|
349
367
|
api = Api(get_default_pool_manager())
|
|
@@ -11,7 +11,7 @@ from tinydb.queries import QueryLike
|
|
|
11
11
|
from tinydb.storages import JSONStorage, MemoryStorage
|
|
12
12
|
|
|
13
13
|
from showtime.types import (Episode, EpisodeId, Show, ShowId, ShowStatus,
|
|
14
|
-
TVMazeEpisode, TVMazeShow)
|
|
14
|
+
TVMazeEpisode, TVMazeShow, ShowWithCount)
|
|
15
15
|
|
|
16
16
|
SHOW = 'show'
|
|
17
17
|
EPISODE = 'episode'
|
|
@@ -39,7 +39,8 @@ class Database(TinyDB):
|
|
|
39
39
|
'id': tv_maze_show.id,
|
|
40
40
|
'name': tv_maze_show.name,
|
|
41
41
|
'premiered': tv_maze_show.premiered,
|
|
42
|
-
'status': tv_maze_show.status
|
|
42
|
+
'status': tv_maze_show.status,
|
|
43
|
+
'externals': tv_maze_show.externals,
|
|
43
44
|
})
|
|
44
45
|
return ShowId(tv_maze_show.id)
|
|
45
46
|
|
|
@@ -48,7 +49,8 @@ class Database(TinyDB):
|
|
|
48
49
|
return self.table(SHOW).update({
|
|
49
50
|
'name': tv_maze_show.name,
|
|
50
51
|
'premiered': tv_maze_show.premiered,
|
|
51
|
-
'status': tv_maze_show.status
|
|
52
|
+
'status': tv_maze_show.status,
|
|
53
|
+
'externals': tv_maze_show.externals,
|
|
52
54
|
}, where('id') == show_id)
|
|
53
55
|
|
|
54
56
|
def add_episode(self, show_id: ShowId, episode: TVMazeEpisode) -> EpisodeId:
|
|
@@ -152,6 +154,22 @@ class Database(TinyDB):
|
|
|
152
154
|
shows = self.table(SHOW).search(where('id').one_of(show_ids))
|
|
153
155
|
return cast(List[Show], shows)
|
|
154
156
|
|
|
157
|
+
def _get_shows_episodes_totals(self) -> List[ShowWithCount]:
|
|
158
|
+
all_shows = [{**show, 'total': 0, 'seen': 0} for show in self.table(SHOW)]
|
|
159
|
+
all_shows_keyed = {show['id']: show for show in all_shows}
|
|
160
|
+
for episode in self.table(EPISODE):
|
|
161
|
+
show_id = episode['show_id']
|
|
162
|
+
all_shows_keyed[show_id]['total'] += 1
|
|
163
|
+
if episode['watched'] != '':
|
|
164
|
+
all_shows_keyed[show_id]['seen'] += 1
|
|
165
|
+
return cast(List[ShowWithCount], all_shows_keyed.values())
|
|
166
|
+
|
|
167
|
+
def get_unfinished_shows(self) -> List[ShowWithCount]:
|
|
168
|
+
"""Returns list of unfinished shows"""
|
|
169
|
+
all_shows_totals = self._get_shows_episodes_totals()
|
|
170
|
+
unfinished_shows = [show for show in all_shows_totals if show['total'] > show['seen']]
|
|
171
|
+
return sorted(unfinished_shows, key=lambda item: item['premiered'] or "")
|
|
172
|
+
|
|
155
173
|
|
|
156
174
|
def get_direct_write_db(file_name: str) -> Database:
|
|
157
175
|
"""Returns database instance with direct interface"""
|
|
@@ -6,7 +6,7 @@ from typing import Callable, Dict, List
|
|
|
6
6
|
from terminaltables import AsciiTable as Table # type: ignore
|
|
7
7
|
|
|
8
8
|
from showtime.types import (DecoratedEpisode, Episode, Show, TVMazeEpisode,
|
|
9
|
-
TVMazeShow)
|
|
9
|
+
TVMazeShow, ShowWithCount)
|
|
10
10
|
|
|
11
11
|
PrintFunction = Callable[[str], None]
|
|
12
12
|
|
|
@@ -153,6 +153,29 @@ class Output():
|
|
|
153
153
|
title = 'Followed shows'
|
|
154
154
|
return str(Table(data, title=title).table)
|
|
155
155
|
|
|
156
|
+
def unfinished_shows_table(self, shows: List[ShowWithCount]) -> str:
|
|
157
|
+
"""formats list of shows with episodes count as a table"""
|
|
158
|
+
data = []
|
|
159
|
+
data.append([
|
|
160
|
+
'ID',
|
|
161
|
+
'Name',
|
|
162
|
+
'Premiered',
|
|
163
|
+
'Status',
|
|
164
|
+
'Episodes',
|
|
165
|
+
'Watched'
|
|
166
|
+
])
|
|
167
|
+
for show in shows:
|
|
168
|
+
data.append([
|
|
169
|
+
str(show['id']),
|
|
170
|
+
show['name'],
|
|
171
|
+
show['premiered'],
|
|
172
|
+
show['status'],
|
|
173
|
+
str(show['total']),
|
|
174
|
+
str(show['seen']),
|
|
175
|
+
])
|
|
176
|
+
title = 'Unfinished shows'
|
|
177
|
+
return str(Table(data, title=title).table)
|
|
178
|
+
|
|
156
179
|
def completed_shows_table(self, shows: List[Show]) -> str:
|
|
157
180
|
"""formats list of completed shows as a table"""
|
|
158
181
|
data = []
|
|
@@ -8,7 +8,7 @@ from ratelimit import limits, sleep_and_retry
|
|
|
8
8
|
from showtime.api import Api
|
|
9
9
|
from showtime.config import Config
|
|
10
10
|
from showtime.database import Database, transaction, NOT_WATCHED_VALUE
|
|
11
|
-
from showtime.types import (DecoratedEpisode, Episode, EpisodeId, Show, ShowId,
|
|
11
|
+
from showtime.types import (DecoratedEpisode, Episode, EpisodeId, Show, ShowId, ShowWithCount,
|
|
12
12
|
TVMazeEpisode, TVMazeShow)
|
|
13
13
|
|
|
14
14
|
|
|
@@ -157,10 +157,12 @@ class ShowtimeApp():
|
|
|
157
157
|
def sync(self,
|
|
158
158
|
on_show_sync: Union[Callable[[Show], None], None] = None,
|
|
159
159
|
on_episode_insert: Union[Callable[[TVMazeEpisode], None], None] = None,
|
|
160
|
-
on_episode_update: Union[Callable[[TVMazeEpisode], None], None] = None
|
|
160
|
+
on_episode_update: Union[Callable[[TVMazeEpisode], None], None] = None,
|
|
161
|
+
all=False):
|
|
161
162
|
"""Updates episode information for followed shows from tvmaze"""
|
|
162
163
|
with transaction(self.database) as transacted_db:
|
|
163
|
-
shows = transacted_db.get_active_shows()
|
|
164
|
+
shows = transacted_db.get_shows() if all else transacted_db.get_active_shows()
|
|
165
|
+
|
|
164
166
|
for show in shows:
|
|
165
167
|
show_id = ShowId(show['id'])
|
|
166
168
|
if on_show_sync:
|
|
@@ -255,3 +257,7 @@ class ShowtimeApp():
|
|
|
255
257
|
def episodes_get_watched(self) -> List[Episode]:
|
|
256
258
|
"""Returns all watched episodes"""
|
|
257
259
|
return self.database.get_watched_episodes()
|
|
260
|
+
|
|
261
|
+
def show_get_unfinished(self) -> List[ShowWithCount]:
|
|
262
|
+
"""Returns list of unfinished shows"""
|
|
263
|
+
return self.database.get_unfinished_shows()
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""Showtime Types Module"""
|
|
2
2
|
|
|
3
3
|
from enum import Enum
|
|
4
|
-
from typing import NamedTuple
|
|
4
|
+
from typing import NamedTuple, Dict
|
|
5
5
|
from typing_extensions import TypedDict
|
|
6
6
|
|
|
7
7
|
ShowId = int
|
|
@@ -16,6 +16,7 @@ class TVMazeShow(NamedTuple):
|
|
|
16
16
|
premiered: str
|
|
17
17
|
status: str
|
|
18
18
|
url: str
|
|
19
|
+
externals: Dict
|
|
19
20
|
|
|
20
21
|
|
|
21
22
|
class TVMazeEpisode(NamedTuple):
|
|
@@ -42,6 +43,13 @@ class Show(TypedDict):
|
|
|
42
43
|
name: str
|
|
43
44
|
premiered: Date
|
|
44
45
|
status: str
|
|
46
|
+
externals: Dict
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class ShowWithCount(Show):
|
|
50
|
+
"""DB Show with episode counts"""
|
|
51
|
+
total: int
|
|
52
|
+
seen: int
|
|
45
53
|
|
|
46
54
|
|
|
47
55
|
class Episode(TypedDict):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: showtime-cli
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.22
|
|
4
4
|
Summary: Command line show tracker using the TVMaze public API
|
|
5
5
|
Home-page: https://github.com/aquilax/showtime
|
|
6
6
|
Author: Evgeniy Vasilev
|
|
@@ -16,15 +16,27 @@ Classifier: Programming Language :: Python :: 3 :: Only
|
|
|
16
16
|
Classifier: Topic :: Utilities
|
|
17
17
|
Description-Content-Type: text/markdown
|
|
18
18
|
License-File: LICENSE
|
|
19
|
-
Requires-Dist: cmd2==2.
|
|
20
|
-
Requires-Dist: urllib3==2.0
|
|
19
|
+
Requires-Dist: cmd2==2.5.11
|
|
20
|
+
Requires-Dist: urllib3==2.5.0
|
|
21
21
|
Requires-Dist: ratelimit==2.2.1
|
|
22
|
-
Requires-Dist: tinydb==4.8.
|
|
22
|
+
Requires-Dist: tinydb==4.8.2
|
|
23
23
|
Requires-Dist: terminaltables==3.1.10
|
|
24
|
-
Requires-Dist: python-dateutil==2.
|
|
25
|
-
Requires-Dist: typing-extensions==4.
|
|
24
|
+
Requires-Dist: python-dateutil==2.9.0.post0
|
|
25
|
+
Requires-Dist: typing-extensions==4.12.2
|
|
26
26
|
Provides-Extra: test
|
|
27
27
|
Requires-Dist: tox; extra == "test"
|
|
28
|
+
Dynamic: author
|
|
29
|
+
Dynamic: author-email
|
|
30
|
+
Dynamic: classifier
|
|
31
|
+
Dynamic: description
|
|
32
|
+
Dynamic: description-content-type
|
|
33
|
+
Dynamic: home-page
|
|
34
|
+
Dynamic: keywords
|
|
35
|
+
Dynamic: license
|
|
36
|
+
Dynamic: license-file
|
|
37
|
+
Dynamic: provides-extra
|
|
38
|
+
Dynamic: requires-dist
|
|
39
|
+
Dynamic: summary
|
|
28
40
|
|
|
29
41
|
# showtime
|
|
30
42
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|