Skip to content

Commit

Permalink
[generate] code refine for generate_function and test cases
Browse files Browse the repository at this point in the history
New helper function add: generate_vendor
  • Loading branch information
iblislin committed Jun 7, 2016
1 parent 8cdbb7b commit abdf0e7
Show file tree
Hide file tree
Showing 2 changed files with 175 additions and 49 deletions.
140 changes: 93 additions & 47 deletions couchapp/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import os
import sys

from shutil import copy2, copytree
from shutil import Error, copy2, copytree

from couchapp import localdoc
from couchapp.errors import AppError
Expand Down Expand Up @@ -122,54 +122,100 @@ def init_template(path, template='default'):
localdoc.document(path, create=True)


def generate_function(path, kind, name, template=None):
functions_path = ['functions']
if template:
functions_path = []
_relpath = os.path.join(*template.split('/'))
template_dir = find_template_dir(_relpath)
def generate_function(path, func_type, name, template='default'):
'''
Generate function from template
:param path: the app dir
:param func_type: function type. e.g. ``view``, ``show``.
:param name: the function name
:param template: the template set
The big picture of template dir is discribed
in :py:func:`~couchapp.generate.init_template`.
Here we show the detail structure of ``functions`` dir::
functions/
filter.js
list.js
map.js
reduce.js
show.js
spatial.js
update.js
validate_doc_update.js
...
myfunc.js
'''
tmpl_name = os.path.join(*template.split('/'))
tmpl_dir = find_template_dir(tmpl_name, tmpl_type='functions',
raise_error=True)

file_list = [] # [(src, dest), ...]
empty_dir = False
if func_type == 'view':
dir_ = os.path.join(path, 'views', name)
empty_dir = True
file_list.append(('map.js', 'map.js'))
file_list.append(('reduce.js', 'reduce.js'))

elif func_type in ('filter', 'list', 'show', 'update'):
dir_ = os.path.join(path, '{0}s'.format(func_type))
file_list.append(('{0}.js'.format(func_type),
'{0}.js'.format(name)))

elif func_type == 'function': # user defined function
dir_ = path
file_list.append(('{0}.js'.format(name),
'{0}.js'.format(name)))

elif func_type == 'spatial':
dir_ = os.path.join(path, 'spatial')
file_list.append(('spatial.js', '{0}.js'.format(name)))

elif func_type == 'validate_doc_update':
dir_ = path
file_list.append(('validate_doc_update.js', 'validate_doc_update.js'))

else:
template_dir = find_template_dir()
if template_dir:
functions = []
if kind == "view":
path = os.path.join(path, "%ss" % kind, name)
if os.path.exists(path):
raise AppError("The view %s already exists" % name)
functions = [('map.js', 'map.js'), ('reduce.js', 'reduce.js')]
elif kind == "function":
functions = [('%s.js' % name, '%s.js' % name)]
elif kind == "vendor":
app_dir = os.path.join(path, "vendor", name)
try:
os.makedirs(app_dir)
except:
pass
targetpath = os.path.join(*template.split('/'))
copy_helper(path, targetpath)
return
elif kind == "spatial":
path = os.path.join(path, "spatial")
functions = [("spatial.js", "%s.js" % name)]
else:
path = os.path.join(path, "%ss" % kind)
functions = [('%s.js' % kind, "%s.js" % name)]
raise AppError('unrecognized function type "{0}"'.format(func_type))

setup_dir(dir_, require_empty=empty_dir)

for src, dest in file_list:
full_src = os.path.join(tmpl_dir, src)
full_dest = os.path.join(dir_, dest)

try:
os.makedirs(path)
except:
pass

for template, target in functions:
target_path = os.path.join(path, target)
root_path = [template_dir] + functions_path + [template]
root = os.path.join(*root_path)
try:
shutil.copy2(root, target_path)
except:
logger.warning("%s not found in %s" %
(template, os.path.join(*root_path[:-1])))
else:
raise AppError("Defaults templates not found. Check your install.")
copy2(full_src, full_dest)
except Error:
logger.warning('function "%s" not found in "%s"', src, tmpl_dir)
else:
logger.debug('function "%s" generated successfully', dest)

logger.info('enjoy the %s function, "%s"!', func_type, name)


def generate_vendor(path, name, template='default'):
'''
Generate vendor from template set
:param path: the app dir
:param name: the vendor name
:param template: the template set
'''
tmpl_name = os.path.join(*template.split('/'))
tmpl_dir = find_template_dir(tmpl_name, tmpl_type='vendor',
raise_error=True)

vendor_dir = os.path.join(path, 'vendor')
setup_dir(vendor_dir)

copy_helper(tmpl_dir, vendor_dir)

logger.debug('vendor dir "%s"', tmpl_dir)
logger.info('vendor "%s" generated successfully', name)


def copy_helper(src, dest):
Expand Down
84 changes: 82 additions & 2 deletions tests/test_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from couchapp.errors import AppError
from couchapp.generator import copy_helper, find_template_dir
from couchapp.generator import init_basic, init_template, save_id
from couchapp.generator import generate
from couchapp.generator import generate, generate_vendor, generate_function

from mock import patch
from nose.tools import raises, with_setup
Expand Down Expand Up @@ -205,7 +205,7 @@ def _find_dir(*args, **kwargs):

@patch('couchapp.generator.generate_function')
@patch('couchapp.generator.generate_vendor')
def test_generate_functions(gen_vendor, gen_func):
def test_generate_dispatch_function(gen_vendor, gen_func):
generate('/mock/app', 'view', 'mock_view', template='default')

assert gen_func.called
Expand All @@ -229,3 +229,83 @@ def test_generate_dispatch_to_vendor(gen_vendor, gen_func):

assert not gen_func.called
assert gen_vendor.called


@patch('couchapp.generator.copy_helper')
@patch('couchapp.generator.setup_dir')
@patch('couchapp.generator.find_template_dir', return_value='/vendor/boostrap')
def test_generate_vendor(find_template_dir, setup_dir, copy_helper):
generate_vendor('/app', 'boostrap')

assert find_template_dir.called
setup_dir.assert_called_with('/app/vendor')
copy_helper.assert_called_with('/vendor/boostrap', '/app/vendor')


@patch('couchapp.generator.copy2')
@patch('couchapp.generator.setup_dir')
@patch('couchapp.generator.find_template_dir', return_value='/funcs/view')
def test_generate_function_view(find_template_dir, setup_dir, copy2):
generate_function('/app', 'view', 'mock')

assert find_template_dir.called
setup_dir.assert_called_with('/app/views/mock', require_empty=True)
copy2.assert_any_call('/funcs/view/map.js', '/app/views/mock/map.js')
copy2.assert_any_call('/funcs/view/reduce.js', '/app/views/mock/reduce.js')


@patch('couchapp.generator.copy2')
@patch('couchapp.generator.setup_dir')
@patch('couchapp.generator.find_template_dir', return_value='/funcs')
def test_generate_function_list(find_template_dir, setup_dir, copy2):
generate_function('/app', 'list', 'mock')

assert find_template_dir.called
setup_dir.assert_called_with('/app/lists', require_empty=False)
copy2.assert_called_with('/funcs/list.js', '/app/lists/mock.js')


@patch('couchapp.generator.copy2')
@patch('couchapp.generator.setup_dir')
@patch('couchapp.generator.find_template_dir', return_value='/funcs')
def test_generate_function_user_func(find_template_dir, setup_dir, copy2):
generate_function('/app', 'function', 'mock')

assert find_template_dir.called
setup_dir.assert_called_with('/app', require_empty=False)
copy2.assert_called_with('/funcs/mock.js', '/app/mock.js')


@patch('couchapp.generator.copy2')
@patch('couchapp.generator.setup_dir')
@patch('couchapp.generator.find_template_dir', return_value='/funcs')
def test_generate_function_spatial(find_template_dir, setup_dir, copy2):
generate_function('/app', 'spatial', 'mock')

assert find_template_dir.called
setup_dir.assert_called_with('/app/spatial', require_empty=False)
copy2.assert_called_with('/funcs/spatial.js', '/app/spatial/mock.js')


@patch('couchapp.generator.copy2')
@patch('couchapp.generator.setup_dir')
@patch('couchapp.generator.find_template_dir', return_value='/funcs')
def test_generate_function_validate_doc(find_template_dir, setup_dir, copy2):
generate_function('/app', 'validate_doc_update', 'mock')

assert find_template_dir.called
setup_dir.assert_called_with('/app', require_empty=False)
copy2.assert_called_with('/funcs/validate_doc_update.js',
'/app/validate_doc_update.js')


@raises(AppError)
@patch('couchapp.generator.copy2')
@patch('couchapp.generator.setup_dir')
@patch('couchapp.generator.find_template_dir', return_value='/funcs')
def test_generate_function_unkown(find_template_dir, setup_dir, copy2):
generate_function('/app', 'magic', 'mock')

assert find_template_dir.called
assert not setup_dir.called
assert not copy2.called

0 comments on commit abdf0e7

Please sign in to comment.