Source code for swissvotes.models.file

from onegov.file import File
from operator import attrgetter


from typing import TYPE_CHECKING
if TYPE_CHECKING:
    from onegov.core.orm import SessionManager
    from onegov.swissvotes.models import SwissVote
    from onegov.swissvotes.models import TranslatablePage
    from sqlalchemy.orm import relationship
    from typing import Protocol
    from typing import TypeVar

[docs] FileT = TypeVar('FileT', bound=File)
class HasFiles(Protocol[FileT]): files: relationship[list[FileT]] class HasFilesAndSessionManager(HasFiles[FileT], Protocol): @property def session_manager(self) -> SessionManager | None: ...
[docs] class SwissVoteFile(File): """ An attachment to a vote. """
[docs] __mapper_args__ = {'polymorphic_identity': 'swissvote'}
if TYPE_CHECKING: # backrefs created through associated
[docs] linked_swissvotes: relationship[list[SwissVote]]
@property
[docs] def locale(self) -> str: return self.name.split('-')[1]
@property
[docs] def filename(self) -> str: return self.reference.filename
[docs] class TranslatablePageFile(File): """ An attachment to a translatable content page. """
[docs] __mapper_args__ = {'polymorphic_identity': 'swissvotes_page'}
if TYPE_CHECKING: # backrefs created through associated
[docs] linked_swissvotes_page: relationship[list[TranslatablePage]]
@property
[docs] def locale(self) -> str: return self.name.split('-')[0]
@property
[docs] def filename(self) -> str: return self.reference.filename
[docs] class FileSubCollection: """ A subset of files prefixed by the descriptor's name. """
[docs] def __set_name__(self, owner: type['HasFiles[FileT]'], name: str) -> None: self.name = name
[docs] def __get__( self, instance: 'HasFiles[FileT] | None', owner: type['HasFiles[FileT]'] ) -> list['FileT']: if instance: return sorted(( file for file in instance.files if file.name.startswith(self.name) ), key=attrgetter('name')) return []
[docs] class LocalizedFile: """ A helper for localized files. Automatically choses the file according to the currently used locale. The files are internally stored as normal files using the filename to identify the wanted file. Example: class MyModel(Base, AssociatedFiles): pdf = LocalizedFile() """ def __init__( self, extension: str, label: str, static_views: dict[str, str] ) -> None:
[docs] self.extension = extension
[docs] self.label = label
[docs] self.static_views = static_views or {}
[docs] def __set_name__(self, owner: type['HasFiles[FileT]'], name: str) -> None: self.name = name
[docs] def __get_localized_name__( self, instance: 'HasFilesAndSessionManager[FileT]', locale: str | None = None ) -> str: if not locale: assert instance.session_manager is not None locale = instance.session_manager.current_locale return f'{self.name}-{locale}'
[docs] def __get_by_locale__( self, instance: 'HasFilesAndSessionManager[FileT] | None', locale: str | None = None ) -> 'FileT | None': if instance: name = self.__get_localized_name__(instance, locale) for file in instance.files: if file.name == name: return file return None
[docs] def __get__( self, instance: 'HasFilesAndSessionManager[FileT] | None', owner: type['HasFilesAndSessionManager[FileT]'] ) -> 'FileT | None': return self.__get_by_locale__(instance)
[docs] def __set_by_locale__( self, instance: 'HasFilesAndSessionManager[FileT]', value: 'FileT', locale: str | None = None ) -> None: value.name = self.__get_localized_name__(instance, locale) self.__delete_by_locale__(instance, locale) instance.files.append(value)
[docs] def __set__( self, instance: 'HasFilesAndSessionManager[FileT]', value: 'FileT' ) -> None: return self.__set_by_locale__(instance, value)
[docs] def __delete_by_locale__( self, instance: 'HasFilesAndSessionManager[FileT]', locale: str | None = None ) -> None: name = self.__get_localized_name__(instance, locale) # create a copy of the list since we remove elements for file in tuple(instance.files): if file.name == name: instance.files.remove(file)
[docs] def __delete__(self, instance: 'HasFilesAndSessionManager[FileT]') -> None: self.__delete_by_locale__(instance)
[docs] class LocalizedFiles: @classmethod
[docs] def localized_files(cls) -> dict[str, LocalizedFile]: return { name: attribute for name, attribute in cls.__dict__.items() if isinstance(attribute, LocalizedFile) }