Skip to content

Commit c366407

Browse files
authored
Merge pull request #269 from transifex/json_compile_with_empty_dict
Problem with empty dicts when compiling
2 parents fc7e8a1 + d93ea23 commit c366407

File tree

2 files changed

+83
-27
lines changed

2 files changed

+83
-27
lines changed

openformats/formats/json.py

+72-25
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,10 @@ def _extract(self, parsed, nest=None):
8282

8383
if self.name == "STRUCTURED_JSON":
8484
try:
85-
(string_value, _), = value.find_children(self.STRING_KEY)
86-
except:
85+
(string_value, _), = value.find_children(
86+
self.STRING_KEY
87+
)
88+
except Exception:
8789
# Ignore other types of values like lists
8890
pass
8991
else:
@@ -284,7 +286,8 @@ def _insert_item(self, value, value_position, is_real_stringset):
284286
value_position + len(value) + 1
285287
)
286288
else:
287-
# value is an empty string, add the key but don't update stringset_index
289+
# value is an empty string, add the key but don't update
290+
# stringset_index
288291
at_least_one = True
289292
self._insert_regular_string(
290293
value, value_position, '', False
@@ -306,7 +309,7 @@ def _insert_item(self, value, value_position, is_real_stringset):
306309
return at_least_one
307310

308311
def _insert_from_dict(self, parsed, is_real_stringset):
309-
at_least_one = False
312+
at_least_one = not bool(list(parsed))
310313

311314
for key, key_position, value, value_position in parsed:
312315

@@ -323,7 +326,7 @@ def _insert_from_dict(self, parsed, is_real_stringset):
323326
return at_least_one
324327

325328
def _insert_from_list(self, parsed, is_real_stringset):
326-
at_least_one = False
329+
at_least_one = not bool(list(parsed))
327330

328331
for value, value_position in parsed:
329332
self.transcriber.copy_until(value_position - 1)
@@ -512,7 +515,9 @@ def _compile_value(self, value, template_value, value_position):
512515
else:
513516
self.transcriber.add(u"null")
514517
self.transcriber.skip(len(u"{}".format(template_value)))
515-
self.transcriber.copy_until(value_position + len(u"{}".format(template_value)) + 1)
518+
self.transcriber.copy_until(value_position +
519+
len(u"{}".format(template_value)) +
520+
1)
516521

517522
def _compile_recursively(self, current_part):
518523
if isinstance(current_part, DumbJson):
@@ -522,7 +527,8 @@ def _compile_recursively(self, current_part):
522527
if current_part.type == dict:
523528
(value, _) = current_part.find_children(self.STRING_KEY)[0]
524529
if not value:
525-
for key, key_position, value, value_position in current_part:
530+
for (key, key_position, value,
531+
value_position) in current_part:
526532
self.transcriber.copy_until(key_position - 1)
527533
self.transcriber.copy_until(value_position)
528534
self._compile_recursively(value)
@@ -534,46 +540,85 @@ def _compile_recursively(self, current_part):
534540

535541
line_separator = None
536542
key_value_separator = None
537-
for key, key_position, value, value_position in current_part:
543+
for (key, key_position, value,
544+
value_position) in current_part:
538545
prev_position_end = self.transcriber.ptr
539-
line_separator = current_part.source[prev_position_end+1:key_position-1]
540-
key_value_separator = current_part.source[key_position+len(key):value_position-1]
546+
line_separator = current_part.source[
547+
prev_position_end+1:key_position-1
548+
]
549+
key_value_separator = current_part.source[
550+
key_position+len(key):value_position-1
551+
]
541552
self.transcriber.copy_until(key_position - 1)
542553
self.transcriber.copy_until(value_position)
543554
if key == self.CONTEXT_KEY and translation:
544555
context = translation.context
545-
self._compile_value(self.escape(context), value, value_position)
556+
self._compile_value(self.escape(context),
557+
value,
558+
value_position)
546559
context_added = True
547560
elif key == self.DEVELOPER_COMMENT_KEY and translation:
548561
developer_comment = translation.developer_comment
549-
self._compile_value(self.escape(developer_comment), value, value_position)
562+
self._compile_value(self.escape(developer_comment),
563+
value,
564+
value_position)
550565
developer_comments_added = True
551566
elif key == self.CHARACTER_LIMIT_KEY and translation:
552567
character_limit = translation.character_limit
553-
self._compile_value(character_limit, value, value_position)
568+
self._compile_value(character_limit,
569+
value,
570+
value_position)
554571
character_limit_added = True
555572
elif key == self.STRING_KEY and translation:
556573
if translation.pluralized:
557-
string_replacement = ICUCompiler().serialize_strings(translation.string, delimiter=' ')
558-
string_replacement = value.replace(translation.template_replacement, string_replacement)
574+
string_replacement = ICUCompiler().\
575+
serialize_strings(translation.string,
576+
delimiter=' ')
577+
string_replacement = value.replace(
578+
translation.template_replacement,
579+
string_replacement,
580+
)
559581
else:
560582
string_replacement = translation.string
561-
self._compile_value(string_replacement, value, value_position)
583+
self._compile_value(string_replacement,
584+
value,
585+
value_position)
562586
elif not isinstance(value, DumbJson):
563-
self.transcriber.copy_until(value_position + len(u"{}".format(value)) + 1)
587+
self.transcriber.copy_until(
588+
value_position + len(u"{}".format(value)) + 1
589+
)
564590

565591
extra_elements = []
566-
if not context_added and translation and translation.context:
592+
if (not context_added and
593+
translation and
594+
translation.context):
567595
extra_elements.append(u"\"{}{}\"{}\"".format(
568-
"context", key_value_separator, self.escape(translation.context)))
569-
if not character_limit_added and translation and translation.character_limit:
596+
"context",
597+
key_value_separator,
598+
self.escape(translation.context),
599+
))
600+
if (not character_limit_added and
601+
translation and
602+
translation.character_limit):
570603
extra_elements.append(u"\"{}{}{}".format(
571-
"character_limit", key_value_separator, translation.character_limit))
572-
if not developer_comments_added and translation and translation.developer_comment:
604+
"character_limit",
605+
key_value_separator,
606+
translation.character_limit,
607+
))
608+
if (not developer_comments_added and
609+
translation and
610+
translation.developer_comment):
573611
extra_elements.append(u"\"{}{}\"{}\"".format(
574-
"developer_comment", key_value_separator, self.escape(translation.developer_comment)))
612+
"developer_comment",
613+
key_value_separator,
614+
self.escape(translation.developer_comment),
615+
))
575616
if extra_elements:
576-
self.transcriber.add("," + line_separator + ("," + line_separator).join(extra_elements))
617+
self.transcriber.add(
618+
"," +
619+
line_separator +
620+
("," + line_separator).join(extra_elements)
621+
)
577622

578623
def _create_openstring(self, key, payload_dict):
579624
"""Return a new OpenString based on the given key and payload_dict
@@ -644,7 +689,9 @@ def _create_regular_string(self, key, payload_dict):
644689
:param value: the translation string
645690
:return: an OpenString or None
646691
"""
647-
(string_value, string_position), = payload_dict.find_children(self.STRING_KEY)
692+
(string_value, string_position), = payload_dict.find_children(
693+
self.STRING_KEY
694+
)
648695
payload_dict = json.loads(
649696
payload_dict.source[payload_dict.start:payload_dict.end+1])
650697
comment_value = payload_dict.get(self.DEVELOPER_COMMENT_KEY)

openformats/tests/formats/keyvaluejson/test_keyvaluejson.py

+11-2
Original file line numberDiff line numberDiff line change
@@ -257,15 +257,24 @@ def test_skip_middle_of_dict(self):
257257
def test_skip_start_of_list(self):
258258
string1 = self.random_string
259259
string2 = generate_random_string()
260-
openstring2 = OpenString('..1..', string2, order=1)
261260

262261
source = '["%s", "%s"]' % (string1, string2)
263262

264263
template, stringset = self.handler.parse(source)
265-
compiled = self.handler.compile(template, [openstring2])
264+
compiled = self.handler.compile(template, [stringset[1]])
266265

267266
self.assertEqual(compiled, '[ "%s"]' % string2)
268267

268+
def test_empty_dict_at_start_of_list(self):
269+
string = self.random_string
270+
271+
source = '[{}, "%s"]' % string
272+
273+
template, stringset = self.handler.parse(source)
274+
compiled = self.handler.compile(template, stringset)
275+
276+
self.assertEqual(compiled, '[{}, "%s"]' % string)
277+
269278
def test_skip_end_of_list(self):
270279
string1 = self.random_string
271280
string2 = generate_random_string()

0 commit comments

Comments
 (0)