Example #1
0
    def redirects(self):

        dct = NestedProperties()
        alist = [1, 2, 3]

        dct['foo'] = alist
        dct.redirect('foo', 'baz')

        assert 'foo' in dct
        assert 'baz' in dct
        assert dct['baz'] == alist
Example #2
0
    def test_redirects(self):

        dct = NestedProperties()
        alist = [1, 2, 3]

        dct['foo'] = alist
        dct.redirect('foo', 'baz')

        assert 'foo' in dct
        assert 'baz' in dct
        assert dct['baz'] == alist
Example #3
0
class Reader(object):

    __metaclass__ = abc.ABCMeta

    def __init__(self, conf, meta):

        self.props = NestedProperties((k, v) for k, v in conf.iteritems()
            if k in ['author', 'lang', 'encoding', 'email',
                     'date_format', 'entry_permalink', 'page_permalink'])

        self.props.update(meta)
        self.type = meta.get('type', 'entry')

        # redirect singular -> plural
        for key, to in {'tag': 'tags', 'filter': 'filters'}.iteritems():
            if key in self.props:
                self.props.redirect(key, to)

        self.filters = self.props.get('filters', [])

    @abc.abstractproperty
    def md5(self):
        return

    @abc.abstractproperty
    def source(self):
        return

    @abc.abstractproperty
    def has_changed(self):
        return

    @abc.abstractproperty
    def lastmodified(self):
        return

    def getfilters(self):
        return self._filters
    def setfilters(self, filters):
        if isinstance(filters, basestring):
            filters = [filters]
        self._filters = FilterTree(filters)
    filters = property(getfilters, setfilters)

    def gettype(self):
        """="Type of this entry. Can be either ``'entry'`` or ``'page'``"""
        return self._type
    def settype(self, value):
        if value not in ('entry', 'page'):
            raise ValueError("item type must be 'entry' or 'page'")
        self._type = value
    type = property(gettype, settype, doc=gettype.__doc__)

    def hasproperty(self, prop):
        """Test whether BaseEntry has prop in `self.props`."""
        return prop in self.props

    @property
    def date(self):
        return datetime.now()

    def __iter__(self):
        for key in self.props:
            yield key

        for key in (attr for attr in dir(self) if not attr.startswith('_')):
            yield key

    def __contains__(self, other):
        return other in self.props or other in self.__dict__

    def __getattr__(self, attr):
        try:
            return self.props[attr]
        except KeyError:
            raise AttributeError(attr)

    __getitem__ = lambda self, attr: getattr(self, attr)
Example #4
0
class Reader(object):

    __metaclass__ = abc.ABCMeta

    def __init__(self, conf, meta):

        self.props = NestedProperties(
            (k, v) for k, v in conf.iteritems() if k in [
                'author', 'lang', 'encoding', 'email', 'date_format',
                'entry_permalink', 'page_permalink'
            ])

        self.props.update(meta)
        self.type = meta.get('type', 'entry')

        # redirect singular -> plural
        for key, to in {'tag': 'tags', 'filter': 'filters'}.iteritems():
            if key in self.props:
                self.props.redirect(key, to)

        self.filters = self.props.get('filters', [])

    @abc.abstractproperty
    def md5(self):
        return

    @abc.abstractproperty
    def source(self):
        return

    @abc.abstractproperty
    def has_changed(self):
        return

    @abc.abstractproperty
    def lastmodified(self):
        return

    def getfilters(self):
        return self._filters

    def setfilters(self, filters):
        if isinstance(filters, basestring):
            filters = [filters]
        self._filters = FilterTree(filters)

    filters = property(getfilters, setfilters)

    def gettype(self):
        """="Type of this entry. Can be either ``'entry'`` or ``'page'``"""
        return self._type

    def settype(self, value):
        if value not in ('entry', 'page'):
            raise ValueError("item type must be 'entry' or 'page'")
        self._type = value

    type = property(gettype, settype, doc=gettype.__doc__)

    def hasproperty(self, prop):
        """Test whether BaseEntry has prop in `self.props`."""
        return prop in self.props

    @property
    def date(self):
        return datetime.now()

    def __iter__(self):
        for key in self.props:
            yield key

        for key in (attr for attr in dir(self) if not attr.startswith('_')):
            yield key

    def __contains__(self, other):
        return other in self.props or other in self.__dict__

    def __getattr__(self, attr):
        try:
            return self.props[attr]
        except KeyError:
            raise AttributeError(attr)

    __getitem__ = lambda self, attr: getattr(self, attr)
Example #5
0
class FileEntry(BaseEntry):

    def __init__(self, path, conf):

        self.filename = path
        self.mtime = os.path.getmtime(path)
        self.props = NestedProperties((k, v) for k, v in conf.iteritems()
            if k in ['author', 'lang', 'encoding', 'email',
                     'date_format', 'entry_permalink', 'page_permalink'])

        native = conf.get('metastyle', '').lower() == 'native'

        with io.open(path, 'r', encoding=conf['encoding'], errors='replace') as fp:

            if native and path.endswith(('.md', '.mkdown')):
                i, meta = markdownstyle(fp)
            elif native and path.endswith(('.rst', '.rest')):
                i, meta = reststyle(fp)
            else:
                i, meta = yamlstyle(fp)

        meta['title'] = unicode(meta['title'])  # YAML can convert 42 to an int

        self.offset = i
        self.type = meta.get('type', 'entry')
        self.props.update(meta)

        # redirect singular -> plural
        for key, to in {'tag': 'tags', 'filter': 'filters'}.iteritems():
            if key in self.props:
                self.props.redirect(key, to)

        self.filters = self.props.get('filters', [])

    def __repr__(self):
        return "<FileEntry f'%s'>" % self.filename

    @cached_property
    def date(self):
        """parse date value and return :class:`datetime.datetime` object,
        fallback to modification timestamp of the file if unset.
        You can set a ``DATE_FORMAT`` in your :doc:`../conf.py` otherwise
        Acrylamid tries several format strings and throws an exception if
        no pattern works.

        As shortcut you can access ``date.day``, ``date.month``, ``date.year``
        via ``entry.day``, ``entry.month`` and ``entry.year``."""

        # alternate formats from pelican.utils, thank you!
        # https://github.com/ametaireau/pelican/blob/master/pelican/utils.py
        formats = ['%Y-%m-%d %H:%M', '%Y/%m/%d %H:%M',
                   '%Y-%m-%d', '%Y/%m/%d',
                   '%d-%m-%Y', '%Y-%d-%m',  # Weird ones
                   '%d/%m/%Y', '%d.%m.%Y',
                   '%d.%m.%Y %H:%M', '%Y-%m-%d %H:%M:%S']

        if 'date' not in self.props:
            if self.type == 'entry':
                log.warn("using mtime from %r" % self.filename)
            return Date.fromtimestamp(self.mtime)

        string = re.sub(' +', ' ', self.props['date'])
        formats.insert(0, self.props['date_format'])

        for date_format in formats:
            try:
                return Date.strptime(string, date_format)
            except ValueError:
                pass
        else:
            raise AcrylamidException("%r is not a valid date" % string)

    @property
    def extension(self):
        """Filename's extension without leading dot"""
        return os.path.splitext(self.filename)[1][1:]

    @property
    def source(self):
        """Returns the actual, unmodified content."""
        with io.open(self.filename, 'r', encoding=self.props['encoding'],
        errors='replace') as f:
            return u''.join(f.readlines()[self.offset:]).strip()

    @cached_property
    def md5(self):
        return md5(self.filename, self.title, self.date)

    @property
    def content(self):

        # previous value
        res = self.source
        # growing dependencies of the filter chain
        deps = []

        for fxs in self.filters.iter(context=self.context):
            # extend dependencies
            deps.extend(fxs)

            try:
                for f in fxs:
                    res = f.transform(res, self, *f.args)
            except (IndexError, AttributeError):
                # jinja2 will ignore these Exceptions, better to catch them before
                traceback.print_exc(file=sys.stdout)

        return res

    @property
    def has_changed(self):
        return True

    @has_changed.setter
    def has_changed(self, value):
        self._has_changed = value