add creation timestamp to movies

This commit is contained in:
ducklet 2021-07-22 20:30:23 +02:00
parent 5514a8d1e1
commit 159ffce4b4
4 changed files with 74 additions and 12 deletions

View file

@ -165,12 +165,9 @@ def shared_connection() -> Database:
async def add(item): async def add(item):
# Support late initializing of `id` (used for optimization). # Support late initializing - used for optimization.
if hasattr(item, "id") and getattr(item, "id") is None: if getattr(item, "_is_lazy", False):
for f in fields(item): item._lazy_init()
if f.name == "id":
item.id = f.default_factory()
break
values = asplain(item) values = asplain(item)
keys = ", ".join(f"{k}" for k in values) keys = ", ".join(f"{k}" for k in values)

View file

@ -50,7 +50,7 @@ class BasicRow:
def as_movie(self): def as_movie(self):
assert self.startYear is not None assert self.startYear is not None
return Movie( return Movie.lazy(
title=self.primaryTitle, title=self.primaryTitle,
original_title=self.originalTitle, original_title=self.originalTitle,
release_year=self.startYear, release_year=self.startYear,
@ -59,8 +59,6 @@ class BasicRow:
imdb_score=None, imdb_score=None,
runtime=self.runtimeMinutes, runtime=self.runtimeMinutes,
genres=self.genres or set(), genres=self.genres or set(),
updated=None, # optimization: skip default factory
id=None, # optimization: skip default factory
) )
@ -77,12 +75,10 @@ class RatingRow:
return inst return inst
def as_movie(self): def as_movie(self):
return Movie( return Movie.lazy(
imdb_id=self.tconst, imdb_id=self.tconst,
imdb_score=score_from_imdb_rating(self.averageRating), imdb_score=score_from_imdb_rating(self.averageRating),
imdb_votes=self.numVotes, imdb_votes=self.numVotes,
updated=None, # optimization: skip default factory
id=None, # optimization: skip default factory
) )

View file

@ -35,6 +35,9 @@ def fields(class_or_instance):
for f in _fields(class_or_instance): for f in _fields(class_or_instance):
if f.name == "_is_lazy":
continue
if (attn := annotations(f.type)) and _RelationSentinel in attn: if (attn := annotations(f.type)) and _RelationSentinel in attn:
continue # Relations are ignored continue # Relations are ignored
@ -167,8 +170,36 @@ class Movie:
imdb_votes: Optional[int] = None imdb_votes: Optional[int] = None
runtime: Optional[int] = None # minutes runtime: Optional[int] = None # minutes
genres: set[str] = None genres: set[str] = None
created: datetime = field(default_factory=utcnow)
updated: datetime = field(default_factory=utcnow) updated: datetime = field(default_factory=utcnow)
_is_lazy: bool = field(default=False, init=False, repr=False, compare=False)
@classmethod
def lazy(cls, **kwds):
"""Return a new instance without running default factories.
This is meant purely for optimization purposes, to postpone possibly
expensive initialization operations.
"""
# XXX optimize using a metaclass & storing field refs on the class
kwds.setdefault("id", None)
kwds.setdefault("created", None)
kwds.setdefault("updated", None)
movie = cls(**kwds)
movie._is_lazy = True
return movie
def _lazy_init(self):
if not self._is_lazy:
return
for field in fields(Movie):
if getattr(self, field.name) is None and field.default_factory:
setattr(self, field.name, field.default_factory())
self._is_lazy = False
T = TypeVar("T") T = TypeVar("T")
_RelationSentinel = object() _RelationSentinel = object()

View file

@ -0,0 +1,38 @@
-- add creation timestamp to movies
CREATE TABLE _migrate_movies (
id TEXT PRIMARY KEY NOT NULL,
title TEXT NOT NULL,
original_title TEXT,
release_year INTEGER NOT NULL,
media_type TEXT NOT NULL,
imdb_id TEXT NOT NULL UNIQUE,
imdb_score INTEGER,
imdb_votes INTEGER,
runtime INTEGER,
genres TEXT NOT NULL,
created TEXT NOT NULL,
updated TEXT NOT NULL
);;
INSERT INTO _migrate_movies
SELECT
id,
title,
original_title,
release_year,
media_type,
imdb_id,
imdb_score,
imdb_votes,
runtime,
genres,
updated AS created,
updated
FROM movies
WHERE true;;
DROP TABLE movies;;
ALTER TABLE _migrate_movies
RENAME TO movies;;