| 689 | return success |
| 690 | |
| 691 | def _CheckStatusFileForDuplicateKeys(filepath): |
| 692 | comma_space_bracket = re.compile(", *]") |
| 693 | lines = [] |
| 694 | with open(filepath) as f: |
| 695 | for line in f.readlines(): |
| 696 | # Skip all-comment lines. |
| 697 | if line.lstrip().startswith("#"): continue |
| 698 | # Strip away comments at the end of the line. |
| 699 | comment_start = line.find("#") |
| 700 | if comment_start != -1: |
| 701 | line = line[:comment_start] |
| 702 | line = line.strip() |
| 703 | # Strip away trailing commas within the line. |
| 704 | line = comma_space_bracket.sub("]", line) |
| 705 | if len(line) > 0: |
| 706 | lines.append(line) |
| 707 | |
| 708 | # Strip away trailing commas at line ends. Ugh. |
| 709 | for i in range(len(lines) - 1): |
| 710 | if (lines[i].endswith(",") and len(lines[i + 1]) > 0 and |
| 711 | lines[i + 1][0] in ("}", "]")): |
| 712 | lines[i] = lines[i][:-1] |
| 713 | |
| 714 | contents = "\n".join(lines) |
| 715 | # JSON wants double-quotes. |
| 716 | contents = contents.replace("'", '"') |
| 717 | # Fill in keywords (like PASS, SKIP). |
| 718 | for key in statusfile.KEYWORDS: |
| 719 | contents = re.sub(r"\b%s\b" % key, "\"%s\"" % key, contents) |
| 720 | |
| 721 | status = {"success": True} |
| 722 | def check_pairs(pairs): |
| 723 | keys = {} |
| 724 | for key, value in pairs: |
| 725 | if key in keys: |
| 726 | print("%s: Error: duplicate key %s" % (filepath, key)) |
| 727 | status["success"] = False |
| 728 | keys[key] = True |
| 729 | |
| 730 | json.loads(contents, object_pairs_hook=check_pairs) |
| 731 | return status["success"] |
| 732 | |
| 733 | |
| 734 | class StatusFilesProcessor(SourceFileProcessor): |