Esempio n. 1
0
    def __init__(self,
                 content,
                 metadata=None,
                 settings=None,
                 source_path=None,
                 context=None):
        if metadata is None:
            metadata = {}
        if settings is None:
            settings = copy.deepcopy(DEFAULT_CONFIG)

        self.settings = settings
        self._content = content
        if context is None:
            context = {}
        self._context = context
        self.translations = []

        local_metadata = dict(settings['DEFAULT_METADATA'])
        local_metadata.update(metadata)

        # set metadata as attributes
        for key, value in local_metadata.items():
            if key in ('save_as', 'url'):
                key = 'override_' + key
            setattr(self, key.lower(), value)

        # also keep track of the metadata attributes available
        self.metadata = local_metadata

        #default template if it's not defined in page
        self.template = self._get_template()

        # default author to the one in settings if not defined
        if not hasattr(self, 'author'):
            if 'AUTHOR' in settings:
                self.author = Author(settings['AUTHOR'], settings)

        # XXX Split all the following code into pieces, there is too much here.

        # manage languages
        self.in_default_lang = True
        if 'DEFAULT_LANG' in settings:
            default_lang = settings['DEFAULT_LANG'].lower()
            if not hasattr(self, 'lang'):
                self.lang = default_lang

            self.in_default_lang = (self.lang == default_lang)

        # create the slug if not existing, from the title
        if not hasattr(self, 'slug') and hasattr(self, 'title'):
            self.slug = slugify(self.title,
                                settings.get('SLUG_SUBSTITUTIONS', ()))

        self.source_path = source_path

        # manage the date format
        if not hasattr(self, 'date_format'):
            if hasattr(self, 'lang') and self.lang in settings['DATE_FORMATS']:
                self.date_format = settings['DATE_FORMATS'][self.lang]
            else:
                self.date_format = settings['DEFAULT_DATE_FORMAT']

        if isinstance(self.date_format, tuple):
            locale_string = self.date_format[0]
            if sys.version_info < (3, ) and isinstance(locale_string,
                                                       six.text_type):
                locale_string = locale_string.encode('ascii')
            locale.setlocale(locale.LC_ALL, locale_string)
            self.date_format = self.date_format[1]

        if hasattr(self, 'date'):
            self.locale_date = strftime(self.date, self.date_format)

        # manage status
        if not hasattr(self, 'status'):
            self.status = settings['DEFAULT_STATUS']
            if not settings['WITH_FUTURE_DATES']:
                if hasattr(self, 'date') and self.date > datetime.now():
                    self.status = 'draft'

        # store the summary metadata if it is set
        if 'summary' in metadata:
            self._summary = metadata['summary']

        signals.content_object_init.send(self)
Esempio n. 2
0
    def __init__(self,
                 content,
                 metadata=None,
                 settings=None,
                 source_path=None,
                 context=None):
        if metadata is None:
            metadata = {}
        if settings is None:
            settings = copy.deepcopy(DEFAULT_CONFIG)

        self.settings = settings
        self._content = content
        if context is None:
            context = {}
        self._context = context
        self.translations = []

        local_metadata = dict()
        local_metadata.update(metadata)

        # set metadata as attributes
        for key, value in local_metadata.items():
            if key in ('save_as', 'url'):
                key = 'override_' + key
            setattr(self, key.lower(), value)

        # also keep track of the metadata attributes available
        self.metadata = local_metadata

        # default template if it's not defined in page
        self.template = self._get_template()

        # First, read the authors from "authors", if not, fallback to "author"
        # and if not use the settings defined one, if any.
        if not hasattr(self, 'author'):
            if hasattr(self, 'authors'):
                self.author = self.authors[0]
            elif 'AUTHOR' in settings:
                self.author = Author(settings['AUTHOR'], settings)

        if not hasattr(self, 'authors') and hasattr(self, 'author'):
            self.authors = [self.author]

        # XXX Split all the following code into pieces, there is too much here.

        # manage languages
        self.in_default_lang = True
        if 'DEFAULT_LANG' in settings:
            default_lang = settings['DEFAULT_LANG'].lower()
            if not hasattr(self, 'lang'):
                self.lang = default_lang

            self.in_default_lang = (self.lang == default_lang)

        # create the slug if not existing, generate slug according to
        # setting of SLUG_ATTRIBUTE
        if not hasattr(self, 'slug'):
            if (settings['SLUGIFY_SOURCE'] == 'title'
                    and hasattr(self, 'title')):
                self.slug = slugify(self.title,
                                    settings.get('SLUG_SUBSTITUTIONS', ()))
            elif (settings['SLUGIFY_SOURCE'] == 'basename'
                  and source_path is not None):
                basename = os.path.basename(os.path.splitext(source_path)[0])
                self.slug = slugify(basename,
                                    settings.get('SLUG_SUBSTITUTIONS', ()))

        self.source_path = source_path

        # manage the date format
        if not hasattr(self, 'date_format'):
            if hasattr(self, 'lang') and self.lang in settings['DATE_FORMATS']:
                self.date_format = settings['DATE_FORMATS'][self.lang]
            else:
                self.date_format = settings['DEFAULT_DATE_FORMAT']

        if isinstance(self.date_format, tuple):
            locale_string = self.date_format[0]
            if sys.version_info < (3, ) and isinstance(locale_string,
                                                       six.text_type):
                locale_string = locale_string.encode('ascii')
            locale.setlocale(locale.LC_ALL, locale_string)
            self.date_format = self.date_format[1]

        # manage timezone
        default_timezone = settings.get('TIMEZONE', 'UTC')
        timezone = getattr(self, 'timezone', default_timezone)

        if hasattr(self, 'date'):
            self.date = set_date_tzinfo(self.date, timezone)
            self.locale_date = strftime(self.date, self.date_format)

        if hasattr(self, 'modified'):
            self.modified = set_date_tzinfo(self.modified, timezone)
            self.locale_modified = strftime(self.modified, self.date_format)

        # manage status
        if not hasattr(self, 'status'):
            self.status = settings['DEFAULT_STATUS']
            if not settings['WITH_FUTURE_DATES'] and hasattr(self, 'date'):
                if self.date.tzinfo is None:
                    now = SafeDatetime.now()
                else:
                    now = SafeDatetime.utcnow().replace(tzinfo=pytz.utc)
                if self.date > now:
                    self.status = 'draft'

        # store the summary metadata if it is set
        if 'summary' in metadata:
            self._summary = metadata['summary']

        signals.content_object_init.send(self)
Esempio n. 3
0
        def replacer(m):
            what = m.group('what')
            value = urlparse(m.group('value'))
            path = value.path
            origin = m.group('path')

            # XXX Put this in a different location.
            if what in {'filename', 'attach'}:
                if path.startswith('/'):
                    path = path[1:]
                else:
                    # relative to the source path of this content
                    path = self.get_relative_source_path(
                        os.path.join(self.relative_dir, path))

                if path not in self._context['filenames']:
                    unquoted_path = path.replace('%20', ' ')

                    if unquoted_path in self._context['filenames']:
                        path = unquoted_path

                linked_content = self._context['filenames'].get(path)
                if linked_content:
                    if what == 'attach':
                        if isinstance(linked_content, Static):
                            linked_content.attach_to(self)
                        else:
                            logger.warning(
                                "%s used {attach} link syntax on a "
                                "non-static file. Use {filename} instead.",
                                self.get_relative_source_path())
                    origin = '/'.join((siteurl, linked_content.url))
                    origin = origin.replace('\\', '/')  # for Windows paths.
                else:
                    logger.warning(
                        "Unable to find `%s`, skipping url replacement.",
                        value.geturl(),
                        extra={
                            'limit_msg': ("Other resources were not found "
                                          "and their urls not replaced")
                        })
            elif what == 'category':
                origin = '/'.join((siteurl, Category(path, self.settings).url))
            elif what == 'tag':
                origin = '/'.join((siteurl, Tag(path, self.settings).url))
            elif what == 'index':
                origin = '/'.join((siteurl, self.settings['INDEX_SAVE_AS']))
            elif what == 'author':
                origin = '/'.join((siteurl, Author(path, self.settings).url))
            else:
                logger.warning(
                    "Replacement Indicator '%s' not recognized, "
                    "skipping replacement", what)

            # keep all other parts, such as query, fragment, etc.
            parts = list(value)
            parts[2] = origin
            origin = urlunparse(parts)

            return ''.join((m.group('markup'), m.group('quote'), origin,
                            m.group('quote')))
Esempio n. 4
0
    def parse_jpeg(self, *, source_path: str) -> Tuple[str, dict]:
        JpegReader.logger.info(source_path)

        img = Image.open(source_path)

        image_data = Exiv2Parser.get_values(source_path)

        title = image_data.get(Exiv.DESCRIPTION.value, "Untitled")
        author = image_data.get(Exiv.ARTIST.value, "Unknown")
        date_string = image_data.get(Exiv.DATETIME.value, "")

        date = datetime.strptime(date_string, "%Y:%m:%d %H:%M:%S")
        slug = URLWrapper(image_data.get(Exiv.HEADLINE.value, title),
                          self.settings).slug
        description_long = image_data.get(Exiv.COMMENT.value, "")
        summary = image_data.get(Exiv.CAPTION.value, description_long[:140])

        tags = [
            Tag(tag, self.settings)
            for tag in image_data.get(Exiv.KEYWORDS.value, list())
        ]

        content_root = self.settings[PelicanConfig.PATH.value]
        path_output = self.settings[PelicanConfig.OUTPUT_PATH.value]
        relative_source = dirname(source_path[len(content_root):]).lstrip(sep)
        if self.settings[PelicanConfig.USE_FOLDER_AS_CATEGORY.value]:
            category = relative_source.split(sep)[-1]
        else:
            category = image_data.get(Exiv.CATEGORY.value, None)

        type_of_content = relative_source.split(sep)[
            0]  # either 'blog' or 'pages' as far as I know.
        url_site = self.settings[PelicanConfig.SITE_URL.value]

        if type_of_content.lower() == PelicanClass.PAGES.value:
            url_document = self.settings[PelicanConfig.PAGE_URL.value]
            document_save_as = self.settings[PelicanConfig.PAGE_SAVE_AS.value]
        else:  # Assume PelicanClass.BLOG
            url_document = self.settings[PelicanConfig.ARTICLE_URL.value]
            document_save_as = self.settings[
                PelicanConfig.ARTICLE_SAVE_AS.value]

        page_url_complete = join(url_site, url_document)

        author_wrapper = Author(author, self.settings)

        # Move image in place:
        metadata = {
            PelicanMetadata.TITLE.value: title,
            PelicanMetadata.AUTHORS.value: [author_wrapper],
            PelicanMetadata.DATE.value: date,
            PelicanMetadata.SLUG.value: slug,
            PelicanMetadata.TAGS.value: tags,
            PelicanMetadata.CUSTOM_ALL.value: image_data,
        }
        if category is not None:
            metadata[PelicanMetadata.CATEGORY.value] = Category(
                category, self.settings)

        thumb_name = "{0}_thumb.jpg".format(slug)
        original_name = "{0}.jpg".format(slug)

        path_output_html = join(path_output,
                                document_save_as).format(**metadata)
        path_output_dir = dirname(path_output_html)
        path_output_original = join(path_output_dir, original_name)
        path_output_thumb = join(path_output_dir, thumb_name)

        # Here we generate the summary info incase this is used for articles we get nice thumbnails and summary
        metadata[PelicanMetadata.SUMMARY.value] = summary
        metadata[PelicanMetadata.FEATURED_IMAGE.value] = join(
            url_site, path_output_thumb[len(path_output):])
        if Exiv.OBJECT_NAME.value in image_data:
            metadata[PelicanMetadata.TEMPLATE.value] = image_data[
                Exiv.OBJECT_NAME.value]

        # Write the size/HTML out before we reduce the image to a thumb
        content = "<img src='{src}' alt='{alt}' style='width: {width}px; height: auto; max-width: 100%;'></img><p>{body}</p>".format(
            src=original_name,
            alt=title,
            width=img.width,
            height=img.height,
            body=description_long,
        )

        # Ensure the directory levels exist
        if not isdir(path_output_dir):
            makedirs(path_output_dir)
        img.save(path_output_original)
        img.thumbnail(self.thumb_size)
        img.save(path_output_thumb)

        # Debug info if we need it
        JpegReader.logger.debug(content)
        JpegReader.logger.debug(str(metadata))
        JpegReader.logger.debug(path_output_html)

        return content, metadata
Esempio n. 5
0
    def _link_replacer(self, siteurl, m):
        what = m.group('what')
        value = urlparse(m.group('value'))
        path = value.path
        origin = m.group('path')

        # urllib.parse.urljoin() produces `a.html` for urljoin("..", "a.html")
        # so if RELATIVE_URLS are enabled, we fall back to os.path.join() to
        # properly get `../a.html`. However, os.path.join() produces
        # `baz/http://foo/bar.html` for join("baz", "http://foo/bar.html")
        # instead of correct "http://foo/bar.html", so one has to pick a side
        # as there is no silver bullet.
        if self.settings['RELATIVE_URLS']:
            joiner = os.path.join
        else:
            joiner = urljoin

            # However, it's not *that* simple: urljoin("blog", "index.html")
            # produces just `index.html` instead of `blog/index.html` (unlike
            # os.path.join()), so in order to get a correct answer one needs to
            # append a trailing slash to siteurl in that case. This also makes
            # the new behavior fully compatible with Pelican 3.7.1.
            if not siteurl.endswith('/'):
                siteurl += '/'

        # XXX Put this in a different location.
        if what in {'filename', 'static', 'attach'}:
            if path.startswith('/'):
                path = path[1:]
            else:
                # relative to the source path of this content
                path = self.get_relative_source_path(
                    os.path.join(self.relative_dir, path))

            key = 'static_content' if what in ('static', 'attach')\
                else 'generated_content'

            def _get_linked_content(key, path):
                try:
                    return self._context[key][path]
                except KeyError:
                    try:
                        # Markdown escapes spaces, try unescaping
                        return self._context[key][path.replace('%20', ' ')]
                    except KeyError:
                        if what == 'filename' and key == 'generated_content':
                            key = 'static_content'
                            linked_content = _get_linked_content(key, path)
                            if linked_content:
                                logger.warning(
                                    '{filename} used for linking to static'
                                    'content %s in %s. Use {static} instead',
                                    path, self.get_relative_source_path())
                                return linked_content
                        return None

            linked_content = _get_linked_content(key, path)
            if linked_content:
                if what == 'attach':
                    linked_content.attach_to(self)
                origin = joiner(siteurl, linked_content.url)
                origin = origin.replace('\\', '/')  # for Windows paths.
            else:
                logger.warning(
                    "Unable to find '%s', skipping url replacement.",
                    value.geturl(),
                    extra={
                        'limit_msg': ("Other resources were not found "
                                      "and their urls not replaced")
                    })
        elif what == 'category':
            origin = joiner(siteurl, Category(path, self.settings).url)
        elif what == 'tag':
            origin = joiner(siteurl, Tag(path, self.settings).url)
        elif what == 'index':
            origin = joiner(siteurl, self.settings['INDEX_SAVE_AS'])
        elif what == 'author':
            origin = joiner(siteurl, Author(path, self.settings).url)
        else:
            logger.warning(
                "Replacement Indicator '%s' not recognized, "
                "skipping replacement", what)

        # keep all other parts, such as query, fragment, etc.
        parts = list(value)
        parts[2] = origin
        origin = urlunparse(parts)

        return ''.join(
            (m.group('markup'), m.group('quote'), origin, m.group('quote')))
Esempio n. 6
0
    def __init__(self,
                 content,
                 metadata=None,
                 settings=None,
                 source_path=None,
                 context=None):
        if metadata is None:
            metadata = {}
        if settings is None:
            settings = copy.deepcopy(DEFAULT_CONFIG)

        self.settings = settings
        self._content = content
        if context is None:
            context = {}
        self._context = context
        self.translations = []

        local_metadata = dict()
        local_metadata.update(metadata)

        # set metadata as attributes
        for key, value in local_metadata.items():
            if key in ('save_as', 'url'):
                key = 'override_' + key
            setattr(self, key.lower(), value)

        # also keep track of the metadata attributes available
        self.metadata = local_metadata

        # default template if it's not defined in page
        self.template = self._get_template()

        # First, read the authors from "authors", if not, fallback to "author"
        # and if not use the settings defined one, if any.
        if not hasattr(self, 'author'):
            if hasattr(self, 'authors'):
                self.author = self.authors[0]
            elif 'AUTHOR' in settings:
                self.author = Author(settings['AUTHOR'], settings)

        if not hasattr(self, 'authors') and hasattr(self, 'author'):
            self.authors = [self.author]

        # XXX Split all the following code into pieces, there is too much here.

        # manage languages
        self.in_default_lang = True
        if 'DEFAULT_LANG' in settings:
            default_lang = settings['DEFAULT_LANG'].lower()
            if not hasattr(self, 'lang'):
                self.lang = default_lang

            self.in_default_lang = (self.lang == default_lang)

        # create the slug if not existing, generate slug according to
        # setting of SLUG_ATTRIBUTE
        if not hasattr(self, 'slug'):
            if (settings['SLUGIFY_SOURCE'] == 'title'
                    and hasattr(self, 'title')):
                value = self.title
            elif (settings['SLUGIFY_SOURCE'] == 'basename'
                  and source_path is not None):
                value = os.path.basename(os.path.splitext(source_path)[0])
            else:
                value = None
            if value is not None:
                self.slug = slugify(
                    value,
                    regex_subs=settings.get('SLUG_REGEX_SUBSTITUTIONS', []),
                    preserve_case=settings.get('SLUGIFY_PRESERVE_CASE', False),
                    use_unicode=settings.get('SLUGIFY_USE_UNICODE', False))

        self.source_path = source_path
        self.relative_source_path = self.get_relative_source_path()

        # manage the date format
        if not hasattr(self, 'date_format'):
            if hasattr(self, 'lang') and self.lang in settings['DATE_FORMATS']:
                self.date_format = settings['DATE_FORMATS'][self.lang]
            else:
                self.date_format = settings['DEFAULT_DATE_FORMAT']

        if isinstance(self.date_format, tuple):
            locale_string = self.date_format[0]
            locale.setlocale(locale.LC_ALL, locale_string)
            self.date_format = self.date_format[1]

        # manage timezone
        default_timezone = settings.get('TIMEZONE', 'UTC')
        timezone = getattr(self, 'timezone', default_timezone)
        self.timezone = pytz.timezone(timezone)

        if hasattr(self, 'date'):
            self.date = set_date_tzinfo(self.date, timezone)
            self.locale_date = self.date.strftime(self.date_format)

        if hasattr(self, 'modified'):
            self.modified = set_date_tzinfo(self.modified, timezone)
            self.locale_modified = self.modified.strftime(self.date_format)

        # manage status
        if not hasattr(self, 'status'):
            # Previous default of None broke comment plugins and perhaps others
            self.status = getattr(self, 'default_status', '')

        # store the summary metadata if it is set
        if 'summary' in metadata:
            self._summary = metadata['summary']

        signals.content_object_init.send(self)