Exemple #1
0
def test_copy():
    from flamingo.core.data_model import ContentSet
    from copy import deepcopy

    cs1 = ContentSet()
    cs1.add(a=1)
    cs2 = deepcopy(cs1)

    assert cs1[0]['a'] == cs2[0]['a']
    assert cs1[0] is not cs2[0]
Exemple #2
0
def test_exclude():
    from flamingo.core.data_model import ContentSet

    cs = ContentSet()

    for i in range(10):
        cs.add(a=i)

    cs = cs.exclude(a=5)

    assert [i['a'] for i in cs] == [0, 1, 2, 3, 4, 6, 7, 8, 9]
Exemple #3
0
def test_in():
    from flamingo.core.data_model import ContentSet

    cs = ContentSet()

    for i in range(10):
        cs.add(a=i)

    cs = cs.filter(a__in=[4, 5, 8])

    assert [i['a'] for i in cs] == [4, 5, 8]
Exemple #4
0
def test_gte():
    from flamingo.core.data_model import ContentSet

    cs = ContentSet()

    for i in range(10):
        cs.add(a=i)

    cs = cs.filter(a__gte=5)

    assert [i['a'] for i in cs] == [5, 6, 7, 8, 9]
Exemple #5
0
def test_lt():
    from flamingo.core.data_model import ContentSet

    cs = ContentSet()

    for i in range(10):
        cs.add(a=i)

    cs = cs.filter(a__lt=5)

    assert [i['a'] for i in cs] == [0, 1, 2, 3, 4]
Exemple #6
0
def test_order_by():
    from flamingo.core.data_model import ContentSet

    cs = ContentSet()

    cs.add(a=4)
    cs.add(a=3)
    cs.add(a=5)
    cs.add(a=1)
    cs.add(a=2)

    assert [i['a'] for i in cs] == [4, 3, 5, 1, 2]
    assert [i['a'] for i in cs.order_by('a')] == [1, 2, 3, 4, 5]
    assert [i['a'] for i in cs.order_by('-a')] == [5, 4, 3, 2, 1]
Exemple #7
0
def test_iadd():
    from flamingo.core.data_model import ContentSet, Content

    cs = ContentSet()
    c1 = Content(a=1)
    c2 = Content(a=2)

    cs.add(c1)

    assert c1 in cs
    assert c2 not in cs

    cs += c2

    assert c1 in cs
    assert c2 in cs
Exemple #8
0
def add_media(context, content, name):
    # gen source
    if name.startswith('/'):
        source = os.path.join(context.settings.CONTENT_ROOT, name[1:])

    else:
        source = os.path.join(
            os.path.dirname(
                os.path.join(context.settings.CONTENT_ROOT, content['path'])),
            name,
        )

    source = os.path.normpath(source)

    # gen destination
    if name.startswith('/'):
        destination = os.path.join(
            context.settings.MEDIA_ROOT,
            name[1:],
        )

    else:
        destination = os.path.join(
            context.settings.MEDIA_ROOT,
            os.path.dirname(content['path']),
            os.path.basename(name),
        )

    # gen link
    link = os.path.join(
        '/media',
        os.path.relpath(destination, context.settings.MEDIA_ROOT),
    )

    # content['media']
    if not content['media']:
        content['media'] = ContentSet()

    media_content = Content(source=source, destination=destination, link=link)

    content['media'].add(media_content)

    return media_content
Exemple #9
0
def test_values():
    from flamingo.core.data_model import ContentSet

    cs = ContentSet()

    for i in range(10):
        cs.add(a=i, b=i + 1, c=i if i % 2 == 0 else None)

    assert cs.values('a', 'b', 'c') == [
        (0, 1, 0),
        (1, 2, None),
        (2, 3, 2),
        (3, 4, None),
        (4, 5, 4),
        (5, 6, None),
        (6, 7, 6),
        (7, 8, None),
        (8, 9, 8),
        (9, 10, None),
    ]

    assert cs.values('c') == [0, 2, 4, 6, 8]
Exemple #10
0
        def __init__(self, settings, contents=None):
            super().__init__(settings)

            self.settings = settings
            self.contents = contents or ContentSet()
Exemple #11
0
class Context:
    def __init__(self, settings):
        self.settings = settings

        # setup logging
        self.logger = logging.getLogger('flamingo')
        self.logger.debug('setting up context')

        # setup plugins
        self.plugins = []
        plugins = (self.settings.CORE_PLUGINS + self.settings.DEFAULT_PLUGINS +
                   self.settings.PLUGINS)

        for plugin in plugins:
            self.logger.debug("setting up plugin '%s' ", plugin)

            try:
                plugin_class = acquire(plugin)
                self.plugins.append(plugin_class())

            except Exception:
                self.logger.error('plugin setup failed', exc_info=True)

        # setup parser
        self.parser = FileParser()
        self.run_plugin_hook('parser_setup')

        # parse contents
        self.contents = ContentSet()
        self.content = None

        self._media = []  # FIXME: this should be part of Content()

        for path in self.get_source_paths():
            self.logger.debug("reading %s ", path)

            try:
                self.content = Content(
                    path=os.path.relpath(path, settings.CONTENT_ROOT))

                self.parser.parse(path, self.content)

                self.run_plugin_hook('content_parsed', self.content)

                self.contents.add(self.content)

            except ParsingError as e:
                self.logger.error('%s: %s', path, e)

            except Exception:
                self.logger.error('exception occoured while reading %s',
                                  path,
                                  exc_info=True)

        del self.content
        self.run_plugin_hook('contents_parsed')

        # setup templating engine
        templating_engine_class = acquire(settings.TEMPLATING_ENGINE)

        self.templating_engine = templating_engine_class(
            settings.THEME_PATHS + settings.CORE_THEME_PATHS)

        self.run_plugin_hook('templating_engine_setup', self.templating_engine)
        self.run_plugin_hook('context_setup')

    def get_source_paths(self):
        self.logger.debug('searching for content')

        supported_extensions = self.parser.get_extensions()

        if self.settings.CONTENT_PATHS:
            self.logger.debug('using user defined content paths')

            for path in self.settings.CONTENT_PATHS:
                path = os.path.join(self.settings.CONTENT_ROOT, path)
                extension = os.path.splitext(path)[1][1:]

                if extension not in supported_extensions:
                    self.logger.debug(
                        "skipping '%s'. extension '%s' is not supported", path,
                        extension)

                    continue

                yield path

        else:
            self.logger.debug("searching content recursive in %s",
                              self.settings.CONTENT_ROOT)

            for root, dirs, files in os.walk(self.settings.CONTENT_ROOT):
                for name in files:
                    extension = os.path.splitext(name)[1][1:]

                    if extension not in supported_extensions:
                        continue

                    yield os.path.join(root, name)

    def run_plugin_hook(self, name, *args, **kwargs):
        self.logger.debug("running plugin hook '%s'", name)

        for plugin in self.plugins:
            hook = getattr(plugin, name, None)

            if not hook:
                continue

            self.logger.debug('running %s.%s', plugin.__class__.__name__, name)
            hook(self, *args, **kwargs)

    def render(self, content, template_name=''):
        template_name = template_name or content['template']

        template_context = {
            'content': content,
            'context': self,
        }

        return self.templating_engine.render(template_name, template_context)

    def copy_media(self, filename, content_source_path):
        # gen source_path
        if filename.startswith('/'):
            source_path = os.path.join(self.settings.CONTENT_ROOT,
                                       filename[1:])

        else:
            source_path = os.path.join(
                os.path.dirname(
                    os.path.join(self.settings.CONTENT_ROOT,
                                 content_source_path)),
                filename,
            )

        source_path = os.path.normpath(source_path)

        # gen destination_path
        destination_path = os.path.join(
            self.settings.MEDIA_ROOT,
            os.path.relpath(source_path, self.settings.CONTENT_ROOT),
        )

        # gen link
        link = os.path.join(
            '/media',
            os.path.relpath(destination_path, self.settings.MEDIA_ROOT),
        )

        # check if media exists
        if not os.path.exists(source_path):
            self.logger.critical(
                "media '%s' does not exist (used as '%s' in '%s')",
                source_path,
                filename,
                content_source_path,
            )

        else:
            self._media.append((
                source_path,
                destination_path,
            ))

        return source_path, destination_path, link

    def build(self, clean=True):
        self.run_plugin_hook('pre_build')

        def makedirs(path):
            dirname = os.path.dirname(path)

            if not os.path.exists(dirname):
                self.logger.debug('mkdir -p %s', dirname)
                os.makedirs(dirname)

        # remove previous artifacts
        if clean and os.path.exists(self.settings.OUTPUT_ROOT):
            self.logger.debug('rm -rf %s', self.settings.OUTPUT_ROOT)
            shutil.rmtree(self.settings.OUTPUT_ROOT)

        # render contents
        for content in self.contents:
            output_path = os.path.join(self.settings.OUTPUT_ROOT,
                                       content['output'])

            makedirs(output_path)

            # render and write content
            with open(output_path, 'w+') as f:
                self.logger.debug("writing '%s'...", output_path)

                if content['template']:
                    output = self.render(content)

                else:
                    output = content['content']

                f.write(output)

        if self.settings.CONTENT_PATHS:
            return

        # copy media
        for source_path, destination_path in self._media:
            makedirs(destination_path)
            self.logger.debug('cp %s %s', source_path, destination_path)
            shutil.copy(source_path, destination_path)

        # copy static
        for static_dir in self.templating_engine.find_static_dirs():
            for root, dirs, files in os.walk(static_dir):
                for f in files:
                    src = os.path.join(root, f)

                    dst = os.path.join(
                        self.settings.STATIC_ROOT,
                        os.path.relpath(root, static_dir),
                        f,
                    )

                    self.logger.debug('cp %s %s', src, dst)

                    makedirs(dst)
                    shutil.copy(src, dst)

        self.run_plugin_hook('post_build')
Exemple #12
0
    def __init__(self, settings):
        self.settings = settings

        # setup logging
        self.logger = logging.getLogger('flamingo')
        self.logger.debug('setting up context')

        # setup plugins
        self.plugins = []
        plugins = (self.settings.CORE_PLUGINS + self.settings.DEFAULT_PLUGINS +
                   self.settings.PLUGINS)

        for plugin in plugins:
            self.logger.debug("setting up plugin '%s' ", plugin)

            try:
                plugin_class = acquire(plugin)
                self.plugins.append(plugin_class())

            except Exception:
                self.logger.error('plugin setup failed', exc_info=True)

        # setup parser
        self.parser = FileParser()
        self.run_plugin_hook('parser_setup')

        # parse contents
        self.contents = ContentSet()
        self.content = None

        self._media = []  # FIXME: this should be part of Content()

        for path in self.get_source_paths():
            self.logger.debug("reading %s ", path)

            try:
                self.content = Content(
                    path=os.path.relpath(path, settings.CONTENT_ROOT))

                self.parser.parse(path, self.content)

                self.run_plugin_hook('content_parsed', self.content)

                self.contents.add(self.content)

            except ParsingError as e:
                self.logger.error('%s: %s', path, e)

            except Exception:
                self.logger.error('exception occoured while reading %s',
                                  path,
                                  exc_info=True)

        del self.content
        self.run_plugin_hook('contents_parsed')

        # setup templating engine
        templating_engine_class = acquire(settings.TEMPLATING_ENGINE)

        self.templating_engine = templating_engine_class(
            settings.THEME_PATHS + settings.CORE_THEME_PATHS)

        self.run_plugin_hook('templating_engine_setup', self.templating_engine)
        self.run_plugin_hook('context_setup')
Exemple #13
0
def test_filter():
    from flamingo.core.data_model import ContentSet

    # keyword args
    cs = ContentSet()

    for i in range(10):
        cs.add(a=i)

    cs = cs.filter(a=5)

    assert cs.count() == 1
    assert cs[0]['a'] == 5

    # dict
    cs = ContentSet()

    for i in range(10):
        cs.add(a=i)

    cs = cs.filter({'a': 5})

    assert cs.count() == 1
    assert cs[0]['a'] == 5
Exemple #14
0
def test_ContentSet_get():
    from flamingo.core.data_model import ContentSet

    from flamingo.core.errors import (
        MultipleObjectsReturned,
        ObjectDoesNotExist,
    )

    # single object
    cs = ContentSet()

    cs.add(a=1)

    assert cs.get()['a'] == 1

    # simple get
    cs = ContentSet()

    cs.add(a=1)
    cs.add(a=2)

    assert cs.get(a=1)['a'] == 1

    # MultipleObjectsReturned
    cs = ContentSet()

    cs.add(a=1)
    cs.add(a=1)

    with pytest.raises(MultipleObjectsReturned):
        assert cs.get()

    with pytest.raises(MultipleObjectsReturned):
        assert cs.get(a=1)

    # ObjectDoesNotExist
    cs = ContentSet()

    cs.add(a=1)
    cs.add(a=2)

    with pytest.raises(ObjectDoesNotExist):
        assert cs.get(a=3)
Exemple #15
0
    def __init__(self, settings, contents=None):
        super().__init__()

        self.settings = settings
        self.errors = []

        # setup logging
        self.logger = logging.getLogger('flamingo')
        self.logger.debug('setting up context')

        # setup plugins
        self.plugins = []
        self.plugin_paths = []

        plugins = (self.settings.CORE_PLUGINS_PRE +
                   self.settings.DEFAULT_PLUGINS + self.settings.PLUGINS +
                   self.settings.CORE_PLUGINS_POST)

        for plugin in plugins:
            self.logger.debug("setting up plugin '%s' ", plugin)

            try:
                plugin_class, plugin_path = acquire(plugin)

                if plugin == 'flamingo.core.plugins.Hooks':
                    self.plugins.append(plugin_class(self))

                else:
                    self.plugins.append(plugin_class())

                self.plugin_paths.append(plugin_path)

            except Exception as e:
                self.logger.error('plugin setup failed', exc_info=True)
                self.errors.append(e)

        self.plugin_paths = list(set(self.plugin_paths))

        # discover plugin hooks
        self._plugin_hooks = {
            'parser_setup': [],
            'content_parsed': [],
            'contents_parsed': [],
            'templating_engine_setup': [],
            'context_setup': [],
            'pre_build': [],
            'post_build': [],

            # live-server hooks
            'render_content': [],
            'render_media_content': [],
        }

        hook_names = self._plugin_hooks.keys()

        for plugin in self.plugins:
            for hook_name in hook_names:
                if hook_name not in dir(plugin):
                    continue

                hook = getattr(plugin, hook_name)

                if hook:
                    self._plugin_hooks[hook_name].append((
                        plugin.__class__.__name__,
                        hook,
                    ))

        # setup parser
        self.parser = FileParser(context=self)
        self.run_plugin_hook('parser_setup')

        # parse contents
        self.contents = contents or ContentSet()
        self.parse_all()

        # setup templating engine
        templating_engine_class, path = acquire(settings.TEMPLATING_ENGINE)

        self.templating_engine = templating_engine_class(
            settings.THEME_PATHS +
            sum([getattr(i, 'THEME_PATHS', [])
                 for i in self.plugins], []) + settings.CORE_THEME_PATHS)

        self.run_plugin_hook('templating_engine_setup', self.templating_engine)
        self.run_plugin_hook('context_setup')