Skip to content

Commit

Permalink
Enable HTML page generation for all entity types instead of only the …
Browse files Browse the repository at this point in the history
…default Betty ones. (bartfeenstra#920)
  • Loading branch information
bartfeenstra authored Dec 6, 2022
1 parent 6d8f620 commit fa9cb66
Show file tree
Hide file tree
Showing 79 changed files with 3,322 additions and 1,892 deletions.
1 change: 1 addition & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ omit =

[report]
exclude_lines =
pass
# pragma: no cover
def __repr__
raise NotImplementedError
23 changes: 16 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

# Betty 👵

![Test status](https://github.com/bartfeenstra/betty/workflows/Test/badge.svg) [![Code coverage](https://codecov.io/gh/bartfeenstra/betty/branch/master/graph/badge.svg)](https://codecov.io/gh/bartfeenstra/betty) [![PyPI releases](https://badge.fury.io/py/betty.svg)](https://pypi.org/project/betty/) [![Supported Python versions](https://img.shields.io/pypi/pyversions/betty.svg?logo=python&logoColor=FBE072)](https://pypi.org/project/betty/) [![Recent downloads](https://img.shields.io/pypi/dm/betty.svg)](https://pypi.org/project/betty/) [![Follow Betty on Twitter](https://img.shields.io/twitter/follow/Betty_Project.svg?label=Betty_Project&style=flat&logo=twitter&logoColor=4FADFF)](https://twitter.com/Betty_Project)
Expand Down Expand Up @@ -88,6 +89,11 @@ locales:
- locale: en-US
alias: en
- locale: nl
entity_types:
Person:
generate_html_list: true
File:
generate_html_list: false
extensions:
betty.anonymizer.Anonymizer: {}
betty.cleaner.Cleaner: {}
Expand All @@ -114,27 +120,30 @@ extensions:
betty.wikipedia.Wikipedia: {}
```
- `base_url` (required); The absolute, public URL at which the site will be published.
- `base_url` (required): The absolute, public URL at which the site will be published.
- `debug` (optional): `true` to output more detailed logs and disable optimizations that make debugging harder. Defaults
to `false`.
- `root_path` (optional); The relative path under the public URL at which the site will be published.
- `clean_urls` (optional); A boolean indicating whether to use clean URLs, e.g. `/path` instead of `/path/index.html`.
- `root_path` (optional): The relative path under the public URL at which the site will be published.
- `clean_urls` (optional): A boolean indicating whether to use clean URLs, e.g. `/path` instead of `/path/index.html`.
Defaults to `false`.
- `content_negotiation` (optional): Enables dynamic content negotiation, but requires a web server
that supports it. This implies `clean_urls`. Defaults to `false`
- `title` (optional); The site's title.
- `author` (optional); The site's author and copyright holder.
- `title` (optional): The site's title.
- `author` (optional): The site's author and copyright holder.
- `lifetime_threshold` (optional); The number of years people are expected to live at most, e.g. after which they're
presumed to have died. Defaults to `125`.
- `locales` (optional); An array of locales, each of which is an object with the following keys:
- `locale`(required): An [IETF BCP 47](https://tools.ietf.org/html/bcp47) language tag.
- `alias` (optional): A shorthand alias to use instead of the full language tag, such as when rendering URLs.

If no locales are defined, Betty defaults to US English.
- `entity_types` (optional): Keys are entity type names, and values are objects containing the following keys:
- `generate_html_list` (optional): Whether to generate the HTML page to list entities of this type. Defaults to
`false`.
- `extensions` (optional): The extensions to enable. Keys are extension names, and values are objects containing the
following keys:
- `enabled` (optional). A boolean indicating whether the extension is enabled. Defaults to `true`.
- `configuration` (optional). An object containing the extension's own configuration, if it provides any configuration
- `enabled` (optional): A boolean indicating whether the extension is enabled. Defaults to `true`.
- `configuration` (optional): An object containing the extension's own configuration, if it provides any configuration
options.

Both keys may be omitted to quickly enable an extension using its default configuration.
Expand Down
6 changes: 3 additions & 3 deletions betty/_package/pyinstaller/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from betty.http_api_doc import HttpApiDoc
from betty.maps import Maps
from betty.npm import _Npm, build_assets
from betty.project import ProjectExtensionConfiguration
from betty.project import ExtensionConfiguration
from betty.trees import Trees


Expand All @@ -34,9 +34,9 @@ def _filter_submodule(submodule: str) -> bool:
async def _build_assets() -> None:
npm_builder_extension_types = {HttpApiDoc, Maps, Trees}
with App() as app:
app.project.configuration.extensions.add(ProjectExtensionConfiguration(_Npm))
app.project.configuration.extensions.add(ExtensionConfiguration(_Npm))
for extension_type in npm_builder_extension_types:
app.project.configuration.extensions.add(ProjectExtensionConfiguration(extension_type))
app.project.configuration.extensions.add(ExtensionConfiguration(extension_type))
await asyncio.gather(*[
build_assets(app.extensions[extension_type])
for extension_type
Expand Down
72 changes: 34 additions & 38 deletions betty/app/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from __future__ import annotations

import locale
import weakref
from concurrent.futures._base import Executor
from concurrent.futures.thread import ThreadPoolExecutor
Expand All @@ -9,45 +8,41 @@
from pathlib import Path
from typing import List, Type, TYPE_CHECKING, Set, Iterator, Optional

import aiohttp
from babel.core import parse_locale
from babel.localedata import locale_identifiers

try:
from typing import Self # type: ignore
except ImportError:
from typing_extensions import Self

from jinja2 import Environment as Jinja2Environment
from reactives import reactive
from reactives.factory.type import ReactiveInstance

from betty.app.extension import ListExtensions, Extension, Extensions, build_extension_type_graph, \
CyclicDependencyError, ExtensionDispatcher, ConfigurableExtension, discover_extension_types
from betty.asyncio import sync
from betty.concurrent import ExceptionRaisingAwaitableExecutor
from betty.config import FileBasedConfiguration, DumpedConfigurationImport, Configurable, DumpedConfigurationExport
from betty.config.load import ConfigurationValidationError, Loader, Field
from betty.dispatch import Dispatcher
from betty.fs import FileSystem, ASSETS_DIRECTORY_PATH, HOME_DIRECTORY_PATH
from betty.locale import negotiate_locale, TranslationsRepository, Translations, rfc_1766_to_bcp_47, bcp_47_to_rfc_1766
from betty.lock import Locks
from betty.model import Entity, EntityTypeProvider
from betty.model.ancestry import Citation, Event, File, Person, PersonName, Presence, Place, Enclosure, \
Source, Note, EventType
from betty.model.event_type import EventTypeProvider, Birth, Baptism, Adoption, Death, Funeral, Cremation, Burial, Will, \
Engagement, Marriage, MarriageAnnouncement, Divorce, DivorceAnnouncement, Residence, Immigration, Emigration, \
Occupation, Retirement, Correspondence, Confirmation
from betty.project import Project
from betty.render import Renderer, SequentialRenderer

try:
from graphlib_backport import TopologicalSorter, CycleError
except ModuleNotFoundError:
from graphlib import TopologicalSorter, CycleError
except ImportError:
from graphlib_backport import TopologicalSorter # type: ignore

import aiohttp
from jinja2 import Environment as Jinja2Environment
from reactives import reactive

from betty.concurrent import ExceptionRaisingAwaitableExecutor
from betty.config import ConfigurationError, FileBasedConfiguration, DumpedConfiguration
from betty.dispatch import Dispatcher
from betty.lock import Locks
from betty.render import Renderer, SequentialRenderer

from betty.model.ancestry import Citation, Event, File, Person, PersonName, Presence, Place, Enclosure, \
Source, Note, EventType
from betty.config import Configurable
from betty.fs import FileSystem, ASSETS_DIRECTORY_PATH, HOME_DIRECTORY_PATH
from betty.locale import negotiate_locale, TranslationsRepository, Translations, rfc_1766_to_bcp_47, bcp_47_to_rfc_1766
try:
from typing_extensions import Self
except ModuleNotFoundError:
from typing import Self # type: ignore

if TYPE_CHECKING:
from betty.builtins import _
Expand Down Expand Up @@ -90,22 +85,22 @@ def locale(self) -> Optional[str]:

@locale.setter
def locale(self, locale: str) -> None:
try:
parse_locale(bcp_47_to_rfc_1766(locale))
except ValueError:
raise ConfigurationValidationError(_('{locale} is not a valid IETF BCP 47 language tag.').format(locale=locale))
self._locale = locale

def load(self, dumped_configuration: DumpedConfiguration) -> None:
if not isinstance(dumped_configuration, dict):
raise ConfigurationError(_('Betty application configuration must be a mapping (dictionary).'))

if 'locale' in dumped_configuration:
if not isinstance(dumped_configuration['locale'], str):
raise ConfigurationError(_('The locale must be a string.'), contexts=['`title`'])
try:
parse_locale(bcp_47_to_rfc_1766(dumped_configuration['locale']))
except ValueError:
raise ConfigurationError(_('{locale} is not a valid IETF BCP 47 language tag.').format(locale=locale))
self.locale = dumped_configuration['locale']
def load(self, dumped_configuration: DumpedConfigurationImport, loader: Loader) -> None:
loader.assert_record(dumped_configuration, {
'locale': Field(
True,
loader.assert_str, # type: ignore
lambda x: loader.assert_setattr(self, 'locale', x),
),
})

def dump(self) -> DumpedConfiguration:
def dump(self) -> DumpedConfigurationExport:
dumped_configuration = {}
if self._locale is not None:
dumped_configuration['locale'] = self.locale
Expand All @@ -121,7 +116,8 @@ def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._configuration = AppConfiguration()
with suppress(FileNotFoundError):
self.configuration.read()
with Translations():
self.configuration.read()

self._acquired = False
self._extensions = _AppExtensions()
Expand Down
4 changes: 2 additions & 2 deletions betty/app/extension/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
Iterator, Sequence

try:
from typing import Self # type: ignore
except ImportError:
from typing_extensions import Self
except ModuleNotFoundError:
from typing import Self # type: ignore

from reactives import reactive, scope
from reactives.factory.type import ReactiveInstance
Expand Down
Loading

0 comments on commit fa9cb66

Please sign in to comment.