Skip to content

Commit

Permalink
Added tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ereOn committed Jan 16, 2016
1 parent e3efa4a commit 7d89f46
Show file tree
Hide file tree
Showing 16 changed files with 639 additions and 22 deletions.
2 changes: 1 addition & 1 deletion dev_requirements.txt
@@ -1,3 +1,3 @@
coverage==3.7.1
coverage==4.0.3
nose==1.3.7
mock==1.3.0
2 changes: 1 addition & 1 deletion pygen/parsers/__init__.py
Expand Up @@ -6,7 +6,7 @@
import pkg_resources
import warnings

from ..exceptions import NoParserError
from .exceptions import NoParserError


def get_parser_class_map():
Expand Down
File renamed without changes.
2 changes: 2 additions & 0 deletions pygen/parsers/json.py
Expand Up @@ -2,6 +2,8 @@
A JSON file parser.
"""

from __future__ import absolute_import

import json

from .base import BaseParser
Expand Down
6 changes: 5 additions & 1 deletion pygen/parsers/yaml.py
Expand Up @@ -2,8 +2,12 @@
A YAML file parser.
"""

from __future__ import absolute_import

import yaml

from six import StringIO

from .base import BaseParser


Expand All @@ -14,4 +18,4 @@ def load(self, file):
return yaml.load(file)

def loads(self, s):
return yaml.loads(s)
return yaml.load(StringIO(s))
21 changes: 19 additions & 2 deletions pygen/scope/__init__.py
Expand Up @@ -14,10 +14,18 @@ def parse_scope(value):
:param value: The dotted path string.
:returns: A `Scope` instance if `value` is a valid path.
"""
if not value:
return Scope()

if not re.match('^[\w\d_-]+(\.[\w\d_-]+)*$', value):
raise InvalidScope(value)

return Scope(scope=value.split('.'))
scope = [
int(x) if re.match('^\d+$', x) else x
for x in value.split('.')
]

return Scope(scope=scope)


class Scope(object):
Expand All @@ -30,7 +38,16 @@ def __init__(self, scope=None):
:param scope: A list of path components.
"""
self.scope = scope or []
self.scope = list(scope or [])

def __eq__(self, other):
if not isinstance(other, Scope):
return NotImplemented

return other.scope == self.scope

def __ne__(self, other):
return not self == other

def __repr__(self):
return 'Scope(%r)' % self.scope
Expand Down
19 changes: 6 additions & 13 deletions pygen/scripts.py
Expand Up @@ -4,6 +4,7 @@

import click
import os
import yaml

from .parsers import parse_file
from .templates import TemplatesManager
Expand All @@ -13,10 +14,6 @@ def hl(obj):
return click.style(str(obj), fg='yellow', bold=True)


def identifier(obj):
return click.style(str(obj), fg='cyan', bold=True)


def pinfo(msg, *args, **kwargs):
click.secho(str(msg).format(*args, **kwargs), fg='white')

Expand All @@ -25,10 +22,6 @@ def pdebug(msg, *args, **kwargs):
click.secho(str(msg).format(*args, **kwargs), fg='black', bold=True)


def perror(msg, *args, **kwargs):
click.secho(str(msg).format(*args, **kwargs), fg='red', bold=True)


@click.command(help="Generate code from a definition file.")
@click.option(
'-d',
Expand Down Expand Up @@ -76,7 +69,7 @@ def pygen(debug, output_root, targets, templates_root, definition_file):
if debug:
pdebug(
"Definition file is as follow:\n{definition}",
definition=definition,
definition=yaml.dump(definition),
)

pinfo(
Expand All @@ -89,13 +82,13 @@ def pygen(debug, output_root, targets, templates_root, definition_file):

try:
os.makedirs(output_root)
except IOError:
except OSError:
pass

if not targets:
targets = templates_manager.default_targets

for index, target_name in enumerate(targets):
for index, target_name in enumerate(sorted(targets)):
progress = float(index) / len(targets)
pinfo(
"[{progress:3d}%] Generating target `{target_name}`.",
Expand All @@ -113,11 +106,11 @@ def pygen(debug, output_root, targets, templates_root, definition_file):
)
pinfo(
"Writing {output_file_name}.",
output_file_name=hl(output_file_name),
output_file_name=hl(output_file_name.replace('\\', '/')),
)

with open(output_file_name, 'w') as destination_file:
destination_file.write(content)
destination_file.write(content) # pragma: no branch

pinfo("[100%] Done.")

Expand Down
6 changes: 5 additions & 1 deletion pygen/templates.py
Expand Up @@ -50,7 +50,11 @@ def default_targets(self):
targets = self.index['default_targets']

if targets:
return targets
return {
target: value
for target, value in self.targets.items()
if target in targets
}
else:
return self.targets

Expand Down
3 changes: 2 additions & 1 deletion setup.py
Expand Up @@ -21,7 +21,8 @@
'tests',
]),
install_requires=[
'six==1.9.0',
'six==1.10.0',
'future==0.15.2',
'Jinja2==2.8',
'click==6.2',
'PyYAML==3.11',
Expand Down
128 changes: 128 additions & 0 deletions tests/test_parsers/__init__.py
@@ -0,0 +1,128 @@
"""
Unit tests for the parsers utility functions.
"""

import warnings

from mock import (
MagicMock,
patch,
)
from unittest import TestCase

from pygen.parsers import (
get_parser_class_map,
get_parser_from_file,
get_parser_from_file_name,
parse_file,
)
from pygen.parsers.exceptions import NoParserError


class ParsersTests(TestCase):
@patch('pygen.parsers.pkg_resources.iter_entry_points')
def test_get_parser_class_map_import_error(self, iter_entry_points):
entry_point = MagicMock()
entry_point.load.side_effect = ImportError
iter_entry_points.return_value = [entry_point]

with warnings.catch_warnings():
warnings.simplefilter("ignore")
result = get_parser_class_map()

self.assertEqual({}, result)

@patch('pygen.parsers.pkg_resources.iter_entry_points')
def test_get_parser_class_map_registered_twice(self, iter_entry_points):
class_ = MagicMock()
class_.extensions = ['.foo']
entry_point = MagicMock()
entry_point.load.return_value = class_

iter_entry_points.return_value = [
entry_point,
entry_point,
]

result = get_parser_class_map()

self.assertEqual(
{
'.foo': class_,
},
result,
)

@patch('pygen.parsers.pkg_resources.iter_entry_points')
def test_get_parser_class_map_already_registered(self, iter_entry_points):
def get_entry_point_for_extensions(extensions):
class_ = MagicMock()
class_.extensions = extensions
entry_point = MagicMock()
entry_point.load.return_value = class_
return entry_point

iter_entry_points.return_value = [
get_entry_point_for_extensions(['.foo']),
get_entry_point_for_extensions(['.bar', '.foo']),
]

with warnings.catch_warnings():
warnings.simplefilter("ignore")
result = get_parser_class_map()

self.assertEqual(
{
'.foo': iter_entry_points.return_value[0].load.return_value,
'.bar': iter_entry_points.return_value[1].load.return_value,
},
result,
)

@patch('pygen.parsers.parser_class_map')
def test_get_parser_from_file_name_no_parser_error(self, parser_class_map):
parser_class_map.get.return_value = None

with self.assertRaises(NoParserError) as error:
get_parser_from_file_name('a.foo')

parser_class_map.get.assert_called_once_with('.foo')
self.assertEqual('a.foo', error.exception.filename)
self.assertEqual(set(), error.exception.extensions)

@patch('pygen.parsers.parser_class_map')
def test_get_parser_from_file_name(self, parser_class_map):
class_ = MagicMock()
parser_class_map.get.return_value = class_

result = get_parser_from_file_name('a.foo')

parser_class_map.get.assert_called_once_with('.foo')
self.assertEqual(class_(), result)

@patch('pygen.parsers.parser_class_map')
def test_get_parser_from_file(self, parser_class_map):
class_ = MagicMock()
parser_class_map.get.return_value = class_
file = MagicMock()
file.name = 'a.foo'

result = get_parser_from_file(file)

parser_class_map.get.assert_called_once_with('.foo')
self.assertEqual(class_(), result)

@patch('pygen.parsers.parser_class_map')
def test_parse_file(self, parser_class_map):
content = 'my_content'
class_ = MagicMock()
class_().load.return_value = content
parser_class_map.get.return_value = class_
file = MagicMock()
file.name = 'a.foo'

result = parse_file(file)

parser_class_map.get.assert_called_once_with('.foo')
class_().load.assert_called_once_with(file)
self.assertEqual('my_content', result)
22 changes: 22 additions & 0 deletions tests/test_parsers/test_json.py
@@ -0,0 +1,22 @@
"""
Tests for the JSON parser.
"""

from unittest import TestCase

from pygen.parsers.json import JsonParser
from six import StringIO


class JsonParserTests(TestCase):
def setUp(self):
self.parser = JsonParser()

def test_load(self):
file = StringIO('{"a": 1}')
result = self.parser.load(file=file)
self.assertEqual({'a': 1}, result)

def test_loads(self):
result = self.parser.loads('{"a": 1}')
self.assertEqual({'a': 1}, result)
22 changes: 22 additions & 0 deletions tests/test_parsers/test_yaml.py
@@ -0,0 +1,22 @@
"""
Tests for the YAML parser.
"""

from unittest import TestCase

from pygen.parsers.yaml import YamlParser
from six import StringIO


class YamlParserTests(TestCase):
def setUp(self):
self.parser = YamlParser()

def test_load(self):
file = StringIO('a: 1')
result = self.parser.load(file=file)
self.assertEqual({'a': 1}, result)

def test_loads(self):
result = self.parser.loads('a: 1')
self.assertEqual({'a': 1}, result)

0 comments on commit 7d89f46

Please sign in to comment.