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)
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)
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')))
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
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')))
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)