示例#1
0
def _render_entity_type_list_json(www_directory_path: str, entities: Iterable[Any], entity_type_name: str, configuration: Configuration) -> None:
    entity_type_path = os.path.join(www_directory_path, entity_type_name)
    with _create_json_resource(entity_type_path) as f:
        url_generator = SiteUrlGenerator(configuration)
        data = {
            '$schema': StaticPathUrlGenerator(configuration).generate('schema.json#/definitions/%sCollection' % entity_type_name, absolute=True),
            'collection': []
        }
        for entity in entities:
            data['collection'].append(url_generator.generate(
                entity, 'application/json', absolute=True))
        dump(data, f)
示例#2
0
文件: json.py 项目: gholamiayub/betty
 def __init__(self, configuration: Configuration, locale: str, *args,
              **kwargs):
     stdjson.JSONEncoder.__init__(self, *args, **kwargs)
     self._url_generator = SiteUrlGenerator(configuration)
     self._static_url_generator = StaticPathUrlGenerator(configuration)
     self._locale = locale
     self._mappers = {
         LocalizedName: self._encode_localized_name,
         Place: self._encode_place,
         Point: self._encode_coordinates,
         Person: self._encode_person,
         PersonName: self._encode_person_name,
         File: self._encode_file,
         DerivedEvent: self._encode_event,
         IdentifiableEvent: self._encode_identifiable_event,
         Event.Type: self._encode_event_type,
         Presence.Role: self._encode_presence_role,
         Date: self._encode_date,
         DateRange: self._encode_date_range,
         Citation: self._encode_citation,
         Source: self._encode_source,
         Link: self._encode_link,
         Note: self._encode_note,
     }
示例#3
0
文件: site.py 项目: patlx/betty
 def __init__(self, configuration: Configuration):
     self._site_stack = []
     self._ancestry = Ancestry()
     self._configuration = configuration
     self._assets = FileSystem(join(dirname(abspath(__file__)), 'assets'))
     self._dispatcher = Dispatcher()
     self._localized_url_generator = SiteUrlGenerator(configuration)
     self._static_url_generator = StaticPathUrlGenerator(configuration)
     self._locale = None
     self._translations = defaultdict(gettext.NullTranslations)
     self._default_translations = None
     self._plugins = OrderedDict()
     self._plugin_exit_stack = AsyncExitStack()
     self._init_plugins()
     self._init_dispatch_handlers()
     self._init_assets()
     self._init_translations()
     self._jinja2_environment = None
     self._renderer = None
     self._executor = None
     self._locks = Locks()
示例#4
0
 def test_generate_with_invalid_value(self):
     configuration = Configuration('/tmp', 'https://example.com')
     sut = SiteUrlGenerator(configuration)
     with self.assertRaises(ValueError):
         sut.generate(9, 'text/html')
示例#5
0
 def test_generate(self, expected: str, resource: Any):
     configuration = Configuration('/tmp', 'https://example.com')
     sut = SiteUrlGenerator(configuration)
     self.assertEquals(expected, sut.generate(resource, 'text/html'))
示例#6
0
文件: json.py 项目: gholamiayub/betty
class JSONEncoder(stdjson.JSONEncoder):
    def __init__(self, configuration: Configuration, locale: str, *args,
                 **kwargs):
        stdjson.JSONEncoder.__init__(self, *args, **kwargs)
        self._url_generator = SiteUrlGenerator(configuration)
        self._static_url_generator = StaticPathUrlGenerator(configuration)
        self._locale = locale
        self._mappers = {
            LocalizedName: self._encode_localized_name,
            Place: self._encode_place,
            Point: self._encode_coordinates,
            Person: self._encode_person,
            PersonName: self._encode_person_name,
            File: self._encode_file,
            DerivedEvent: self._encode_event,
            IdentifiableEvent: self._encode_identifiable_event,
            Event.Type: self._encode_event_type,
            Presence.Role: self._encode_presence_role,
            Date: self._encode_date,
            DateRange: self._encode_date_range,
            Citation: self._encode_citation,
            Source: self._encode_source,
            Link: self._encode_link,
            Note: self._encode_note,
        }

    @classmethod
    def get_factory(cls, configuration: Configuration, locale: str):
        return lambda *args, **kwargs: cls(configuration, locale, *args, **
                                           kwargs)

    def default(self, o):
        otype = type(o)
        if otype in self._mappers:
            return self._mappers[otype](o)
        stdjson.JSONEncoder.default(self, o)

    def _generate_url(self, resource: Any):
        return self._url_generator.generate(resource,
                                            'application/json',
                                            locale=self._locale)

    def _encode_schema(self, encoded: Dict, defintion: str) -> None:
        encoded['$schema'] = self._static_url_generator.generate(
            'schema.json#/definitions/%s' % defintion)

    def _encode_described(self, encoded: Dict, described: Described) -> None:
        if described.description is not None:
            encoded['description'] = described.description
            encoded.update({
                '@context': {},
            })
            encoded['@context'][
                'description'] = 'https://schema.org/description'

    def _encode_dated(self, encoded: Dict, dated: Dated) -> None:
        if dated.date is not None:
            encoded['date'] = dated.date

    def _encode_date(self, date: Date) -> Dict:
        encoded = {}
        if date.year:
            encoded['year'] = date.year
        if date.month:
            encoded['month'] = date.month
        if date.day:
            encoded['day'] = date.day
        return encoded

    def _encode_date_range(self, date: DateRange) -> Dict:
        encoded = {}
        if date.start:
            encoded['start'] = date.start
        if date.end:
            encoded['end'] = date.end
        return encoded

    def _encode_has_links(self, encoded: Dict, has_links: HasLinks) -> None:
        encoded['links'] = list(has_links.links)

    def _encode_link(self, link: Link) -> Dict:
        return {
            'url': link.url,
            'label': link.label,
        }

    def _encode_has_citations(self, encoded: Dict,
                              has_citations: HasCitations) -> None:
        encoded['citations'] = [
            self._generate_url(citation)
            for citation in has_citations.citations
        ]

    def _encode_coordinates(self, coordinates: Point) -> Dict:
        return {
            '@context': {
                'latitude': 'https://schema.org/latitude',
                'longitude': 'https://schema.org/longitude',
            },
            '@type': 'https://schema.org/GeoCoordinates',
            'latitude': coordinates.latitude,
            'longitude': coordinates.longitude,
        }

    def _encode_localized_name(self, name: LocalizedName) -> Dict:
        encoded = {
            'name': name.name,
        }
        if name.locale:
            encoded['locale'] = name.locale
        return encoded

    def _encode_place(self, place: Place) -> Dict:
        encoded = {
            '@context': {
                'events': 'https://schema.org/event',
                'encloses': 'https://schema.org/containsPlace',
            },
            '@type':
            'https://schema.org/Place',
            'id':
            place.id,
            'names':
            place.names,
            'events': [self._generate_url(event) for event in place.events],
            'encloses':
            [self._generate_url(enclosed) for enclosed in place.encloses]
        }
        self._encode_schema(encoded, 'place')
        self._encode_has_links(encoded, place)
        if place.coordinates is not None:
            encoded['coordinates'] = place.coordinates
            encoded['@context']['coordinates'] = 'https://schema.org/geo'
        if place.enclosed_by is not None:
            encoded['enclosedBy'] = self._generate_url(place.enclosed_by)
            encoded['@context'][
                'enclosedBy'] = 'https://schema.org/containedInPlace'
        return encoded

    def _encode_person(self, person: Person) -> Dict:
        encoded = {
            '@context': {
                'parents': 'https://schema.org/parent',
                'children': 'https://schema.org/child',
                'siblings': 'https://schema.org/sibling',
            },
            '@type':
            'https://schema.org/Person',
            'id':
            person.id,
            'names':
            list(person.names),
            'parents':
            [self._generate_url(parent) for parent in person.parents],
            'children':
            [self._generate_url(child) for child in person.children],
            'siblings':
            [self._generate_url(sibling) for sibling in person.siblings],
            'private':
            person.private,
            'presences': [],
        }
        for presence in person.presences:
            if isinstance(presence.event, Identifiable):
                encoded['presences'].append({
                    '@context': {
                        'event': 'https://schema.org/performerIn',
                    },
                    'role':
                    presence.role,
                    'event':
                    self._generate_url(presence.event),
                })
        self._encode_schema(encoded, 'person')
        self._encode_has_citations(encoded, person)
        self._encode_has_links(encoded, person)
        return encoded

    def _encode_person_name(self, name: PersonName) -> Dict:
        encoded = {}
        if name.individual is not None or name.affiliation is not None:
            encoded.update({
                '@context': {},
            })
        if name.individual is not None:
            encoded['@context']['individual'] = 'https://schema.org/givenName'
            encoded['individual'] = name.individual
        if name.affiliation is not None:
            encoded['@context'][
                'affiliation'] = 'https://schema.org/familyName'
            encoded['affiliation'] = name.affiliation
        return encoded

    def _encode_file(self, file: File) -> Dict:
        encoded = {
            'id': file.id,
            'entities':
            [self._generate_url(entity) for entity in file.resources],
            'notes': file.notes,
        }
        self._encode_schema(encoded, 'file')
        if file.type is not None:
            encoded['type'] = file.type
        return encoded

    def _encode_event(self, event: Event) -> Dict:
        encoded = {
            '@type':
            'https://schema.org/Event',
            'type':
            event.type,
            'presences': [{
                '@context': {
                    'person': 'https://schema.org/actor',
                },
                'role': presence.role,
                'person': self._generate_url(presence.person),
            } for presence in event.presences],
        }
        self._encode_schema(encoded, 'event')
        self._encode_dated(encoded, event)
        self._encode_has_citations(encoded, event)
        if event.place is not None:
            encoded['place'] = self._generate_url(event.place)
            encoded.update({
                '@context': {},
            })
            encoded['@context']['place'] = 'https://schema.org/location'
        return encoded

    def _encode_identifiable_event(self, event: Event) -> Dict:
        encoded = self._encode_event(event)
        encoded['id'] = event.id
        return encoded

    def _encode_event_type(self, event_type: Event.Type) -> str:
        return event_type.value

    def _encode_presence_role(self, role: Presence.Role) -> str:
        return role.value

    def _encode_citation(self, citation: Citation) -> Dict:
        encoded = {
            '@type': 'https://schema.org/Thing',
            'id': citation.id,
            'source': self._generate_url(citation.source),
            'facts': []
        }
        for fact in citation.facts:
            if isinstance(fact, Identifiable):
                encoded['facts'].append(self._generate_url(fact))
        self._encode_schema(encoded, 'citation')
        self._encode_dated(encoded, citation)
        return encoded

    def _encode_source(self, source: Source) -> Dict:
        encoded = {
            '@context': {
                'name': 'https://schema.org/name',
            },
            '@type':
            'https://schema.org/Thing',
            'id':
            source.id,
            'name':
            source.name,
            'contains':
            [self._generate_url(contained) for contained in source.contains],
            'citations':
            [self._generate_url(citation) for citation in source.citations],
        }
        if source.author is not None:
            encoded['author'] = source.author
        if source.publisher is not None:
            encoded['publisher'] = source.publisher
        self._encode_schema(encoded, 'source')
        self._encode_dated(encoded, source)
        self._encode_has_links(encoded, source)
        if source.contained_by is not None:
            encoded['containedBy'] = self._generate_url(source.contained_by)
        return encoded

    def _encode_note(self, note: Note) -> Dict:
        return {
            'text': note.text,
        }
示例#7
0
def create_environment(site: Site,
                       default_locale: Optional[str] = None) -> Environment:
    if default_locale is None:
        default_locale = site.configuration.default_locale
    url_generator = SiteUrlGenerator(site.configuration)
    template_directory_paths = list(
        [join(path, 'templates') for path in site.resources.paths])
    environment = Environment(
        loader=FileSystemLoader(template_directory_paths),
        undefined=StrictUndefined,
        autoescape=select_autoescape(['html']),
        trim_blocks=True,
        lstrip_blocks=True,
        extensions=[
            'jinja2.ext.do',
            'jinja2.ext.i18n',
        ],
    )
    environment.install_gettext_translations(site.translations[default_locale])
    environment.globals['site'] = site
    environment.globals['locale'] = default_locale
    environment.globals['plugins'] = _Plugins(site.plugins)
    environment.globals['EventType'] = Event.Type
    environment.globals['PresenceRole'] = Presence.Role
    environment.globals['urlparse'] = urlparse
    environment.filters['map'] = _filter_map
    environment.filters['flatten'] = _filter_flatten
    environment.filters['walk'] = _filter_walk
    environment.filters['takewhile'] = _filter_takewhile
    environment.filters['locale_get_data'] = lambda locale: Locale.parse(
        locale, '-')
    environment.filters[
        'negotiate_localizeds'] = lambda localizeds: negotiate_localizeds(
            default_locale, localizeds)
    environment.filters['sort_localizeds'] = contextfilter(
        lambda context, *args, **kwargs: _filter_sort_localizeds(
            context, default_locale, *args, **kwargs))

    # A filter to convert any value to JSON.
    @contextfilter
    def _filter_json(context, data, indent=None):
        return stdjson.dumps(data,
                             indent=indent,
                             cls=JSONEncoder.get_factory(
                                 site.configuration,
                                 resolve_or_missing(context, 'locale')))

    environment.filters['json'] = _filter_json

    # Override Jinja2's built-in JSON filter, which escapes the JSON for use in HTML, to use Betty's own encoder.
    @contextfilter
    def _filter_tojson(context, data, indent=None):
        return htmlsafe_json_dumps(data,
                                   indent=indent,
                                   dumper=lambda *args, **kwargs: _filter_json(
                                       context, *args, **kwargs))

    environment.filters['tojson'] = _filter_tojson
    environment.tests['resource'] = lambda x: isinstance(x, Resource)
    environment.tests['identifiable'] = lambda x: isinstance(x, Identifiable)
    environment.filters['paragraphs'] = _filter_paragraphs

    def _filter_format_date(date: Datey):
        with Translations(site.translations[default_locale]):
            return format_datey(date, default_locale)

    environment.filters['format_date'] = _filter_format_date
    environment.filters['format_degrees'] = _filter_format_degrees
    environment.globals['citer'] = _Citer()

    def _filter_url(resource, content_type=None, locale=None, **kwargs):
        content_type = content_type if content_type else 'text/html'
        locale = locale if locale else default_locale
        return url_generator.generate(resource,
                                      content_type,
                                      locale=locale,
                                      **kwargs)

    environment.filters['url'] = _filter_url
    environment.filters['static_url'] = StaticPathUrlGenerator(
        site.configuration).generate
    environment.filters['file'] = lambda *args: _filter_file(site, *args)
    environment.filters['image'] = lambda *args, **kwargs: _filter_image(
        site, *args, **kwargs)
    environment.globals['search_index'] = lambda: index(site, environment)
    for plugin in site.plugins.values():
        if isinstance(plugin, Jinja2Provider):
            environment.globals.update(plugin.globals)
            environment.filters.update(plugin.filters)
    return environment