def header(renderer, text, level, raw):
     anchor_type = self.get_config().get('anchor-type')
     if anchor_type == "random":
         anchor = uuid.uuid4().hex[:6]
     elif anchor_type == "custom":
         # Extract custom anchor from origin header.
         # The header should match the syntax:
         # `text (#anchor)`,
         # if matched, text and anchor get the value respectively,
         # otherwise fallback to slugify function.
         #
         # Firstly, this syntax give the user the ability to
         # customize the TOC anchor link.
         # `# How Lektor Works (#anchor-text)` renders to
         # <h1 id="anchor-text">How Lektor Works</h1>
         #
         # However this is a pretty workaround and useful way for
         # those non-ascii languages, such as CJK to use the
         # custom anchor as the slug.
         # `# 中文标题 (#chinese-title)` renders to
         # <h1 id="chinese-title">中文标题</h1>
         match = re.search(r'(.*)\(#(.*)\)', text)
         if match:
             text, anchor = match.groups()
             anchor = anchor.replace(' ', '')
         else:
             anchor = slugify(raw)
     else:
         anchor = slugify(raw)
     renderer.meta['toc'].append((level, anchor, Markup(text)))
     return '<h%d id="%s">%s</h%d>' % (level, anchor, text, level)
Esempio n. 2
0
def test_slugify():
    from lektor.utils import slugify

    assert slugify("w o w") == "w-o-w"
    assert slugify(u"Șö prĕtty") == "so-pretty"
    assert slugify("im age.jpg") == "im-age.jpg"
    assert slugify("slashed/slug") == "slashed/slug"
Esempio n. 3
0
 def header(renderer, text, level, raw):
     if self.get_config().get('anchor-type') == "random":
         anchor = uuid.uuid4().hex[:6]
     else:
         anchor = slugify(raw)
     renderer.meta['toc'].append((level, anchor, Markup(text)))
     return '<h%d id="%s">%s</h%d>' % (level, anchor, text, level)
Esempio n. 4
0
 def get_slug(self, source):
     slug_expr = self.slug_expr
     if slug_expr is None:
         slug = source._id
     else:
         slug = str(slug_expr.__get__(source))
     return slugify(slug)
Esempio n. 5
0
def _meetup_to_lektor_id(data):
    """"""
    local_date = data.get('local_date', '')

    name = data.get('name', '')
    _name = unidecode(name)
    for key, val in _REPLACE.items():
        _name = _name.replace(key, val)

    _name = slugify(_name)
    id_ = local_date + '-' + _name

    date_part = '/'.join(local_date.split('-')[:-1])
    slug = date_part + '/' + _name

    if id_ not in _ID_CACHE:
        _ID_CACHE[id_] = 0
        final_id = id_
    else:
        _ID_CACHE[id_] += 1
        final_id = id_ + '-' + str(_ID_CACHE[id_])

    if slug not in _SLUG_CACHE:
        _SLUG_CACHE[slug] = 0
        final_slug = slug[:]
    else:
        _SLUG_CACHE[slug] += 1

        if slug not in SLUG_WARNING_IGNORE:
            print(slug)

        final_slug = slug + '-' + str(_SLUG_CACHE[slug])

    return final_id, final_slug
Esempio n. 6
0
 def header(renderer, text, level, raw):
     anchor = slugify(raw)
     renderer.meta['toc'].append((level, anchor, Markup(text)))
     return u'<h{level:d} id="{anchor}">{text}</h{level:d}>'.format(
         level=renderer.adjusted_header_level(level),
         anchor=anchor,
         text=text,
     )
Esempio n. 7
0
    def get_default_child_slug(self, pad, data):
        """Formats out the child slug."""
        slug_format = self.child_config.slug_format
        if slug_format is None:
            return slugify(data['_id'])

        if self._child_slug_tmpl is None or \
           self._child_slug_tmpl[0] != slug_format:
            self._child_slug_tmpl = (slug_format,
                                     FormatExpression(self.env, slug_format))

        try:
            return '_'.join(self._child_slug_tmpl[1].evaluate(
                pad, this=data).strip().split()).strip('/')
        except Exception:
            # XXX: log
            return 'temp-' + slugify(data['_id'])
Esempio n. 8
0
def project_quickstart(defaults=None):
    if not defaults:
        defaults = {}

    g = Generator('project')

    g.title('Lektor Quickstart')
    g.text(
        'This wizard will generate a new basic project with some sensible '
        'defaults for getting started quickly.  We just need to go through '
        'a few questions so that the project is set up correctly for you.'
    )

    name = defaults.get('name')
    if name is None:
        name = g.prompt('Project Name', None,
            'A project needs a name.  The name is primarily used for the admin '
            'UI and some other places to refer to your project to not get '
            'confused if multiple projects exist.  You can change this at '
            'any later point.')

    author_name = g.prompt('Author Name', get_default_author(),
        'Your name.  This is used in a few places in the default template '
        'to refer to in the default copyright messages.')

    path = defaults.get('path')
    if path is None:
        here = os.path.abspath(os.getcwd())
        default_project_path = None
        try:
            if len(os.listdir(here)) == []:
                default_project_path = here
        except OSError:
            pass
        if default_project_path is None:
            default_project_path = os.path.join(os.getcwd(), name)
        path = g.prompt('Project Path', default_project_path,
            'This is the path where the project will be located.  You can '
            'move a project around later if you do not like the path.  If '
            'you provide a relative path it will be relative to the working '
            'directory.')
        path = os.path.expanduser(path)

    with_blog = g.prompt('Add Basic Blog', True,
        'Do you want to generate a basic blog module?  If you enable this '
        'the models for a very basic blog will be generated.')

    g.confirm('That\'s all. Create project?')

    g.run({
        'project_name': name,
        'project_slug': slugify(name),
        'project_path': path,
        'with_blog': with_blog,
        'this_year': datetime.utcnow().year,
        'today': datetime.utcnow().strftime('%Y-%m-%d'),
        'author_name': author_name,
    }, path)
Esempio n. 9
0
def project_quickstart(defaults=None):
    if not defaults:
        defaults = {}

    g = Generator('project')

    g.title('Lektor Quickstart')
    g.text(
        'This wizard will generate a new basic project with some sensible '
        'defaults for getting started quickly.  We just need to go through '
        'a few questions so that the project is set up correctly for you.'
    )

    name = defaults.get('name')
    if name is None:
        name = g.prompt('Project Name', None,
            'A project needs a name.  The name is primarily used for the admin '
            'UI and some other places to refer to your project to not get '
            'confused if multiple projects exist.  You can change this at '
            'any later point.')

    author_name = g.prompt('Author Name', get_default_author(),
        'Your name.  This is used in a few places in the default template '
        'to refer to in the default copyright messages.')

    path = defaults.get('path')
    if path is None:
        here = os.path.abspath(os.getcwd())
        default_project_path = None
        try:
            if len(os.listdir(here)) == []:
                default_project_path = here
        except OSError:
            pass
        if default_project_path is None:
            default_project_path = os.path.join(os.getcwd(), name)
        path = g.prompt('Project Path', default_project_path,
            'This is the path where the project will be located.  You can '
            'move a project around later if you do not like the path.  If '
            'you provide a relative path it will be relative to the working '
            'directory.')
        path = os.path.expanduser(path)

    with_blog = g.prompt('Add Basic Blog', True,
        'Do you want to generate a basic blog module?  If you enable this '
        'the models for a very basic blog will be generated.')

    g.confirm('That\'s all. Create project?')

    g.run({
        'project_name': name,
        'project_slug': slugify(name),
        'project_path': path,
        'with_blog': with_blog,
        'this_year': datetime.utcnow().year,
        'today': datetime.utcnow().strftime('%Y-%m-%d'),
        'author_name': author_name,
    }, path)
Esempio n. 10
0
    def get_default_child_slug(self, pad, data):
        """Formats out the child slug."""
        slug_format = self.child_config.slug_format
        if slug_format is None:
            return slugify(data['_id'])

        if self._child_slug_tmpl is None or \
           self._child_slug_tmpl[0] != slug_format:
            self._child_slug_tmpl = (
                slug_format,
                FormatExpression(self.env, slug_format)
            )

        try:
            return '_'.join(self._child_slug_tmpl[1].evaluate(
                pad, this=data).strip().split()).strip('/')
        except Exception:
            # XXX: log
            return 'temp-' + slugify(data['_id'])
Esempio n. 11
0
    def publish(self, target_url, credentials=None, server_info=None, **extra):
        draft = '--draft' in click.get_current_context().args
        host = target_url.host

        if credentials and credentials.get('key'):
            access_token = credentials['key']
        elif server_info and server_info.extra.get('key'):
            access_token = server_info.extra['key']
        else:
            raise RuntimeError(
                "Use lektor deploy --key <ACCESS_TOKEN>,"
                " see https://github.com/ajdavis/lektor-netlify/README.md")

        sites_url = (
            'https://api.netlify.com/api/v1/sites?access_token=' +
            access_token)

        response = requests.get(
            sites_url,
            headers={'User-Agent': 'https://github.com/ajdavis/lektor-netlify'})

        response.raise_for_status()
        j = response.json()
        for site in j:
            site_url = urls.url_parse(unicode(site['url']))
            if site_url.host == host:
                site_id = site['site_id']
                break
        else:
            site_name = slugify(host).replace('.', '-')
            force_ssl = bool_from_string(server_info.extra.get('force_ssl'),
                                         default=False)

            print('Creating new Netlify site "%s" at %s' % (site_name, host))
            response = requests.post(sites_url, {
                'name': site_name,
                'custom_domain': host,
                'force_ssl': force_ssl})
            response.raise_for_status()
            site_id = response.json()['site_id']

        cmd = [
            'netlify',
            'deploy',
            '--auth', access_token,
            '--site', site_id,
            '--dir', self.output_path]

        if draft:
            yield "Deploying as draft"
        else:
            cmd.append('--prod')

        for line in Command(cmd):
            yield line
Esempio n. 12
0
    def publish(self, target_url, credentials=None, server_info=None, **extra):
        draft = '--draft' in click.get_current_context().args
        host = target_url.host

        if credentials and credentials.get('key'):
            access_token = credentials['key']
        elif server_info and server_info.extra.get('key'):
            access_token = server_info.extra['key']
        else:
            raise RuntimeError(
                "Use lektor deploy --key <ACCESS_TOKEN>,"
                " see https://github.com/ajdavis/lektor-netlify/README.md")

        sites_url = (
            'https://api.netlify.com/api/v1/sites?access_token=' +
            access_token)

        response = requests.get(
            sites_url,
            headers={'User-Agent': 'https://github.com/ajdavis/lektor-netlify'})

        response.raise_for_status()
        j = response.json()
        for site in j:
            site_url = urls.url_parse(unicode(site['url']))
            if site_url.host == host:
                site_id = site['site_id']
                break
        else:
            site_name = slugify(host).replace('.', '-')
            force_ssl = bool_from_string(server_info.extra.get('force_ssl'),
                                         default=False)

            print('Creating new Netlify site "%s" at %s' % (site_name, host))
            response = requests.post(sites_url, {
                'name': site_name,
                'custom_domain': host,
                'force_ssl': force_ssl})
            response.raise_for_status()
            site_id = response.json()['site_id']

        cmd = [
            'netlify',
            '-t', access_token,
            'deploy',
            '-s', site_id,
            '-p', self.output_path]

        if draft:
            yield "Deploying as draft"
            cmd.append('--draft')

        for line in Command(cmd):
            yield line
Esempio n. 13
0
def plugin_quickstart(defaults=None, project=None):
    if defaults is None:
        defaults = {}

    g = Generator('plugin')

    plugin_name = defaults.get('plugin_name')
    if plugin_name is None:
        plugin_name = g.prompt(
            'Plugin Name',
            default=None,
            info='This is the human readable name for this plugin')

    plugin_id = plugin_name.lower()  # pylint: disable=no-member
    if plugin_id.startswith('lektor'):
        plugin_id = plugin_id[6:]
    if plugin_id.endswith('plugin'):
        plugin_id = plugin_id[:-6]
    plugin_id = slugify(plugin_id)

    path = defaults.get('path')
    if path is None:
        if project is not None:
            default_path = os.path.join(project.tree, 'packages', plugin_id)
        else:
            if len(os.listdir('.')) == 0:
                default_path = os.getcwd()
            else:
                default_path = os.path.join(os.getcwd(), plugin_id)
        path = g.prompt('Plugin Path', default_path,
                        'The place where you want to initialize the plugin')

    author_name = g.prompt(
        'Author Name', get_default_author(),
        'Your name as it will be embedded in the plugin metadata.')

    author_email = g.prompt('Author E-Mail', get_default_author_email(),
                            'Your e-mail address for the plugin info.')

    g.confirm('Create Plugin?')

    g.run(
        {
            'plugin_name': plugin_name,
            'plugin_id': plugin_id,
            'plugin_class': plugin_id.title().replace('-', '') + 'Plugin',
            'plugin_module': 'lektor_' + plugin_id.replace('-', '_'),
            'author_name': author_name,
            'author_email': author_email,
        }, path)
Esempio n. 14
0
def plugin_quickstart(defaults=None, project=None):
    if defaults is None:
        defaults = {}

    g = Generator('plugin')

    plugin_name = defaults.get('plugin_name')
    if plugin_name is None:
        plugin_name = g.prompt('Plugin Name', default=None,
            info='This is the human readable name for this plugin')

    plugin_id = plugin_name.lower()  # pylint: disable=no-member
    if plugin_id.startswith('lektor'):
        plugin_id = plugin_id[6:]
    if plugin_id.endswith('plugin'):
        plugin_id = plugin_id[:-6]
    plugin_id = slugify(plugin_id)

    path = defaults.get('path')
    if path is None:
        if project is not None:
            default_path = os.path.join(project.tree, 'packages',
                                        plugin_id)
        else:
            if len(os.listdir('.')) == 0:
                default_path = os.getcwd()
            else:
                default_path = os.path.join(os.getcwd(), plugin_id)
        path = g.prompt('Plugin Path', default_path,
            'The place where you want to initialize the plugin')

    author_name = g.prompt('Author Name', get_default_author(),
        'Your name as it will be embedded in the plugin metadata.')

    author_email = g.prompt('Author E-Mail', get_default_author_email(),
        'Your e-mail address for the plugin info.')

    g.confirm('Create Plugin?')

    g.run({
        'plugin_name': plugin_name,
        'plugin_id': plugin_id,
        'plugin_class': plugin_id.title().replace('-', '') + 'Plugin',
        'plugin_module': 'lektor_' + plugin_id.replace('-', '_'),
        'author_name': author_name,
        'author_email': author_email,
    }, path)
Esempio n. 15
0
    def get_default_child_slug(self, pad, data):
        """Formats out the child slug."""
        slug_format = self.child_config.slug_format
        if slug_format is None:
            return data["_id"]

        if self._child_slug_tmpl is None or self._child_slug_tmpl[
                0] != slug_format:
            self._child_slug_tmpl = (
                slug_format,
                FormatExpression(self.env, slug_format),
            )

        try:
            return "_".join(self._child_slug_tmpl[1].evaluate(
                pad, this=data).strip().split()).strip("/")
        except Exception:
            # XXX: log
            return "temp-" + slugify(data["_id"])
Esempio n. 16
0
    def get_default_child_slug(self, pad, data):
        """Formats out the child slug."""
        slug_format = self.child_config.slug_format
        if slug_format is None:
            return data["_id"]

        if self._child_slug_tmpl is None or self._child_slug_tmpl[
                0] != slug_format:
            self._child_slug_tmpl = (
                slug_format,
                FormatExpression(self.env, slug_format),
            )

        try:
            return "_".join(self._child_slug_tmpl[1].evaluate(
                pad, this=data).strip().split()).strip("/")
        except Exception as exc:
            reporter.report_generic("Failed to expand child slug_format: %s" %
                                    exc)
            return "temp-" + slugify(data["_id"])
 def header(renderer, text, level, raw):
     anchor = slugify(raw)
     renderer.meta['toc'].append((level, anchor, Markup(text)))
     return '<h%d id="%s">%s</h%d>' % (level, anchor, text, level)
Esempio n. 18
0
 def value_from_raw(self, raw):
     if raw.value is None:
         return raw.missing_value('Missing slug')
     return slugify(raw.value)
 def header(renderer, text, level, raw):
     anchor = slugify(raw)
     renderer.meta['toc'].append((level, anchor, Markup(text)))
     return '<h%d id="%s">%s</h%d>' % (level, anchor, text, level)
Esempio n. 20
0
def theme_quickstart(defaults=None, project=None):
    if defaults is None:
        defaults = {}

    g = Generator("theme")

    theme_name = defaults.get("theme_name")
    if theme_name is None:
        theme_name = g.prompt(
            "Theme Name",
            default=None,
            info="This is the human readable name for this theme",
        )

    theme_id = theme_name.lower()  # pylint: disable=no-member
    if theme_id != "lektor" and theme_id.startswith("lektor"):
        theme_id = theme_id[6:].strip()
    if theme_id != "theme" and theme_id.startswith("theme"):
        theme_id = theme_id[5:]
    if theme_id != "theme" and theme_id.endswith("theme"):
        theme_id = theme_id[:-5]
    theme_id = slugify(theme_id)

    path = defaults.get("path")
    if path is None:
        if project is not None:
            default_path = os.path.join(project.tree, "themes",
                                        "lektor-theme-{}".format(theme_id))
        else:
            if len(os.listdir(".")) == 0:
                default_path = os.getcwd()
            else:
                default_path = os.path.join(os.getcwd(), theme_id)
        path = g.prompt(
            "Theme Path",
            default_path,
            "The place where you want to initialize the theme",
        )

    author_name = g.prompt(
        "Author Name",
        get_default_author(),
        "Your name as it will be embedded in the theme metadata.",
    )

    author_email = g.prompt(
        "Author E-Mail",
        get_default_author_email(),
        "Your e-mail address for the theme info.",
    )

    g.confirm("Create Theme?")

    g.run(
        {
            "theme_name": theme_name,
            "theme_id": theme_id,
            "author_name": author_name,
            "author_email": author_email,
        },
        path,
    )

    # symlink
    theme_dir = os.getcwd()
    example_themes = os.path.join(path, "example-site/themes")
    os.makedirs(example_themes)
    os.chdir(example_themes)
    try:
        os.symlink(
            "../../../lektor-theme-{}".format(theme_id),
            "lektor-theme-{}".format(theme_id),
        )
    except AttributeError:
        g.warn(
            "Could not automatically make a symlink to have your example-site"
            "easily pick up your theme.")
    os.chdir(theme_dir)

    # Sample image
    os.makedirs(os.path.join(path, "images"))
    source_image_path = os.path.join(
        os.path.dirname(os.path.realpath(__file__)),
        "quickstart-templates/theme/images/homepage.png",
    )
    destination_image_path = os.path.join(path, "images/homepage.png")
    with open(source_image_path, "rb") as f:
        image = f.read()
    with open(destination_image_path, "wb") as f:
        f.write(image)
Esempio n. 21
0
def plugin_quickstart(defaults=None, project=None):
    if defaults is None:
        defaults = {}

    g = Generator("plugin")

    plugin_name = defaults.get("plugin_name")
    if plugin_name is None:
        plugin_name = g.prompt(
            "Plugin Name",
            default=None,
            info="This is the human readable name for this plugin",
        )

    plugin_id = plugin_name.lower()  # pylint: disable=no-member
    if plugin_id.startswith("lektor"):
        plugin_id = plugin_id[6:]
    if plugin_id.endswith("plugin"):
        plugin_id = plugin_id[:-6]
    plugin_id = slugify(plugin_id)

    path = defaults.get("path")
    if path is None:
        if project is not None:
            default_path = os.path.join(project.tree, "packages", plugin_id)
        else:
            if len(os.listdir(".")) == 0:
                default_path = os.getcwd()
            else:
                default_path = os.path.join(os.getcwd(), plugin_id)
        path = g.prompt(
            "Plugin Path",
            default_path,
            "The place where you want to initialize the plugin",
        )

    author_name = g.prompt(
        "Author Name",
        get_default_author(),
        "Your name as it will be embedded in the plugin metadata.",
    )

    author_email = g.prompt(
        "Author E-Mail",
        get_default_author_email(),
        "Your e-mail address for the plugin info.",
    )

    g.confirm("Create Plugin?")

    g.run(
        {
            "plugin_name": plugin_name,
            "plugin_id": plugin_id,
            "plugin_class": plugin_id.title().replace("-", "") + "Plugin",
            "plugin_module": "lektor_" + plugin_id.replace("-", "_"),
            "author_name": author_name,
            "author_email": author_email,
        },
        path,
    )
Esempio n. 22
0
def project_quickstart(defaults=None):
    if not defaults:
        defaults = {}

    g = Generator("project")

    g.title("Lektor Quickstart")
    g.text("This wizard will generate a new basic project with some sensible "
           "defaults for getting started quickly.  We just need to go through "
           "a few questions so that the project is set up correctly for you.")

    name = defaults.get("name")
    if name is None:
        name = g.prompt(
            "Project Name",
            None,
            "A project needs a name.  The name is primarily used for the admin "
            "UI and some other places to refer to your project to not get "
            "confused if multiple projects exist.  You can change this at "
            "any later point.",
        )

    author_name = g.prompt(
        "Author Name",
        get_default_author(),
        "Your name.  This is used in a few places in the default template "
        "to refer to in the default copyright messages.",
    )

    path = defaults.get("path")
    if path is None:
        here = os.path.abspath(os.getcwd())
        default_project_path = None
        try:
            if len(os.listdir(here)) == []:
                default_project_path = here
        except OSError:
            pass
        if default_project_path is None:
            default_project_path = os.path.join(os.getcwd(), name)
        path = g.prompt(
            "Project Path",
            default_project_path,
            "This is the path where the project will be located.  You can "
            "move a project around later if you do not like the path.  If "
            "you provide a relative path it will be relative to the working "
            "directory.",
        )
        path = os.path.expanduser(path)

    with_blog = g.prompt(
        "Add Basic Blog",
        True,
        "Do you want to generate a basic blog module?  If you enable this "
        "the models for a very basic blog will be generated.",
    )

    g.confirm("That's all. Create project?")

    g.run(
        {
            "project_name": name,
            "project_slug": slugify(name),
            "project_path": path,
            "with_blog": with_blog,
            "this_year": datetime.utcnow().year,
            "today": datetime.utcnow().strftime("%Y-%m-%d"),
            "author_name": author_name,
        },
        path,
    )
Esempio n. 23
0
def test_slugify():

    assert slugify("w o w") == "w-o-w"
    assert slugify(u"Șö prĕtty") == "so-pretty"
    assert slugify("im age.jpg") == "im-age.jpg"
    assert slugify("slashed/slug") == "slashed/slug"
Esempio n. 24
0
def theme_quickstart(defaults=None, project=None):
    if defaults is None:
        defaults = {}

    g = Generator("theme")

    theme_name = defaults.get("theme_name")
    if theme_name is None:
        theme_name = g.prompt(
            "Theme Name",
            default=None,
            info="This is the human readable name for this theme",
        )

    theme_id = theme_name.lower()
    if theme_id != "lektor" and theme_id.startswith("lektor"):
        theme_id = theme_id[6:].strip()
    if theme_id != "theme" and theme_id.startswith("theme"):
        theme_id = theme_id[5:]
    if theme_id != "theme" and theme_id.endswith("theme"):
        theme_id = theme_id[:-5]
    theme_id = slugify(theme_id)

    path = defaults.get("path")
    if path is None:
        if project is not None:
            default_path = os.path.join(project.tree, "themes",
                                        "lektor-theme-{}".format(theme_id))
        else:
            if len(os.listdir(".")) == 0:
                default_path = os.getcwd()
            else:
                default_path = os.path.join(os.getcwd(), theme_id)
        path = g.prompt(
            "Theme Path",
            default_path,
            "The place where you want to initialize the theme",
        )

    author_name = g.prompt(
        "Author Name",
        get_default_author(),
        "Your name as it will be embedded in the theme metadata.",
    )

    author_email = g.prompt(
        "Author E-Mail",
        get_default_author_email(),
        "Your e-mail address for the theme info.",
    )

    g.confirm("Create Theme?")

    g.run(
        {
            "theme_name": theme_name,
            "theme_id": theme_id,
            "author_name": author_name,
            "author_email": author_email,
        },
        path,
    )

    # symlink
    theme_dir = os.getcwd()
    example_themes = os.path.join(path, "example-site/themes")
    os.makedirs(example_themes)
    os.chdir(example_themes)
    try:
        os.symlink(
            "../../../lektor-theme-{}".format(theme_id),
            "lektor-theme-{}".format(theme_id),
        )
    except OSError as exc:
        # Windows, by default, only allows members of the "Administrators" group
        # to create symlinks. For users who are not allowed to create symlinks,
        # error Code 1314 - "A required privilege is not held by the client"
        # is raised.
        if getattr(exc, "winerror", None) != 1314:
            raise
        g.warn(
            "Could not automatically make a symlink to have your example-site"
            "easily pick up your theme.")
    os.chdir(theme_dir)

    # Sample image
    os.makedirs(os.path.join(path, "images"))
    source_image_path = os.path.join(
        os.path.dirname(os.path.realpath(__file__)),
        "quickstart-templates/theme/images/homepage.png",
    )
    destination_image_path = os.path.join(path, "images/homepage.png")
    with open(source_image_path, "rb") as f:
        image = f.read()
    with open(destination_image_path, "wb") as f:
        f.write(image)