# Generate a Pyramid Project with a Python Script that Interacts with the Cookiecutter REPL.

### Generate a Pyramid project using a Python script to interact with Cookiecutter via Pexpect.¶

We will create a Pyramid project in your home directory for Unix or at the root for Windows. It is assumed you know the path to where you installed cookiecutter. Issue the following commands and override the defaults in the prompts as follows.

I originally attempted to open a subprocess with subprocess.Popen and then communicate with the process. I learned from this stackoverflow answer that it gets complicated with a REPL situation.

In [3]:
import tempfile
from pathlib import Path
import os
import pickle

from IPython.display import display, HTML

BASE_DIR = Path(Path.home(), 'scratch')
PROJECT_NAME = 'pyramid_practice'
PREFIX = f'{PROJECT_NAME}_'
WORKING_DIR_NAME = tempfile.mkdtemp(prefix=PREFIX, dir=BASE_DIR)
WORKING_DIR = BASE_DIR.joinpath(WORKING_DIR_NAME)
assert WORKING_DIR.exists(), "No working directory exists."

# Save WORKING_DIR value in a pickle to use in another blog post.
Path('working_dir.pk').write_bytes(pickle.dumps(WORKING_DIR))

Out[3]:
98

### Use Cookiecutter and Pexpect to scaffold the project¶

#### Update¶

The purpose of this exercise was to practice pexpect.

In [4]:
import pexpect

RETURN_KEY = 'return_key'
DEFAULT, TWO = '\n', '2'
inputs = dict(
default=DEFAULT,
project_name=PROJECT_NAME,
repo_name=DEFAULT,
template_lang=TWO, # Chameleon
orm=TWO, # SQLAlchemy
)

os.chdir(WORKING_DIR)
child = pexpect.spawnu(command)
EXPECTED = ']:'
print(f'working directory: {Path(os.curdir).absolute().parts[-1]}')
for value in inputs.values():
child.expect(EXPECTED)
if child.before:
display(HTML((f'<h3>{child.before}{EXPECTED}<h3>')))
child.sendline(value)
display(HTML((f'<h4>sending "{value.strip() or RETURN_KEY}"<h4>')))

assert not child.wait(), "There was an error in the subprocess."

working directory: pyramid_practice_y2bz1v0h


#### Select backend: 1 - none 2 - sqlalchemy 3 - zodb Choose from 1, 2, 3 (1, 2, 3) [1]:

##### sending "2"
In [5]:
for base, dirs, files in os.walk(WORKING_DIR):
for dir_ in dirs:
for file in files:
print(Path(*Path(base, dir_, file).parts[-2:]))

pyramid_practice/pytest.ini
pyramid_practice/CHANGES.txt
pyramid_practice/.gitignore
pyramid_practice/setup.py
pyramid_practice/MANIFEST.in
pyramid_practice/production.ini
pyramid_practice/development.ini
pyramid_practice/.coveragerc
static/routes.py
static/tests.py
static/__init__.py
templates/routes.py
templates/tests.py
templates/__init__.py
views/routes.py
views/tests.py
views/__init__.py