# -*- coding: utf-8 -*-
"""
Extension that creates a base structure for the project using django-admin.
Warning:
*Deprecation Notice* - In the next major release the Django extension
will be extracted into an independent package.
After PyScaffold v4.0, you will need to explicitly install
``pyscaffoldext-django`` in your system/virtualenv in order to be
able to use it.
"""
import os
import shutil
from os.path import join as join_path
from .. import shell
from ..api import Extension, helpers
from ..warnings import UpdateNotSupported
class Django(Extension):
"""Generate Django project files"""
mutually_exclusive = True
def activate(self, actions):
"""Register hooks to generate project using django-admin.
Args:
actions (list): list of actions to perform
Returns:
list: updated list of actions
"""
# `get_default_options` uses passed options to compute derived ones,
# so it is better to prepend actions that modify options.
actions = helpers.register(
actions, enforce_django_options, before="get_default_options"
)
# `apply_update_rules` uses CWD information,
# so it is better to prepend actions that modify it.
actions = helpers.register(
actions, create_django_proj, before="apply_update_rules"
)
return actions
def enforce_django_options(struct, opts):
"""Make sure options reflect the Django usage.
Args:
struct (dict): project representation as (possibly) nested
:obj:`dict`.
opts (dict): given options, see :obj:`create_project` for
an extensive list.
Returns:
struct, opts: updated project representation and options
"""
opts["package"] = opts["project"] # required by Django
opts["force"] = True
opts.setdefault("requirements", []).append("django")
return struct, opts
def create_django_proj(struct, opts):
"""Creates a standard Django project with django-admin
Args:
struct (dict): project representation as (possibly) nested
:obj:`dict`.
opts (dict): given options, see :obj:`create_project` for
an extensive list.
Returns:
struct, opts: updated project representation and options
Raises:
:obj:`RuntimeError`: raised if django-admin is not installed
"""
if opts.get("update"):
helpers.logger.warning(UpdateNotSupported(extension="django"))
return struct, opts
try:
shell.django_admin("--version")
except Exception as e:
raise DjangoAdminNotInstalled from e
pretend = opts.get("pretend")
shell.django_admin("startproject", opts["project"], log=True, pretend=pretend)
if not pretend:
src_dir = join_path(opts["project"], "src")
os.mkdir(src_dir)
shutil.move(
join_path(opts["project"], opts["project"]),
join_path(src_dir, opts["package"]),
)
return struct, opts
class DjangoAdminNotInstalled(RuntimeError):
"""This extension depends on the ``django-admin`` cli script."""
DEFAULT_MESSAGE = "django-admin is not installed, " "run: pip install django"
def __init__(self, message=DEFAULT_MESSAGE, *args, **kwargs):
super(DjangoAdminNotInstalled, self).__init__(message, *args, **kwargs)