Merge branch 'master' into nonstrict-encoding

pull/44/head
Andrew Krasichkov 2017-05-16 23:03:05 +03:00 committed by GitHub
commit cb4dbc875a
20 changed files with 128 additions and 87 deletions

View File

@ -1,6 +1,7 @@
language: python language: python
sudo: false sudo: false
python: python:
- "2.6"
- "2.7" - "2.7"
- "3.5" - "3.5"
- "3.6" - "3.6"
@ -11,4 +12,4 @@ install:
script: script:
- nosetests --with-coverage --cover-package gixy -v - nosetests --with-coverage --cover-package gixy -v
- flake8 --max-line-length=120 setup.py yodax - if [[ $TRAVIS_PYTHON_VERSION != '2.6' ]]; then flake8 --max-line-length=120 setup.py gixy; fi

View File

@ -1,7 +1,7 @@
# [add_header_multiline] Multiline response headers # [add_header_multiline] Multiline response headers
You should avoid using multiline response headers, because: You should avoid using multiline response headers, because:
* they are depricated (see [RFC 7230](https://tools.ietf.org/html/rfc7230#section-3.2.4)); * they are deprecated (see [RFC 7230](https://tools.ietf.org/html/rfc7230#section-3.2.4));
* some HTTP-clients and web browser never supported them (e.g. IE/Edge/Nginx). * some HTTP-clients and web browser never supported them (e.g. IE/Edge/Nginx).
## How can I find it? ## How can I find it?
@ -22,4 +22,4 @@ more_set_headers -t 'text/html text/plain'
``` ```
## What can I do? ## What can I do?
The only solution is to never use multiline response headers. The only solution is to never use multiline response headers.

View File

@ -92,7 +92,7 @@ class ArgsParser(ArgumentParser):
""" """
keys = [] keys = []
for arg in action.option_strings: for arg in action.option_strings:
if arg in {'--config', '--write-config', '--version'}: if arg in ['--config', '--write-config', '--version']:
continue continue
if any([arg.startswith(2 * c) for c in self.prefix_chars]): if any([arg.startswith(2 * c) for c in self.prefix_chars]):
keys += [arg[2:], arg] # eg. for '--bla' return ['bla', '--bla'] keys += [arg[2:], arg] # eg. for '--bla' return ['bla', '--bla']

View File

@ -16,7 +16,6 @@ LOG = logging.getLogger()
def _init_logger(debug=False): def _init_logger(debug=False):
LOG.handlers = [] LOG.handlers = []
log_level = logging.DEBUG if debug else logging.INFO log_level = logging.DEBUG if debug else logging.INFO
logging.captureWarnings(True)
LOG.setLevel(log_level) LOG.setLevel(log_level)
handler = logging.StreamHandler(sys.stderr) handler = logging.StreamHandler(sys.stderr)
@ -31,7 +30,7 @@ def _create_plugin_help(option):
else: else:
default = str(option) default = str(option)
return 'Default: {}'.format(default) return 'Default: {0}'.format(default)
def _get_cli_parser(): def _get_cli_parser():
@ -41,7 +40,7 @@ def _get_cli_parser():
parser.add_argument( parser.add_argument(
'-v', '--version', action='version', '-v', '--version', action='version',
version='Gixy v{}'.format(gixy.version)) version='Gixy v{0}'.format(gixy.version))
parser.add_argument( parser.add_argument(
'-l', '--level', dest='level', action='count', default=0, '-l', '--level', dest='level', action='count', default=0,
@ -106,7 +105,7 @@ def main():
try: try:
severity = gixy.severity.ALL[args.level] severity = gixy.severity.ALL[args.level]
except IndexError: except IndexError:
sys.stderr.write('Too high level filtering. Maximum level: -{}\n'.format('l' * (len(gixy.severity.ALL) - 1))) sys.stderr.write('Too high level filtering. Maximum level: -{0}\n'.format('l' * (len(gixy.severity.ALL) - 1)))
sys.exit(1) sys.exit(1)
if args.tests: if args.tests:
@ -132,7 +131,7 @@ def main():
name = plugin_cls.__name__ name = plugin_cls.__name__
options = copy.deepcopy(plugin_cls.options) options = copy.deepcopy(plugin_cls.options)
for opt_key, opt_val in options.items(): for opt_key, opt_val in options.items():
option_name = '{}:{}'.format(name, opt_key) option_name = '{name}:{key}'.format(name=name, key=opt_key)
if option_name not in args: if option_name not in args:
continue continue

View File

@ -75,7 +75,7 @@ class Context(object):
result = builtins.builtin_var(name) result = builtins.builtin_var(name)
if not result: if not result:
LOG.info("Can't find variable '{}'".format(name)) LOG.info("Can't find variable '{0}'".format(name))
return result return result
def __deepcopy__(self, memo): def __deepcopy__(self, memo):

View File

@ -432,7 +432,7 @@ class BranchToken(Token):
elif isinstance(token, sre_parse.SubPattern): elif isinstance(token, sre_parse.SubPattern):
self.childs.append(InternalSubpatternToken(token=token, parent=self.parent, regexp=self.regexp)) self.childs.append(InternalSubpatternToken(token=token, parent=self.parent, regexp=self.regexp))
else: else:
raise RuntimeError('Unexpected token {} in branch'.format(token)) raise RuntimeError('Unexpected token {0} in branch'.format(token))
def can_contain(self, char, skip_literal=True): def can_contain(self, char, skip_literal=True):
for child in self.childs: for child in self.childs:
@ -461,7 +461,7 @@ class BranchToken(Token):
return res return res
def __str__(self): def __str__(self):
return '(?:{})'.format('|'.join(str(x) for x in self.childs)) return '(?:{0})'.format('|'.join(str(x) for x in self.childs))
class SubpatternToken(Token): class SubpatternToken(Token):
@ -661,7 +661,7 @@ class InToken(Token):
elif isinstance(child, CategoryToken): elif isinstance(child, CategoryToken):
blacklisted.update(child.char_list) blacklisted.update(child.char_list)
else: else:
LOG.info('Unexpected child "{!r}"'.format(child)) LOG.info('Unexpected child "{0!r}"'.format(child))
for char in _build_reverse_list(set()): for char in _build_reverse_list(set()):
if char not in blacklisted: if char not in blacklisted:
@ -756,7 +756,7 @@ class GroupRefToken(Token):
return self.group.generate(context) return self.group.generate(context)
def __str__(self): def __str__(self):
return '\\\\{}'.format(self.id) return '\\\\{0}'.format(self.id)
class AssertToken(Token): class AssertToken(Token):
@ -854,7 +854,7 @@ def parse(sre_obj, parent=None, regexp=None):
elif token[0] == sre_parse.ASSERT_NOT: elif token[0] == sre_parse.ASSERT_NOT:
pass # TODO(buglloc): Do it! pass # TODO(buglloc): Do it!
else: else:
LOG.info('Unexpected token "{}"'.format(token[0])) LOG.info('Unexpected token "{0}"'.format(token[0]))
return result return result

View File

@ -60,7 +60,7 @@ class Block(Directive):
self.children.append(directive) self.children.append(directive)
def __str__(self): def __str__(self):
return '{} {} {}'.format(self.name, ' '.join(self.args), '{') return '{name} {args} {{'.format(name=self.name, args=' '.join(self.args))
class Root(Block): class Root(Block):
@ -89,7 +89,7 @@ class ServerBlock(Block):
def __str__(self): def __str__(self):
server_names = [str(sn) for sn in self.find('server_name')] server_names = [str(sn) for sn in self.find('server_name')]
if server_names: if server_names:
return 'server {{\n{}'.format('\n'.join(server_names[:2])) return 'server {{\n{0}'.format('\n'.join(server_names[:2]))
return 'server {' return 'server {'
@ -141,10 +141,10 @@ class IfBlock(Block):
# if ($request_method = POST) # if ($request_method = POST)
self.variable, self.operand, self.value = args self.variable, self.operand, self.value = args
else: else:
raise Exception('Unknown "if" definition, args: {}'.format(repr(args))) raise Exception('Unknown "if" definition, args: {0!r}'.format(args))
def __str__(self): def __str__(self):
return '{} ({}) {{'.format(self.name, ' '.join(self.args)) return '{name} ({args}) {{'.format(name=self.name, args=' '.join(self.args))
class IncludeBlock(Block): class IncludeBlock(Block):
@ -156,7 +156,7 @@ class IncludeBlock(Block):
self.file_path = args[0] self.file_path = args[0]
def __str__(self): def __str__(self):
return 'include {};'.format(self.file_path) return 'include {0};'.format(self.file_path)
class MapBlock(Block): class MapBlock(Block):

View File

@ -41,7 +41,7 @@ class Directive(object):
raise NotImplementedError() raise NotImplementedError()
def __str__(self): def __str__(self):
return '{} {};'.format(self.name, ' '.join(self.args)) return '{name} {args};'.format(name=self.name, args=' '.join(self.args))
class AddHeaderDirective(Directive): class AddHeaderDirective(Directive):

View File

@ -4,7 +4,7 @@ from gixy.directives import block
class BaseFormatter(object): class BaseFormatter(object):
skip_parents = {block.Root, block.HttpBlock} skip_parents = set([block.Root, block.HttpBlock])
def format_reports(self, reports, stats): def format_reports(self, reports, stats):
raise NotImplementedError("Formatter must override format_reports function") raise NotImplementedError("Formatter must override format_reports function")
@ -74,11 +74,11 @@ class BaseFormatter(object):
if leap.is_block: if leap.is_block:
result.append('') result.append('')
directive = str(leap).replace('\n', '\n' + '\t' * (level + 1)) directive = str(leap).replace('\n', '\n' + '\t' * (level + 1))
result.append('{:s}{:s}'.format('\t' * level, directive)) result.append('{indent:s}{dir:s}'.format(indent='\t' * level, dir=directive))
if leap.is_block: if leap.is_block:
result.extend(self._traverse_tree(leap, points, level + 1 if printable else level)) result.extend(self._traverse_tree(leap, points, level + 1 if printable else level))
if printable and have_parentheses: if printable and have_parentheses:
result.append('{:s}}}'.format('\t' * level)) result.append('{indent:s}}}'.format(indent='\t' * level))
return result return result

View File

@ -22,8 +22,8 @@ class NginxParser(object):
self._init_directives() self._init_directives()
def parse_file(self, path, root=None): def parse_file(self, path, root=None):
LOG.debug("Parse file: {}".format(path)) LOG.debug("Parse file: {0}".format(path))
content = open(path, mode='rb').read() content = open(path).read()
return self.parse(content=content, root=root, path_info=path) return self.parse(content=content, root=root, path_info=path)
def parse(self, content, root=None, path_info=None): def parse(self, content, root=None, path_info=None):
@ -103,7 +103,7 @@ class NginxParser(object):
if self.is_dump: if self.is_dump:
return self._resolve_dump_include(pattern=pattern, parent=parent) return self._resolve_dump_include(pattern=pattern, parent=parent)
if not self.allow_includes: if not self.allow_includes:
LOG.debug('Includes are disallowed, skip: {}'.format(pattern)) LOG.debug('Includes are disallowed, skip: {0}'.format(pattern))
return return
return self._resolve_file_include(pattern=pattern, parent=parent) return self._resolve_file_include(pattern=pattern, parent=parent)
@ -117,7 +117,7 @@ class NginxParser(object):
self.parse_file(file_path, include) self.parse_file(file_path, include)
if not file_path: if not file_path:
LOG.warning("File not found: {}".format(path)) LOG.warning("File not found: {0}".format(path))
def _resolve_dump_include(self, pattern, parent): def _resolve_dump_include(self, pattern, parent):
path = os.path.join(self.cwd, pattern) path = os.path.join(self.cwd, pattern)
@ -130,7 +130,7 @@ class NginxParser(object):
self.parse_block(parsed, include) self.parse_block(parsed, include)
if not founded: if not founded:
LOG.warning("File not found: {}".format(path)) LOG.warning("File not found: {0}".format(path))
def _prepare_dump(self, parsed_block): def _prepare_dump(self, parsed_block):
filename = '' filename = ''

View File

@ -33,7 +33,7 @@ def get_header_values(directive):
result = [] result = []
skip_next = False skip_next = False
for arg in directive.args: for arg in directive.args:
if arg in {'-s', '-t'}: if arg in ['-s', '-t']:
# Skip next value, because it's not a header # Skip next value, because it's not a header
skip_next = True skip_next = True
elif arg.startswith('-'): elif arg.startswith('-'):

View File

@ -18,11 +18,11 @@ class add_header_redefinition(Plugin):
'See documentation: http://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header') 'See documentation: http://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header')
help_url = 'https://github.com/yandex/gixy/blob/master/docs/en/plugins/addheaderredefinition.md' help_url = 'https://github.com/yandex/gixy/blob/master/docs/en/plugins/addheaderredefinition.md'
directives = ['server', 'location', 'if'] directives = ['server', 'location', 'if']
options = {'headers': {'x-frame-options', options = {'headers': set(['x-frame-options',
'x-content-type-options', 'x-content-type-options',
'x-xss-protection', 'x-xss-protection',
'content-security-policy', 'content-security-policy',
'cache-control'} 'cache-control'])
} }
def __init__(self, config): def __init__(self, config):

View File

@ -39,16 +39,16 @@ class origins(Plugin):
self.valid_re = re.compile(regex) self.valid_re = re.compile(regex)
def audit(self, directive): def audit(self, directive):
if directive.operand not in {'~', '~*', '!~', '!~*'}: if directive.operand not in ['~', '~*', '!~', '!~*']:
# Not regexp # Not regexp
return return
if directive.variable not in {'$http_referer', '$http_origin'}: if directive.variable not in ['$http_referer', '$http_origin']:
# Not interesting # Not interesting
return return
invalid_referers = set() invalid_referers = set()
regexp = Regexp(directive.value, case_sensitive=(directive.operand in {'~', '!~'})) regexp = Regexp(directive.value, case_sensitive=(directive.operand in ['~', '!~']))
for value in regexp.generate('/', anchored=True): for value in regexp.generate('/', anchored=True):
if value.startswith('^'): if value.startswith('^'):
value = value[1:] value = value[1:]

36
tests/asserts.py Normal file
View File

@ -0,0 +1,36 @@
from nose.tools import assert_true, assert_false
'''
Various nose.tools helpers that doesn't exists in Python 2.6 Unittest :(
Must be removed with drop Python 2.6 support
'''
def assert_is_instance(obj, cls, msg=None):
"""Same as assert_true(isinstance(obj, cls)), with a nicer
default message."""
if not msg:
msg = '{orig} is not an instance of {test}'.format(orig=type(obj), test=cls)
assert_true(isinstance(obj, cls), msg=msg)
def assert_is_none(obj, msg=None):
"""Same as assert_true(obj is None), with a nicer default message."""
if not msg:
msg = '{orig!r} is not None'.format(orig=obj)
assert_true(obj is None, msg=msg)
def assert_is_not_none(obj, msg=None):
"""Same as assert_false(obj is None), with a nicer default message."""
if not msg:
msg = '{orig!r} is None'.format(orig=obj)
assert_false(obj is None, msg=msg)
def assert_in(member, container, msg=None):
"""Just like assert_true(a in b), but with a nicer default message."""
if not msg:
msg = '{member!r} not found in {container!r}'.format(member=member, container=container)
assert_true(member in container, msg=msg)

View File

@ -232,24 +232,24 @@ def test_negative_must_startswith():
def test_generate(): def test_generate():
cases = ( cases = (
(r'foo', {'foo'}), (r'foo', ['foo']),
(r'^sss', {'^sss'}), (r'^sss', ['^sss']),
(r'(1)(2)(3)', {'123'}), (r'(1)(2)(3)', ['123']),
(r'(1)((2)|(?:3))', {'12', '13'}), (r'(1)((2)|(?:3))', ['12', '13']),
(r'(^1?2?|aa/)', {'^', '^1', '^2', '^12', 'aa/'}), (r'(^1?2?|aa/)', ['^', '^1', '^2', '^12', 'aa/']),
(r'^https?://yandex.ru', {'^http://yandex|ru', '^https://yandex|ru'}), (r'^https?://yandex.ru', ['^http://yandex|ru', '^https://yandex|ru']),
(r'(^bb|11)$', {'^bb$', '11$'}), (r'(^bb|11)$', ['^bb$', '11$']),
(r'(http|https)', {'http', 'https'}), (r'(http|https)', ['http', 'https']),
(r'1*', {'', '11111'}), (r'1*', ['', '11111']),
(r'1*?', {'', '11111'}), (r'1*?', ['', '11111']),
(r'1{0}?2', {'2'}), (r'1[0]?2', ['102', '12']),
(r'1{0}2', {'2'}), (r'1[0]2', ['102']),
(r'1+', {'11111'}), (r'1+', ['11111']),
(r'[^/]?', {'', '|'}), (r'[^/]?', ['', '|']),
(r'^http://(foo|bar)|baz', {'^http://foo', '^http://bar', 'baz'}), (r'^http://(foo|bar)|baz', ['^http://foo', '^http://bar', 'baz']),
(r'[^\x00-\x7b|\x7e-\xff]', {'\x7d'}), (r'[^\x00-\x7b|\x7e-\xff]', ['\x7d']),
(r'(a|b|c)', {'a', 'b', 'c'}), (r'(a|b|c)', ['a', 'b', 'c']),
(r'[xyz]', {'x', 'y', 'z'}) (r'[xyz]', ['x', 'y', 'z'])
) )
for case in cases: for case in cases:
regexp, values = case regexp, values = case
@ -258,7 +258,7 @@ def test_generate():
def test_strict_generate(): def test_strict_generate():
reg = Regexp('^foo|bar', strict=True) reg = Regexp('^foo|bar', strict=True)
assert_equals(sorted(reg.generate('|', anchored=True)), sorted({'^foo', '^bar'})) assert_equals(sorted(reg.generate('|', anchored=True)), sorted(['^foo', '^bar']))
def test_gen_anchor(): def test_gen_anchor():
@ -284,63 +284,63 @@ def test_group_can_contains():
source = '/some/(?P<action>[^/:.]+)/' source = '/some/(?P<action>[^/:.]+)/'
reg = Regexp(source) reg = Regexp(source)
assert_true(reg.can_contain('\n'), assert_true(reg.can_contain('\n'),
'Whole regex "{}" can contains "{}"'.format(source, '\\n')) 'Whole regex "{src}" can contains {sym!r}'.format(src=source, sym='\\n'))
assert_true(reg.group(0).can_contain('\n'), assert_true(reg.group(0).can_contain('\n'),
'Group 0 from regex "{}" can contains "{}"'.format(source, '\\n')) 'Group 0 from regex "{src}" can contains {sym!r}'.format(src=source, sym='\\n'))
assert_true(reg.group('action').can_contain('\n'), assert_true(reg.group('action').can_contain('\n'),
'Group "action" from regex "{}" can contains "{}"'.format(source, '\\n')) 'Group "action" from regex "{src}" can contains {sym!r}'.format(src=source, sym='\\n'))
assert_true(reg.group(1).can_contain('\n'), assert_true(reg.group(1).can_contain('\n'),
'Group 1 from regex "{}" can contains "{}"'.format(source, '\\n')) 'Group 1 from regex "{src}" can contains {sym!r}'.format(src=source, sym='\\n'))
assert_false(reg.group('action').can_contain('/'), assert_false(reg.group('action').can_contain('/'),
'Group "action" from regex "{}" CAN\'T (!) contain "{}"'.format(source, '/')) 'Group "action" from regex "{src}" CAN\'T (!) contain {sym!r}'.format(src=source, sym='/'))
def check_positive_contain(regexp, char): def check_positive_contain(regexp, char):
reg = Regexp(regexp, case_sensitive=True) reg = Regexp(regexp, case_sensitive=True)
assert_true(reg.can_contain(char), assert_true(reg.can_contain(char),
'"{}" should contain "{}"'.format(regexp, char)) '{reg!r} should contain {chr!r}'.format(reg=regexp, chr=char))
reg = Regexp(regexp, case_sensitive=False) reg = Regexp(regexp, case_sensitive=False)
char = char.upper() char = char.upper()
assert_true(reg.can_contain(char), assert_true(reg.can_contain(char),
'"{}" (case insensitive) should contain "{}"'.format(regexp, char)) '{reg!r} (case insensitive) should contain {chr!r}'.format(reg=regexp, chr=char))
def check_negative_contain(regexp, char): def check_negative_contain(regexp, char):
reg = Regexp(regexp, case_sensitive=True) reg = Regexp(regexp, case_sensitive=True)
assert_false(reg.can_contain(char), assert_false(reg.can_contain(char),
'"{}" should not contain "{}"'.format(regexp, char)) '{reg!r} should not contain {chr!r}'.format(reg=regexp, chr=char))
reg = Regexp(regexp, case_sensitive=False) reg = Regexp(regexp, case_sensitive=False)
char = char.upper() char = char.upper()
assert_false(reg.can_contain(char), assert_false(reg.can_contain(char),
'"{}" (case insensitive) should not contain "{}"'.format(regexp, char)) '{reg!r} (case insensitive) should not contain {chr!r}'.format(reg=regexp, chr=char))
def check_positive_startswith(regexp, char, strict): def check_positive_startswith(regexp, char, strict):
reg = Regexp(regexp, case_sensitive=True, strict=strict) reg = Regexp(regexp, case_sensitive=True, strict=strict)
assert_true(reg.can_startswith(char), assert_true(reg.can_startswith(char),
'"{}" can start\'s with "{}"'.format(regexp, char)) '{reg!r} can start\'s with {chr!r}'.format(reg=regexp, chr=char))
reg = Regexp(regexp, case_sensitive=False, strict=strict) reg = Regexp(regexp, case_sensitive=False, strict=strict)
char = char.upper() char = char.upper()
assert_true(reg.can_startswith(char), assert_true(reg.can_startswith(char),
'"{}" (case insensitive) can start\'s with "{}"'.format(regexp, char)) '{reg!r} (case insensitive) can start\'s with {chr!r}'.format(reg=regexp, chr=char))
def check_negative_startswith(regexp, char, strict): def check_negative_startswith(regexp, char, strict):
reg = Regexp(regexp, case_sensitive=True, strict=strict) reg = Regexp(regexp, case_sensitive=True, strict=strict)
assert_false(reg.can_startswith(char), assert_false(reg.can_startswith(char),
'"{}" can\'t start\'s with "{}"'.format(regexp, char)) '{reg!r} can\'t start\'s with {chr!r}'.format(reg=regexp, chr=char))
reg = Regexp(regexp, case_sensitive=False, strict=strict) reg = Regexp(regexp, case_sensitive=False, strict=strict)
char = char.upper() char = char.upper()
assert_false(reg.can_startswith(char), assert_false(reg.can_startswith(char),
'"{}" (case insensitive) can\'t start\'s with "{}"'.format(regexp, char)) '{reg!r} (case insensitive) can\'t start\'s with {chr!r}'.format(reg=regexp, chr=char))
def check_groups_names(regexp, groups): def check_groups_names(regexp, groups):
@ -356,45 +356,46 @@ def check_to_string(regexp, string):
def check_positive_must_contain(regexp, char): def check_positive_must_contain(regexp, char):
reg = Regexp(regexp, case_sensitive=True) reg = Regexp(regexp, case_sensitive=True)
assert_true(reg.must_contain(char), assert_true(reg.must_contain(char),
'"{}" must contain with "{}"'.format(regexp, char)) '{reg!r} must contain with {chr!r}'.format(reg=regexp, chr=char))
reg = Regexp(regexp, case_sensitive=False) reg = Regexp(regexp, case_sensitive=False)
char = char.upper() char = char.upper()
assert_true(reg.must_contain(char), assert_true(reg.must_contain(char),
'"{}" (case insensitive) must contain with "{}"'.format(regexp, char)) '{reg!r} (case insensitive) must contain with {chr!r}'.format(reg=regexp, chr=char))
def check_negative_must_contain(regexp, char): def check_negative_must_contain(regexp, char):
reg = Regexp(regexp, case_sensitive=True) reg = Regexp(regexp, case_sensitive=True)
assert_false(reg.must_contain(char), assert_false(reg.must_contain(char),
'"{}" must NOT contain with "{}"'.format(regexp, char)) '{reg!r} must NOT contain with {chr!r}'.format(reg=regexp, chr=char))
reg = Regexp(regexp, case_sensitive=False) reg = Regexp(regexp, case_sensitive=False)
char = char.upper() char = char.upper()
assert_false(reg.must_contain(char), assert_false(reg.must_contain(char),
'"{}" (case insensitive) must NOT contain with "{}"'.format(regexp, char)) '{reg!r} (case insensitive) must NOT contain with {chr!r}'.format(reg=regexp, chr=char))
def check_positive_must_startswith(regexp, char, strict): def check_positive_must_startswith(regexp, char, strict):
reg = Regexp(regexp, case_sensitive=True, strict=strict) reg = Regexp(regexp, case_sensitive=True, strict=strict)
assert_true(reg.must_startswith(char), assert_true(reg.must_startswith(char),
'"{}" MUST start\'s with "{}"'.format(regexp, char)) '{reg!r} MUST start\'s with {chr!r}'.format(reg=regexp, chr=char))
reg = Regexp(regexp, case_sensitive=False, strict=strict) reg = Regexp(regexp, case_sensitive=False, strict=strict)
char = char.upper() char = char.upper()
assert_true(reg.must_startswith(char), assert_true(reg.must_startswith(char),
'"{}" (case insensitive) MUST start\'s with "{}"'.format(regexp, char)) '{reg!r} (case insensitive) MUST start\'s with {chr!r}'.format(reg=regexp, chr=char))
def check_negative_must_startswith(regexp, char, strict): def check_negative_must_startswith(regexp, char, strict):
reg = Regexp(regexp, case_sensitive=True, strict=strict) reg = Regexp(regexp, case_sensitive=True, strict=strict)
assert_false(reg.must_startswith(char), assert_false(reg.must_startswith(char),
'"{}" MUST NOT start\'s with "{}"'.format(regexp, char)) '{reg!r} MUST NOT start\'s with {chr!r}'.format(reg=regexp, chr=char))
reg = Regexp(regexp, case_sensitive=False, strict=strict) reg = Regexp(regexp, case_sensitive=False, strict=strict)
char = char.upper() char = char.upper()
assert_false(reg.must_startswith(char), assert_false(reg.must_startswith(char),
'"{}" (case insensitive) MUST NOT start\'s with "{}"'.format(regexp, char)) '{reg!r} (case insensitive) MUST NOT start\'s with {chr!r}'.format(reg=regexp, chr=char))
def check_generate(regexp, values): def check_generate(regexp, values):
reg = Regexp(regexp) reg = Regexp(regexp)

View File

@ -1,4 +1,5 @@
from nose.tools import assert_equals, assert_is_instance, assert_is_not_none, assert_is_none, assert_true, assert_false from nose.tools import assert_equals, assert_true, assert_false
from tests.asserts import assert_is_instance, assert_is_none, assert_is_not_none
from gixy.parser.nginx_parser import NginxParser from gixy.parser.nginx_parser import NginxParser
from gixy.directives.block import * from gixy.directives.block import *
@ -148,7 +149,7 @@ def test_block_some_flat():
''' '''
directive = _get_parsed(config) directive = _get_parsed(config)
for d in {'default_type', 'sendfile', 'keepalive_timeout'}: for d in ['default_type', 'sendfile', 'keepalive_timeout']:
c = directive.some(d, flat=True) c = directive.some(d, flat=True)
assert_is_not_none(c) assert_is_not_none(c)
assert_equals(c.name, d) assert_equals(c.name, d)

View File

@ -1,4 +1,5 @@
from nose.tools import assert_equals, assert_is_instance, assert_false, assert_true from nose.tools import assert_equals, assert_false, assert_true
from tests.asserts import assert_is_instance
from gixy.parser.nginx_parser import NginxParser from gixy.parser.nginx_parser import NginxParser
from gixy.directives.directive import * from gixy.directives.directive import *

View File

@ -1,4 +1,5 @@
from nose.tools import assert_is_instance, assert_equal from nose.tools import assert_equal
from tests.asserts import assert_is_instance
from gixy.parser.nginx_parser import NginxParser from gixy.parser.nginx_parser import NginxParser
from gixy.directives.directive import * from gixy.directives.directive import *
from gixy.directives.block import * from gixy.directives.block import *

View File

@ -1,4 +1,5 @@
from nose.tools import assert_equals, assert_true, assert_in from nose.tools import assert_equals, assert_true
from tests.asserts import assert_in
import os import os
from os import path from os import path
import json import json
@ -55,9 +56,9 @@ def test_from_config():
for plugin in manager.plugins: for plugin in manager.plugins:
plugin = plugin.name plugin = plugin.name
assert_true(plugin in tested_plugins, assert_true(plugin in tested_plugins,
'Plugin "{}" should have at least one simple test config'.format(plugin)) 'Plugin {name!r} should have at least one simple test config'.format(name=plugin))
assert_true(plugin in tested_fp_plugins, assert_true(plugin in tested_fp_plugins,
'Plugin "{}" should have at least one simple test config with false positive'.format(plugin)) 'Plugin {name!r} should have at least one simple test config with false positive'.format(name=plugin))
def parse_plugin_options(config_path): def parse_plugin_options(config_path):

View File

@ -1,5 +1,5 @@
[tox] [tox]
envlist = py27, py34, py35, py36, flake8 envlist = py26, py27, py34, py35, py36, flake8
skip_missing_interpreters = True skip_missing_interpreters = True
[testenv] [testenv]
@ -16,4 +16,4 @@ commands =
flake8 setup.py gixy flake8 setup.py gixy
[flake8] [flake8]
max_line_length = 120 max_line_length = 120