Skip to content

Commit

Permalink
Make it more backward compatible
Browse files Browse the repository at this point in the history
  • Loading branch information
abravalheri committed Jul 9, 2020
1 parent 3978ce0 commit 7c0fd7b
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 14 deletions.
1 change: 1 addition & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ norecursedirs =
.tox
testpaths = tests
markers =
only: use '-m only' to run a specific test
slow: mark tests as slow (deselect with '-m "not slow"')
system: mark system tests

Expand Down
44 changes: 40 additions & 4 deletions src/pyscaffoldext/cookiecutter/extension.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,56 @@ class Cookiecutter(Extension):

mutually_exclusive = True

try:
# TODO: Remove this try/except block on PyScaffold >= 4.x
from pyscaffold.extensions import cookiecutter # Check if builtin existis

del cookiecutter

# WORKAROUND:
#
# This avoids raising an error by using `add_argument` with an
# option/flag that was already used and at the same time provides
# a unequivocal way of accessing the newest implementation in the
# tests via the `--x-` prefix.
#
# For the time being this is useful to run against an existing
# version of PyScaffold that have an old implementation of this
# extension built into the core of the system.

@property
def xhelp(self):
return ("Newest version of `{}`, in development".format(self.flag),)

@property
def xflag(self):
return "--x-" + self.flag.strip("-")

except ImportError:
pass # Never mind, we are in a recent version of PyScaffold

def augment_cli(self, parser):
"""Add an option to parser that enables the Cookiecutter extension
Args:
parser (argparse.ArgumentParser): CLI parser object
"""
# TODO: Simplify the x stuff for PyScaffold >= 4.x
flag = getattr(self, "xflag", self.flag)
help = getattr(
self,
"xhelp",
"additionally apply a Cookiecutter template. "
"Note that not all templates are suitable for PyScaffold. "
"Please refer to the docs for more information.",
)

parser.add_argument(
self.flag,
flag,
dest=self.name,
action=create_cookiecutter_parser(self),
metavar="TEMPLATE",
help="additionally apply a Cookiecutter template. "
"Note that not all templates are suitable for PyScaffold. "
"Please refer to the docs for more information.",
help=help,
)

def activate(self, actions):
Expand Down
24 changes: 22 additions & 2 deletions tests/system/helpers.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
# -*- coding: utf-8 -*-
import shlex
import sys
import traceback
from os import environ
from subprocess import STDOUT, check_output
from subprocess import STDOUT, CalledProcessError, check_output
from uuid import uuid4


def uniqstr():
"""Generates a unique random long string every time it is called"""
return str(uuid4()).replace("-", "")


def run(*args, **kwargs):
Expand All @@ -12,10 +20,22 @@ def run(*args, **kwargs):
else:
args = args[0]

if args[0] == "python" and sys.platform != "win32":
args[0] += str(sys.version_info[0])

opts = dict(stderr=STDOUT, universal_newlines=True)
opts.update(kwargs)

return check_output(args, **opts)
try:
output = check_output(args, **opts)
print("command: ", args, opts)
print("output: ", output)
return output
except CalledProcessError as ex:
traceback.print_exc()
msg = "******************** Terminal ($? = {}) ********************\n{}"
print(msg.format(ex.returncode, ex.output))
raise


def run_common_tasks(tests=True, flake8=True):
Expand Down
7 changes: 6 additions & 1 deletion tests/system/test_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,17 @@

import pytest

from pyscaffoldext.cookiecutter.extension import Cookiecutter

from .helpers import run, run_common_tasks

pytestmark = [pytest.mark.slow, pytest.mark.system]

COOKIECUTTER = "https://github.com/pyscaffold/cookiecutter-pypackage.git"

# TODO: Remove workaround for PyScaffold <= 4.x, see comments on class
FLAG = (lambda ext: getattr(ext, "xflag", ext.flag))(Cookiecutter("cookiecutter"))


def is_venv():
"""Check if the tests are running inside a venv"""
Expand Down Expand Up @@ -37,7 +42,7 @@ def test_ensure_inside_test_venv():
def test_namespace_cookiecutter(cwd):
# Given pyscaffold is installed,
# when we call putup with --namespace and --cookiecutter
run("putup myproj --namespace nested.ns --cookiecutter " + COOKIECUTTER)
run("putup myproj --namespace nested.ns {} {}".format(FLAG, COOKIECUTTER))
# then a very complicated module hierarchy should exist
assert isdir("myproj/src/nested/ns/myproj")
# and all the common tasks should run properly
Expand Down
18 changes: 12 additions & 6 deletions tests/test_cookiecutter.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,17 @@
COOKIECUTTER_URL = "https://github.com/pyscaffold/cookiecutter-pypackage.git"
COOKIECUTTER_FILES = ["proj/Makefile", "proj/.github/ISSUE_TEMPLATE.md"]

# TODO: Remove workaround for PyScaffold <= 4.x, see comments on class
FLAG = (lambda ext: getattr(ext, "xflag", ext.flag))(Cookiecutter("cookiecutter"))


@pytest.mark.slow
def test_create_project_with_cookiecutter(tmpfolder):
# Given options with the cookiecutter extension,
opts = dict(
project=PROJ_NAME,
package=PROJ_NAME,
version="0.0.1",
cookiecutter=COOKIECUTTER_URL,
extensions=[Cookiecutter("cookiecutter")],
)
Expand All @@ -41,13 +46,14 @@ def test_create_project_with_cookiecutter(tmpfolder):
for path in COOKIECUTTER_FILES:
assert path_exists(path)
# and also overwritable pyscaffold files (with the exact contents)
tmpfolder.join(PROJ_NAME).join("setup.py").read() == setup_py(opts)
existing_setup = tmpfolder.join(PROJ_NAME).join("setup.py").read()
assert existing_setup == setup_py(opts)


def test_pretend_create_project_with_cookiecutter(tmpfolder, caplog):
# Given options with the cookiecutter extension,
caplog.set_level(logging.INFO)
opts = parse_args([PROJ_NAME, "--pretend", "--cookiecutter", COOKIECUTTER_URL])
opts = parse_args([PROJ_NAME, "--pretend", FLAG, COOKIECUTTER_URL])
opts = process_opts(opts)

# when the project is created,
Expand Down Expand Up @@ -125,7 +131,7 @@ def test_create_project_cookiecutter_and_update(tmpfolder, capsys):
@pytest.mark.slow
def test_cli_with_cookiecutter(tmpfolder):
# Given the command line with the cookiecutter option,
sys.argv = ["pyscaffold", PROJ_NAME, "--cookiecutter", COOKIECUTTER_URL]
sys.argv = ["pyscaffold", PROJ_NAME, FLAG, COOKIECUTTER_URL]

# when pyscaffold runs,
run()
Expand All @@ -137,7 +143,7 @@ def test_cli_with_cookiecutter(tmpfolder):

def test_cli_with_cookiecutter_but_no_template(tmpfolder, capsys):
# Given the command line with the cookiecutter option, but no template
sys.argv = ["pyscaffold", PROJ_NAME, "--cookiecutter"]
sys.argv = ["pyscaffold", PROJ_NAME, FLAG]

# when pyscaffold runs,
# then an exception should be raised.
Expand All @@ -146,7 +152,7 @@ def test_cli_with_cookiecutter_but_no_template(tmpfolder, capsys):

# make sure the exception is related to the missing argument
out, err = capsys.readouterr()
assert "--cookiecutter: expected one argument" in out + err
assert "{}: expected one argument".format(FLAG) in out + err


def test_cli_without_cookiecutter(tmpfolder):
Expand All @@ -167,7 +173,7 @@ def test_cli_with_cookiecutter_and_update(tmpfolder, capsys):

# when the project is updated
# with the cookiecutter extension,
sys.argv = ["pyscaffold", PROJ_NAME, "--update", "--cookiecutter", COOKIECUTTER_URL]
sys.argv = ["pyscaffold", PROJ_NAME, "--update", FLAG, COOKIECUTTER_URL]
run()

# then a warning should be displayed
Expand Down
4 changes: 3 additions & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ envlist = default

[testenv]
description = run test suite with pytest
setenv = TOXINIDIR = {toxinidir}
setenv =
TOXINIDIR = {toxinidir}
passenv =
HOME
commands =
Expand All @@ -18,6 +19,7 @@ extras =

[testenv:docs]
description = invoke sphinx-build to build the HTML docs
skipsdist = true
deps = -r {toxinidir}/docs/requirements.txt
whitelist_externals = make
changedir = {toxinidir}/docs
Expand Down

0 comments on commit 7c0fd7b

Please sign in to comment.