Hide navigation sidebar
Hide table of contents sidebar
Skip to content
Back to top
Toggle table of contents sidebar

# Source code for betty.extension.privatizer

    """Privatize people and associated data by determining if they are likely to be alive."""

    from __future__ import annotations

    from collections import defaultdict
    from logging import getLogger
    from typing import TYPE_CHECKING, final

    from typing_extensions import override

    from betty.load import PostLoadAncestryEvent
    from betty.locale.localizable import _, Localizable
    from betty.model.ancestry import Person, HasPrivacy
    from betty.privatizer import Privatizer as PrivatizerApi
    from betty.project.extension import Extension

    if TYPE_CHECKING:
        from betty.event_dispatcher import EventHandlerRegistry
        from betty.machine_name import MachineName
        from betty.model import Entity

    async def _privatize_ancestry(event: PostLoadAncestryEvent) -> None:
        logger = getLogger(__name__)
        logger.info(event.project.app.localizer._("Privatizing..."))

        privatizer = PrivatizerApi(
            event.project.configuration.lifetime_threshold,
            localizer=event.project.app.localizer,
        )

        newly_privatized: dict[type[HasPrivacy & Entity], int] = defaultdict(lambda: 0)
        entities: list[HasPrivacy & Entity] = []
        for entity in event.project.ancestry:
            if isinstance(entity, HasPrivacy):
                entities.append(entity)
                if entity.private:
                    newly_privatized[entity.type] -= 1  # type: ignore[index]

        for entity in entities:
            privatizer.privatize(entity)

        for entity in entities:
            if entity.private:
                newly_privatized[entity.type] += 1  # type: ignore[index]

        if newly_privatized[Person] > 0:
            logger.info(
                event.project.app.localizer._(
                    "Privatized {count} people because they are likely still alive."
                ).format(
                    count=str(newly_privatized[Person]),
                )
            )
        for entity_type in set(newly_privatized) - {Person}:
            if newly_privatized[entity_type] > 0:
                logger.info(
                    event.project.app.localizer._(
                        "Privatized {count} {entity_type}, because they are associated with private information."
                    ).format(
                        count=str(newly_privatized[entity_type]),
                        entity_type=entity_type.plugin_label_plural().localize(
                            event.project.app.localizer
                        ),
                    )
                )

    @final
    class Privatizer(Extension):
        """
        Extend the Betty Application with privatization features.
        """

        @override
        @classmethod
        def plugin_id(cls) -> MachineName:
            return "privatizer"

        @override
        def register_event_handlers(self, registry: EventHandlerRegistry) -> None:
            registry.add_handler(PostLoadAncestryEvent, _privatize_ancestry)

        @override
        @classmethod
        def plugin_label(cls) -> Localizable:
            return _("Privatizer")

        @override
        @classmethod
        def plugin_description(cls) -> Localizable:
            return _(
                "Determine if people can be proven to have died. If not, mark them and their associated entities private."
            )