Commit 81045c17 authored by Weblate's avatar Weblate

Merge remote-tracking branch 'origin/master'

parents f961dbaa f29614ee
......@@ -222,31 +222,6 @@ class Check(object):
or (src not in chars and tgt in chars)
)
def check_format_strings(self, source, target, regex, unit):
'''
Generic checker for format strings.
'''
if len(target) == 0 or len(source) == 0:
return False
# Try geting source parsing from cache
src_matches = self.get_cache(unit)
# Cache miss
if src_matches is None:
src_matches = set([x[0] for x in regex.findall(source)])
self.set_cache(unit, src_matches)
tgt_matches = set([x[0] for x in regex.findall(target)])
# We ignore %% as this is really not relevant. However it needs
# to be matched to prevent handling %%s as %s.
if '%' in src_matches:
src_matches.remove('%')
if '%' in tgt_matches:
tgt_matches.remove('%')
if src_matches != tgt_matches:
return True
return False
def is_language(self, language, vals):
'''
Detects whether language is in given list, ignores language
......@@ -528,65 +503,94 @@ class EndEllipsisCheck(TargetCheck):
def check_single(self, source, target, flags, language, unit):
return self.check_chars(source, target, -1, [u'…'])
# For now all format string checks use generic implementation, but
# it should be switched to language specific
class BaseFormatCheck(TargetCheck):
'''
Base class for fomat string checks.
'''
flag = None
regexp = None
def check(self, sources, targets, flags, language, unit):
'''
Checks single unit, handling plurals.
'''
if not self.flag in flags:
return False
# Check singular
if self.check_format(sources[0], targets[0], flags, language, unit, len(sources) > 1):
return True
# Do we have more to check?
if len(sources) == 1:
return False
# Check plurals against plural from source
for target in targets[1:]:
if self.check_format(sources[1], target, flags, language, unit, False):
return True
# Check did not fire
return False
def check_format(self, source, target, flags, language, unit, ignore_missing):
'''
Generic checker for format strings.
'''
if len(target) == 0 or len(source) == 0:
return False
# Try geting source parsing from cache
src_matches = self.get_cache(unit)
# Cache miss
if src_matches is None:
src_matches = set([x[0] for x in self.regexp.findall(source)])
self.set_cache(unit, src_matches)
tgt_matches = set([x[0] for x in self.regexp.findall(target)])
# We ignore %% as this is really not relevant. However it needs
# to be matched to prevent handling %%s as %s.
if '%' in src_matches:
src_matches.remove('%')
if '%' in tgt_matches:
tgt_matches.remove('%')
if src_matches != tgt_matches:
# We can ignore missing format strings
# for first of plurals
if ignore_missing and tgt_matches < src_matches:
return False
return True
class PythonFormatCheck(TargetCheck):
return False
class PythonFormatCheck(BaseFormatCheck):
'''
Check for Python format string
'''
check_id = 'python_format'
name = _('Python format')
description = _('Format string does not match source')
def check_single(self, source, target, flags, language, unit):
if not 'python-format' in flags:
return False
return self.check_format_strings(
source,
target,
PYTHON_PRINTF_MATCH,
unit
)
flag = 'python-format'
regexp = PYTHON_PRINTF_MATCH
class PHPFormatCheck(TargetCheck):
class PHPFormatCheck(BaseFormatCheck):
'''
Check for PHP format string
'''
check_id = 'php_format'
name = _('PHP format')
description = _('Format string does not match source')
def check_single(self, source, target, flags, language, unit):
if not 'php-format' in flags:
return False
return self.check_format_strings(
source,
target,
PHP_PRINTF_MATCH,
unit
)
flag = 'php-format'
regexp = PHP_PRINTF_MATCH
class CFormatCheck(TargetCheck):
class CFormatCheck(BaseFormatCheck):
'''
Check for C format string
'''
check_id = 'c_format'
name = _('C format')
description = _('Format string does not match source')
def check_single(self, source, target, flags, language, unit):
if not 'c-format' in flags:
return False
return self.check_format_strings(
source,
target,
C_PRINTF_MATCH,
unit
)
flag = 'c-format'
regexp = C_PRINTF_MATCH
class PluralsCheck(TargetCheck):
......
......@@ -434,75 +434,93 @@ class PythonFormatCheckTest(TestCase):
self.check = PythonFormatCheck()
def test_no_format(self):
self.assertFalse(self.check.check_single(
self.assertFalse(self.check.check_format(
'strins',
'string',
'python-format',
Language('cs'),
Unit('python_no_format')
Unit('python_no_format'),
False
))
def test_format(self):
self.assertFalse(self.check.check_single(
self.assertFalse(self.check.check_format(
u'%s string',
u'%s string',
'python-format',
Language('cs'),
Unit('python_format')
Unit('python_format'),
False
))
def test_percent_format(self):
self.assertFalse(self.check.check_single(
self.assertFalse(self.check.check_format(
u'%d%% string',
u'%d%% string',
'python-format',
Language('cs'),
Unit('python_percent_format')
Unit('python_percent_format'),
False
))
def test_named_format(self):
self.assertFalse(self.check.check_single(
self.assertFalse(self.check.check_format(
u'%(name)s string',
u'%(name)s string',
'python-format',
Language('cs'),
Unit('python_named_format')
Unit('python_named_format'),
False
))
def test_missing_format(self):
self.assertTrue(self.check.check_single(
self.assertTrue(self.check.check_format(
u'%s string',
u'string',
'python-format',
Language('cs'),
Unit('python_missing_format')
Unit('python_missing_format'),
False
))
def test_missing_named_format(self):
self.assertTrue(self.check.check_single(
self.assertTrue(self.check.check_format(
u'%(name)s string',
u'string',
'python-format',
Language('cs'),
Unit('python_missing_named_format'),
False
))
def test_missing_named_format_ignore(self):
self.assertFalse(self.check.check_format(
u'%(name)s string',
u'string',
'python-format',
Language('cs'),
Unit('python_missing_named_format')
Unit('python_missing_named_format'),
True
))
def test_wrong_format(self):
self.assertTrue(self.check.check_single(
self.assertTrue(self.check.check_format(
u'%s string',
u'%c string',
'python-format',
Language('cs'),
Unit('python_wrong_format')
Unit('python_wrong_format'),
False
))
def test_wrong_named_format(self):
self.assertTrue(self.check.check_single(
self.assertTrue(self.check.check_format(
u'%(name)s string',
u'%(jmeno)s string',
'python-format',
Language('cs'),
Unit('python_wrong_named_format')
Unit('python_wrong_named_format'),
False
))
......@@ -511,66 +529,83 @@ class PHPFormatCheckTest(TestCase):
self.check = PHPFormatCheck()
def test_no_format(self):
self.assertFalse(self.check.check_single(
self.assertFalse(self.check.check_format(
'strins',
'string',
'php-format',
Language('cs'),
Unit('php_no_format')
Unit('php_no_format'),
False
))
def test_format(self):
self.assertFalse(self.check.check_single(
self.assertFalse(self.check.check_format(
u'%s string',
u'%s string',
'php-format',
Language('cs'),
Unit('php_format')
Unit('php_format'),
False
))
def test_named_format(self):
self.assertFalse(self.check.check_single(
self.assertFalse(self.check.check_format(
u'%1$s string',
u'%1$s string',
'php-format',
Language('cs'),
Unit('php_named_format')
Unit('php_named_format'),
False
))
def test_missing_format(self):
self.assertTrue(self.check.check_single(
self.assertTrue(self.check.check_format(
u'%s string',
u'string',
'php-format',
Language('cs'),
Unit('php_missing_format')
Unit('php_missing_format'),
False
))
def test_missing_named_format(self):
self.assertTrue(self.check.check_single(
self.assertTrue(self.check.check_format(
u'%1$s string',
u'string',
'php-format',
Language('cs'),
Unit('php_missing_named_format'),
False
))
def test_missing_named_format_ignore(self):
self.assertFalse(self.check.check_format(
u'%1$s string',
u'string',
'php-format',
Language('cs'),
Unit('php_missing_named_format')
Unit('php_missing_named_format'),
True
))
def test_wrong_format(self):
self.assertTrue(self.check.check_single(
self.assertTrue(self.check.check_format(
u'%s string',
u'%c string',
'php-format',
Language('cs'),
Unit('php_wrong_format')
Unit('php_wrong_format'),
False
))
def test_wrong_named_format(self):
self.assertTrue(self.check.check_single(
self.assertTrue(self.check.check_format(
u'%1$s string',
u'%s string',
'php-format',
Language('cs'),
Unit('php_wrong_named_format')
Unit('php_wrong_named_format'),
False
))
......@@ -579,66 +614,83 @@ class CFormatCheckTest(TestCase):
self.check = CFormatCheck()
def test_no_format(self):
self.assertFalse(self.check.check_single(
self.assertFalse(self.check.check_format(
'strins',
'string',
'c-format',
Language('cs'),
Unit('c_no_format')
Unit('c_no_format'),
False
))
def test_format(self):
self.assertFalse(self.check.check_single(
self.assertFalse(self.check.check_format(
u'%s string',
u'%s string',
'c-format',
Language('cs'),
Unit('c_format')
Unit('c_format'),
False
))
def test_named_format(self):
self.assertFalse(self.check.check_single(
self.assertFalse(self.check.check_format(
u'%10s string',
u'%10s string',
'c-format',
Language('cs'),
Unit('c_named_format')
Unit('c_named_format'),
False
))
def test_missing_format(self):
self.assertTrue(self.check.check_single(
self.assertTrue(self.check.check_format(
u'%s string',
u'string',
'c-format',
Language('cs'),
Unit('c_missing_format')
Unit('c_missing_format'),
False
))
def test_missing_named_format(self):
self.assertTrue(self.check.check_single(
self.assertTrue(self.check.check_format(
u'%10s string',
u'string',
'c-format',
Language('cs'),
Unit('c_missing_named_format'),
False
))
def test_missing_named_format_ignore(self):
self.assertFalse(self.check.check_format(
u'%10s string',
u'string',
'c-format',
Language('cs'),
Unit('c_missing_named_format')
Unit('c_missing_named_format'),
True
))
def test_wrong_format(self):
self.assertTrue(self.check.check_single(
self.assertTrue(self.check.check_format(
u'%s string',
u'%c string',
'c-format',
Language('cs'),
Unit('c_wrong_format')
Unit('c_wrong_format'),
False
))
def test_wrong_named_format(self):
self.assertTrue(self.check.check_single(
self.assertTrue(self.check.check_format(
u'%10s string',
u'%20s string',
'c-format',
Language('cs'),
Unit('c_wrong_named_format')
Unit('c_wrong_named_format'),
False
))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment