Add NullPathType and types to PathType

This commit is contained in:
Šarūnas Nejus 2025-05-12 12:19:00 +01:00
parent 1a045c9166
commit b40ce836d5
No known key found for this signature in database
GPG key ID: DD28F6704DBE3435
5 changed files with 73 additions and 68 deletions

View file

@ -49,3 +49,5 @@ f36bc497c8c8f89004f3f6879908d3f0b25123e1
c490ac5810b70f3cf5fd8649669838e8fdb19f4d
# Importer restructure
9147577b2b19f43ca827e9650261a86fb0450cef
# Copy paste query, types from library to dbcore
1a045c91668c771686f4c871c84f1680af2e944b

View file

@ -40,6 +40,8 @@ else:
# To use the SQLite "blob" type, it doesn't suffice to provide a byte
# string; SQLite treats that as encoded text. Wrapping it in a
# `memoryview` tells it that we actually mean non-text data.
# needs to be defined in here due to circular import.
# TODO: remove it from this module and define it in dbcore/types.py instead
BLOB_TYPE = memoryview

View file

@ -22,6 +22,7 @@ import typing
from abc import ABC
from typing import TYPE_CHECKING, Any, Generic, TypeVar, cast
import beets
from beets import util
from . import query
@ -345,7 +346,7 @@ class DateType(Float):
return self.null
class PathType(Type[bytes, bytes]):
class BasePathType(Type[bytes, N]):
"""A dbcore type for filesystem paths.
These are represented as `bytes` objects, in keeping with
@ -356,27 +357,10 @@ class PathType(Type[bytes, bytes]):
query = query.PathQuery
model_type = bytes
def __init__(self, nullable=False):
"""Create a path type object.
def parse(self, string: str) -> bytes:
return util.normpath(string)
`nullable` controls whether the type may be missing, i.e., None.
"""
self.nullable = nullable
@property
def null(self):
if self.nullable:
return None
else:
return b""
def format(self, value):
return util.displayable_path(value)
def parse(self, string):
return util.normpath(util.bytestring_path(string))
def normalize(self, value):
def normalize(self, value: Any) -> bytes | N:
if isinstance(value, str):
# Paths stored internally as encoded bytes.
return util.bytestring_path(value)
@ -391,12 +375,30 @@ class PathType(Type[bytes, bytes]):
def from_sql(self, sql_value):
return self.normalize(sql_value)
def to_sql(self, value):
def to_sql(self, value: bytes) -> BLOB_TYPE:
if isinstance(value, bytes):
value = BLOB_TYPE(value)
return value
class NullPathType(BasePathType[None]):
@property
def null(self) -> None:
return None
def format(self, value: bytes | None) -> str:
return util.displayable_path(value or b"")
class PathType(BasePathType[bytes]):
@property
def null(self) -> bytes:
return b""
def format(self, value: bytes) -> str:
return util.displayable_path(value or b"")
class MusicalKey(String):
"""String representing the musical key of a song.

View file

@ -910,7 +910,7 @@ class Album(LibModel):
_always_dirty = True
_fields = {
"id": types.PRIMARY_ID,
"artpath": types.PathType(True),
"artpath": types.NullPathType(),
"added": types.DATE,
"albumartist": types.STRING,
"albumartist_sort": types.STRING,

View file

@ -1,15 +1,11 @@
import time
import unittest
import beets
from beets.dbcore import types
from beets.util import normpath
class LibraryFieldTypesTest(unittest.TestCase):
"""Test format() and parse() for library-specific field types"""
def test_datetype(self):
def test_datetype():
t = types.DATE
# format
@ -22,7 +18,8 @@ class LibraryFieldTypesTest(unittest.TestCase):
assert t.null == t.parse("not123456789.0")
assert t.null == t.parse("1973-11-29")
def test_pathtype(self):
def test_pathtype():
t = types.PathType()
# format
@ -32,7 +29,8 @@ class LibraryFieldTypesTest(unittest.TestCase):
assert normpath(b"/tmp") == t.parse("/tmp")
assert normpath(b"/tmp/\xc3\xa4lbum") == t.parse("/tmp/\u00e4lbum/")
def test_musicalkey(self):
def test_musicalkey():
t = types.MusicalKey()
# parse
@ -40,7 +38,8 @@ class LibraryFieldTypesTest(unittest.TestCase):
assert "Gm" == t.parse("g minor")
assert "Not c#m" == t.parse("not C#m")
def test_durationtype(self):
def test_durationtype():
t = types.DurationType()
# format