Esempio n. 1
0
def compute_prepend_numbers(inpath, col, outpath, rm_on_empty=False):
    """Compute numbers based on mini-language and prepend to all labels.

    This program highlights cells in the following two specific cases:

    (1) The numbering column says there should be a number in the label, but
        there is no number found in the original label. In this case, the
        number is add to the label.
    (2) The numbering column does not produce a number, but the original label
        has a number. In this case, the number is removed.

    Adding a number means to join the number, the string '. ', and the text of
    the cell.

    Args:
        inpath (str): The path where to find the source file.
        col (str): The name of the column where to find numbering.
        outpath (str): The path where to write the new xlsxfile.
        rm_on_empty (bool): Remove numbers that exist when numbering column is
            blank.

    """
    xlsform = Xlsform(inpath)
    survey = xlsform['survey']
    context = NumberingContext()
    for cell in survey.column(col):
        context.next(str(cell))
    for i, header in enumerate(survey.column_headers()):
        if header.startswith('label') or header.startswith('ppp_label'):
            header_skipped = False
            for num, cell in zip(context.string_iter(), survey.column(i)):
                if not header_skipped:
                    header_skipped = True
                    continue
                if num:
                    old_text = str(cell)
                    cell_num, the_rest = utils.td_split_text(old_text)
                    new_text = '. '.join((num, the_rest))
                    cell.value = new_text
                    if not cell_num:
                        # Highlight yellow for adding a number
                        cell.set_highlight()
                    elif new_text != old_text:
                        # Highlight orange for changing a number
                        cell.set_highlight('HL_ORANGE')
                elif cell and rm_on_empty:
                    cell_num, the_rest = utils.td_split_text(str(cell))
                    if cell_num:
                        cell.value = the_rest
                        cell.set_highlight()
    xlsform.write_out(outpath)
Esempio n. 2
0
def merge_translation_file(merge: List[str], translation_dict: TranslationDict,
                           outfile: List[str], add: List[str],
                           ignore: Set[str], carry: bool, no_diverse: bool):
    """Merge in translations to designated ODK files.

    Args:
        merge: The files to merge into
        translation_dict: The object with translation information
        outfile: Where to write the merged files. Should be the same length as
            `merge`.
        add: Languages to add
        ignore: Languages to ignore when merging
        carry: If true, carry text from the source language to the translations
        no_diverse: If true, do not insert a translation that has various
            choices
    """
    for merge_source, merge_destination in zip(merge, outfile):
        xlsform = Xlsform(merge_source)
        xlsform.add_languages(add)
        xlsform.merge_translations(translation_dict,
                                   ignore,
                                   carry=carry,
                                   no_diverse=no_diverse)
        xlsform.write_out(merge_destination)
        print('Merged translations into file: "{}"'.format(merge_destination))
Esempio n. 3
0
    def test_form_language(self):
        """Form language is correctly determined."""
        answers = (('language-default-none.xlsx',
                    None), ('language-missing-default.xlsx', 'Dioula'),
                   ('language-settings-default.xlsx', 'French'))

        for path, language in answers:
            form_path = os.path.join(self.FORM_DIR, path)
            xlsform = Xlsform(form_path)
            found = xlsform.form_language
            msg = 'Working with "{}"'.format(path)
            self.assertEqual(language, found, msg=msg)
Esempio n. 4
0
    def from_file(cls, path):
        """Create Odkform object from file in path.

        Args:
            path (str): The path for the source file of the ODK form,
                typically an '.xlsx' file meeting the XLSForm specification.

        Returns:
            Odkform
        """
        xlsform = Xlsform(path)
        return cls(xlsform)
Esempio n. 5
0
def create_translation_dict(xlsxfile: List[str], correct: List[str]) \
        -> TranslationDict:
    """Create a translation dict from source Excel files.

    Args:
        xlsxfile: Paths to Excel files
        correct: Paths to Excel files that should be marked correct
    """
    translation_dict = TranslationDict()
    extracted = set()
    for path in correct:
        if path in extracted:
            continue
        xlsform = Xlsform(path)
        translation_dict.extract_translations(xlsform, correct=True)
        extracted.add(path)
    for path in xlsxfile:
        if path in extracted:
            continue
        xlsform = Xlsform(path)
        translation_dict.extract_translations(xlsform)
        extracted.add(path)
    return translation_dict
Esempio n. 6
0
def analytics_obj(xlsxfile):
    """Create an analytics object based on supplied path."""
    xls = Xlsform(xlsxfile)
    form_id = xls.form_id
    form_title = xls.form_title
    prompts = get_filtered_survey_names(xls)
    tags = get_useful_tags(xls)
    today = str(datetime.date.today())
    obj = {
        'form_id': form_id,
        'form_title': form_title,
        'prompts': prompts,
        'tags': tags,
        'created': today,
        '~comment': 'END {}'.format(form_id)
    }
    return obj
Esempio n. 7
0
def do_renumber(xlsform_path,
                renumbering_path,
                dry_run=False,
                all_columns=False):
    logging.info(f'Renumbering XLSForm {xlsform_path} with rules '
                 f'from {renumbering_path}')
    renumbering = RenumberMap(renumbering_path)
    xlsform = Xlsform(xlsform_path)
    check_label_numbers_match(xlsform)
    survey = xlsform['survey']
    if all_columns:
        columns = list(range(len(survey.column_headers())))
    else:
        columns = survey.translatable_columns(indices_only=True)
    cell_applications = []
    for i, row in enumerate(survey):
        if i == 0:
            continue
        for j in columns:
            value = row[j].value
            applications = renumbering.applies_to(value)
            if applications:
                cell_applications.append((row[j], applications))
    all_starts = set(renumbering.map.keys())
    all_found_starts = set(
        itertools.chain.from_iterable(x for _, x in cell_applications))
    missing = sorted(list(all_starts - all_found_starts))
    if missing:
        logging.warning(f'Found items in renumber file but not '
                        f'in XLSForm: {missing}, count: {len(missing)}')
    change_count = 0
    for cell, applications in cell_applications:
        old_value = cell.value
        new_value = renumbering.apply(old_value, applications)
        if not dry_run:
            cell.value = new_value
        if old_value != new_value:
            change_count += 1
            cell.set_highlight()
        else:
            cell.set_highlight('HL_ORANGE')
    logging.info(
        f'Done renumbering XLSForm. Number of cell changes: {change_count}')
    return xlsform
Esempio n. 8
0
    def test_sheet_language(self):
        """Languages found in a sheet are correctly determined."""
        answers = (('language-default-none.xlsx', {
            'survey': [
                None, 'Dioula', 'English', 'French', 'Fulfulde',
                'Gourmantchema', 'Moore'
            ],
            'choices': ['English', 'French'],
            'settings': []
        }), )

        for path, answer in answers:
            form_path = os.path.join(self.FORM_DIR, path)
            xlsform = Xlsform(form_path)
            for sheet in xlsform:
                found = sheet.sheet_languages()
                name = sheet.name
                expected = answer[name]
                msg = 'Testing file "{}" and sheet "{}"'.format(path, name)
                self.assertEqual(expected, found, msg=msg)
Esempio n. 9
0
    def from_file(cls, path):
        """Create Odkform object from file in path.

        Args:
            path (str): The path for the source file of the ODK form,
                typically an '.xlsx' file meeting the XLSForm specification.

        Returns:
            Odkform
        """
        xlsform = Xlsform(path)
        odkform = cls(xlsform)
        if xlsform.warnings:
            msg = 'Warning! File {} contained spreadsheet errors. This may ' \
                  'or may not cause problems in the resulting converted ' \
                  'files. Just to be on the safe side, you may want to open ' \
                  'the original spreadsheet file, take a look at the errors,' \
                  ' and fix and convert again if you feel the need.\nThe ' \
                  'errors found are as follows:\n{}'\
                .format(odkform.title, xlsform.warnings)
            print(msg, file=stderr)
        return odkform