Skip to content

Commit

Permalink
leverage pathlib; remove mustache template support
Browse files Browse the repository at this point in the history
  • Loading branch information
sheppard committed Jun 16, 2023
1 parent c96c34c commit 9ac667a
Showing 1 changed file with 68 additions and 94 deletions.
162 changes: 68 additions & 94 deletions wq/create/forms.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
from wq.build import wq
import click
import os
from xlsconv import parse_xls, xls2django, xls2html, html_context, render
from xlsconv import parse_xls, xls2django
import subprocess
import json
from difflib import unified_diff
from pyxform.question_type_dictionary import QUESTION_TYPE_DICT as QTYPES
import pathlib


@wq.command()
Expand All @@ -14,25 +15,15 @@
required=True,
type=click.Path(exists=True),
)
@click.option(
"--input-dir",
type=click.Path(exists=True),
help="Source / master templates",
)
@click.option(
"--django-dir",
default=".",
type=click.Path(exists=True),
type=click.Path(exists=True, path_type=pathlib.Path),
help="Root of Django project",
)
@click.option(
"--template-dir",
type=click.Path(exists=True),
help="Path to shared template directory",
)
@click.option(
"--form-name",
help="Name to use for Django app and template prefix",
help="Name to use for Django app package directory",
)
@click.option(
"--with-admin/--no-admin",
Expand All @@ -53,9 +44,7 @@
)
def addform(
xlsform,
input_dir,
django_dir,
template_dir,
form_name,
with_admin,
with_wizard,
Expand All @@ -68,40 +57,45 @@ def addform(
\b
db/[form_name]/models.py
db/[form_name]/rest.py
templates/[form_name]_detail.html (if applicable)
templates/[form_name]_edit.html (if applicable)
templates/[form_name]_list.html (if applicable)
Note that Mustache templates are only used for projects generated with
wq.start 1.2 and earlier, which use the @wq/jquery-mobile renderer.
Newer projects leverage the @wq/react + @wq/material renderer, which uses
React components instead of Mustache templates.
db/[form_name]/serializers.py (if applicable)
db/[form_name]/admin.py (if requested)
db/[form_name]/wizard.py (if requested)
"""

manage_py = django_dir / "manage.py"

if django_dir == pathlib.Path("."):
if not manage_py.exists():
if (django_dir / "db" / "manage.py").exists():
django_dir = django_dir / "db"
manage_py = django_dir / "manage.py"
else:
raise click.ClickException(
"Could not find manage.py in current directory. Try specifying --django-dir"
)

xls_json = parse_xls(xlsform)
if not form_name:
form_name = xls_json["name"]

if not os.path.exists(os.path.join(django_dir, form_name)):
os.mkdir(os.path.join(django_dir, form_name))

if not os.path.exists(os.path.join(django_dir, form_name, "migrations")):
os.mkdir(os.path.join(django_dir, form_name, "migrations"))
form_dir = django_dir / form_name
form_dir.mkdir(exist_ok=True)
(form_dir / "migrations").mkdir(exist_ok=True)

create_file(
[django_dir, form_name, "__init__.py"],
form_dir / "__init__.py",
"",
overwrite=force,
)

create_file(
[django_dir, form_name, "migrations", "__init__.py"],
form_dir / "migrations" / "__init__.py",
"",
overwrite=force,
)

create_file(
[django_dir, form_name, "models.py"],
form_dir / "models.py",
xls2django(xlsform, "models"),
overwrite=force,
)
Expand All @@ -112,155 +106,135 @@ def addform(
has_nested = True
if has_nested:
create_file(
[django_dir, form_name, "serializers.py"],
form_dir / "serializers.py",
xls2django(xlsform, "serializers"),
overwrite=force,
)

create_file(
[django_dir, form_name, "rest.py"],
form_dir / "rest.py",
xls2django(xlsform, "rest"),
overwrite=force,
)
if with_admin:
create_file(
[django_dir, form_name, "admin.py"],
form_dir / "admin.py",
xls2django(xlsform, "admin"),
overwrite=force,
)
if with_wizard:
create_file(
[django_dir, form_name, "wizard.py"],
form_dir / "wizard.py",
xls2django(xlsform, "wizard"),
overwrite=force,
)

if not input_dir and os.path.exists("../master_templates"):
input_dir = "../master_templates"
settings_paths = sorted(django_dir.glob("**/settings.py"))
if not settings_paths:
settings_paths = sorted(django_dir.glob("**/settings/base.py"))

if not template_dir and os.path.exists("../templates"):
template_dir = "../templates"

if input_dir and template_dir:
template_types = set(["detail", "edit", "list"])
for field in xls_json["children"]:
if "geo" in field["type"]:
if "popup" in template_types:
print("Warning: multiple geometry fields found.")
template_types.add("popup")
for tmpl in template_types:
create_file(
[template_dir, "%s_%s.html" % (form_name, tmpl)],
xls2html(xlsform, os.path.join(input_dir, "%s.html" % tmpl)),
overwrite=force,
)

settings_path = None
for path, dirs, files in os.walk(django_dir):
for filename in files:
if filename == "settings.py":
settings_path = (path, filename)
elif path.endswith("/settings") and filename == "base.py":
settings_path = (path[:-9], "settings", filename)

if not settings_path:
if not settings_paths:
click.echo("Warning: No settings found in Django directory.")
return

settings_path = settings_paths[0]

new_settings = []
app_section = False
has_app = False
for row in open(os.path.join(*settings_path)):
for row in settings_path.read_text().split(os.linesep):
if "INSTALLED_APPS" in row:
app_section = True
elif app_section:
if ")" in row or "]" in row:
app_section = False
if not has_app:
new_settings.append(
" '%s',%s" % (form_name, os.linesep)
)
new_settings.append(f' "{form_name}",')
else:
if '"%s"' % form_name in row or "'%s'" % form_name in row:
if f'"{form_name}"' in row or f"'{form_name}'" in row:
has_app = True
new_settings.append(row)
create_file(
settings_path, "".join(new_settings), overwrite=force, show_diff=True
settings_path,
os.linesep.join(new_settings),
overwrite=force,
show_diff=True,
)
if not manage_py.exists():
click.echo("Warning: No manage.py found in Django directory.")
return

result = (
subprocess.check_output(
[os.path.join(django_dir, "manage.py"), "makemigrations"]
)
subprocess.check_output([manage_py, "makemigrations"])
.decode("utf-8")
.strip()
)
print(result)
click.echo(result)
if "No changes" in result:
return
migrate = force or click.confirm("Update database schema?", default=True)
if not migrate:
return
subprocess.call([os.path.join(django_dir, "manage.py"), "migrate"])
subprocess.call([manage_py, "migrate"])


def create_file(
path, contents, overwrite=False, show_diff=False, previous_diff=False
):
filename = os.path.join(*path)
has_diff = previous_diff
if os.path.exists(filename) and not overwrite:
existing_file = open(filename, "r")
existing_content = existing_file.read()
path_label = f"{path.parent.name}/{path.name}"

if path.exists() and not overwrite:
existing_content = path.read_text()
if existing_content.strip() == contents.strip():
return False

def print_diff():
diff = unified_diff(
existing_content.split("\n"),
contents.split("\n"),
fromfile="%s (current)" % path[-1],
tofile="%s (new)" % path[-1],
fromfile=f"{path_label} (current)",
tofile=f"{path_label} (new)",
)
for row in diff:
print(row)
click.echo(row)

if show_diff:
print_diff()
message = "Update %s? [Y/n/d/?]"
message = f"Update {path_label}? [Y/n/d/?]"
default_choice = "y"
else:
if not previous_diff:
choice = click.prompt("Update templates? [y/n]")
choice = click.prompt(
f"{path.parent.name} package already exists; update modules? [y/n]"
)
if choice.lower() != "y":
print("Skipping template updates.")
click.echo("Skipping module updates.")
return "skipall"

message = "%s already exists; overwrite? [y/n/d/?]"
message = f"{path_label} already exists; overwrite? [y/n/d/?]"
default_choice = None

has_diff = True
choice = ""
while choice.lower() not in ("y", "n"):
if path[-2] == "settings":
filename = os.path.join(*path[-2:])
else:
filename = path[-1]
choice = click.prompt(
message % filename, default=default_choice, show_default=False
message,
default=default_choice,
show_default=False,
)
if choice == "" and show_diff:
choice = "y"
if choice.lower() == "n":
return has_diff
elif choice.lower() == "?":
print(
click.echo(
" y - overwrite\n"
" n - skip\n"
" d - show diff\n"
" ? - show help"
)
elif choice.lower() == "d":
print_diff()
out = open(os.path.join(*path), "w")
out.write(contents)
out.close()
path.write_text(contents)
return has_diff

0 comments on commit 9ac667a

Please sign in to comment.