Migrate from Poetry and pyenv to uv
This commit is contained in:
+61
-17
@@ -1,4 +1,6 @@
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
from .tag import Tag
|
||||
|
||||
|
||||
@@ -46,8 +48,12 @@ class File:
|
||||
stem is the version label. A flat file carries both in its own name.
|
||||
"""
|
||||
from .movie import identity_key
|
||||
from .naming import (is_canonical_pool_stem, parse_3d_format,
|
||||
parse_pool_stem, parse_tmdb_id)
|
||||
from .naming import (
|
||||
is_canonical_pool_stem,
|
||||
parse_3d_format,
|
||||
parse_pool_stem,
|
||||
parse_tmdb_id,
|
||||
)
|
||||
|
||||
parent = self.file_path.parent.name
|
||||
grouped = is_canonical_pool_stem(parent)
|
||||
@@ -58,8 +64,20 @@ class File:
|
||||
title = self.title or (parsed[0] if parsed else self.file_path.stem)
|
||||
|
||||
label = ""
|
||||
if grouped and self.file_path.stem.startswith(f"{parent} - "):
|
||||
label = self.file_path.stem[len(parent) + 3:]
|
||||
part = (
|
||||
re.fullmatch(
|
||||
rf"{re.escape(parent)}[\s._-]*(?:part|pt|cd|dvd|disc|disk)[\s._-]*(\d{{1,2}})",
|
||||
self.file_path.stem,
|
||||
re.IGNORECASE,
|
||||
)
|
||||
if grouped
|
||||
else None
|
||||
)
|
||||
if part:
|
||||
# one part of a film split across files: "<folder>-part2"
|
||||
label = f"part{int(part.group(1))}"
|
||||
elif grouped and self.file_path.stem.startswith(f"{parent} - "):
|
||||
label = self.file_path.stem[len(parent) + 3 :]
|
||||
elif parse_3d_format(self.file_path.stem):
|
||||
label = parse_3d_format(self.file_path.stem) or ""
|
||||
return identity_key(tmdb_id, title, year), title, year, tmdb_id, label
|
||||
@@ -109,7 +127,9 @@ class File:
|
||||
"new": self.new,
|
||||
"ignored": self.ignored,
|
||||
# ukládáme full_path tagů
|
||||
"tags": [tag.full_path if isinstance(tag, Tag) else tag for tag in self.tags],
|
||||
"tags": [
|
||||
tag.full_path if isinstance(tag, Tag) else tag for tag in self.tags
|
||||
],
|
||||
# which of the tags were derived automatically (from the NFO)
|
||||
"auto_tags": sorted(self.auto_tag_paths),
|
||||
# date může být None
|
||||
@@ -137,7 +157,9 @@ class File:
|
||||
raw_meta = data.get("meta")
|
||||
if raw_meta is None: # legacy: pull year/rating out of the old csfd cache
|
||||
old = data.get("csfd_cache") or {}
|
||||
raw_meta = {"year": old.get("year"), "rating": old.get("rating")} if old else None
|
||||
raw_meta = (
|
||||
{"year": old.get("year"), "rating": old.get("rating")} if old else None
|
||||
)
|
||||
self.meta = dict(raw_meta) if raw_meta else None
|
||||
|
||||
if not self.tagmanager:
|
||||
@@ -198,6 +220,7 @@ class File:
|
||||
if self.added:
|
||||
try:
|
||||
from datetime import datetime
|
||||
|
||||
return datetime.fromisoformat(self.added).timestamp()
|
||||
except ValueError:
|
||||
pass
|
||||
@@ -223,20 +246,23 @@ class File:
|
||||
if year is None:
|
||||
# Last resort: recover it from a canonical "Title (YYYY)" filename.
|
||||
from .naming import parse_pool_stem
|
||||
|
||||
parsed = parse_pool_stem(self.file_path.stem)
|
||||
if parsed is not None:
|
||||
year = parsed[1]
|
||||
rating = cache.get("rating")
|
||||
# user attributes first; core fields take precedence over same-named keys
|
||||
context = dict(self.attributes)
|
||||
context.update({
|
||||
"title": self.title or self.file_path.stem,
|
||||
"year": "" if year is None else str(year),
|
||||
"rating": "" if rating is None else rating,
|
||||
"ext": self.file_path.suffix,
|
||||
"stem": self.file_path.stem,
|
||||
"filename": self.filename,
|
||||
})
|
||||
context.update(
|
||||
{
|
||||
"title": self.title or self.file_path.stem,
|
||||
"year": "" if year is None else str(year),
|
||||
"rating": "" if rating is None else rating,
|
||||
"ext": self.file_path.suffix,
|
||||
"stem": self.file_path.stem,
|
||||
"filename": self.filename,
|
||||
}
|
||||
)
|
||||
return context
|
||||
|
||||
def set_attribute(self, key: str, value: str | None) -> None:
|
||||
@@ -250,6 +276,19 @@ class File:
|
||||
self.attributes.pop(key, None)
|
||||
self.save_metadata()
|
||||
|
||||
def save_location(self) -> None:
|
||||
"""Persist a rename/move of this file without touching shared metadata.
|
||||
|
||||
Every version of a film holds its own in-memory copy of the movie
|
||||
record's shared fields (title, tags, ČSFD, …). A sibling loaded before
|
||||
someone changed those fields would write its stale copy back on a plain
|
||||
:meth:`save_metadata`. Re-reading the record first means only this
|
||||
file's own media entry — path and popisek — actually changes.
|
||||
"""
|
||||
if self.index is not None and self.index.find_movie_by_media(self.file_path):
|
||||
self.get_metadata()
|
||||
self.save_metadata()
|
||||
|
||||
def delete_metadata(self) -> None:
|
||||
"""Drop this file from its movie record; the last one takes the record.
|
||||
|
||||
@@ -316,6 +355,7 @@ class File:
|
||||
|
||||
if schema is None:
|
||||
from .config import DEFAULT_TAG_SCHEMA
|
||||
|
||||
schema = DEFAULT_TAG_SCHEMA
|
||||
|
||||
self.meta = {"year": nfo.year, "rating": nfo.rating}
|
||||
@@ -331,8 +371,11 @@ class File:
|
||||
continue # user-only category
|
||||
category = entry["category"]
|
||||
for value in nfo.field_values(field):
|
||||
tag_obj = (self.tagmanager.add_tag(category, value)
|
||||
if self.tagmanager else Tag(category, value))
|
||||
tag_obj = (
|
||||
self.tagmanager.add_tag(category, value)
|
||||
if self.tagmanager
|
||||
else Tag(category, value)
|
||||
)
|
||||
if tag_obj not in self.tags:
|
||||
self.tags.append(tag_obj)
|
||||
tags_added.append(tag_obj.full_path)
|
||||
@@ -347,6 +390,7 @@ class File:
|
||||
def add_tag(self, tag):
|
||||
# tag může být Tag nebo string
|
||||
from .tag import Tag as TagClass
|
||||
|
||||
if isinstance(tag, str):
|
||||
if "/" in tag and self.tagmanager:
|
||||
category, name = tag.split("/", 1)
|
||||
@@ -375,4 +419,4 @@ class File:
|
||||
return
|
||||
if tag_obj in self.tags:
|
||||
self.tags.remove(tag_obj)
|
||||
self.save_metadata()
|
||||
self.save_metadata()
|
||||
|
||||
Reference in New Issue
Block a user