Internal implementation of Jupytext command line

def jupytext(args=None):
    """Internal implementation of Jupytext command line"""
    args = parse_jupytext_args(args)

    def log(text):
        if not args.quiet:
            sys.stdout.write(text + '\n')

    if args.version:
        log(__version__)
        return 0

    if args.pre_commit:
        if args.notebooks:
            raise ValueError('--pre-commit takes notebooks from the git index. Do not pass any notebook here.')
        args.notebooks = notebooks_in_git_index(args.input_format)
        log('[jupytext] Notebooks in git index are:')
        for nb_file in args.notebooks:
            log(nb_file)

    def writef_git_add(notebook_, nb_file_, fmt_):
        writef(notebook_, nb_file_, fmt_)
        if args.pre_commit:
            system('git', 'add', nb_file_)

    # Read notebook from stdin
    if not args.notebooks:
        if not args.pre_commit:
            args.notebooks = ['-']

    if args.set_formats is not None:
        # Replace empty string with None
        args.update_metadata = recursive_update(args.update_metadata,
                                                {'jupytext': {'formats': args.set_formats or None}})

    if args.paired_paths:
        if len(args.notebooks) != 1:
            raise ValueError('--paired-paths applies to a single notebook')
        print_paired_paths(args.notebooks[0], args.input_format)
        return 1

    if not args.to and not args.output and not args.sync \
            and not args.pipe and not args.check \
            and not args.test and not args.test_strict \
            and not args.update_metadata:
        raise ValueError('Please select an action')

    if args.output and len(args.notebooks) != 1:
        raise ValueError('Please input a single notebook when using --output')

    if args.input_format:
        args.input_format = long_form_one_format(args.input_format)

    if args.to:
        args.to = long_form_one_format(args.to)
        set_format_options(args.to, args.format_options)

    # Main loop
    round_trip_conversion_errors = 0

    # Wildcard extension on Windows #202
    notebooks = []
    for pattern in args.notebooks:
        if '*' in pattern or '?' in pattern:
            notebooks.extend(glob.glob(pattern))
        else:
            notebooks.append(pattern)

    for nb_file in notebooks:
        if nb_file == '-' and args.sync:
            raise ValueError('Cannot sync a notebook on stdin')

        nb_dest = args.output or (None if not args.to
                                  else ('-' if nb_file == '-' else
                                        full_path(base_path(nb_file, args.input_format), args.to)))

        # Just acting on metadata / pipe => save in place
        if not nb_dest and not args.sync:
            nb_dest = nb_file

        if nb_dest == '-':
            args.quiet = True

        # I. ### Read the notebook ###
        fmt = copy(args.input_format) or {}
        set_format_options(fmt, args.format_options)
        log('[jupytext] Reading {}{}'.format(
            nb_file if nb_file != '-' else 'stdin',
            ' in format {}'.format(short_form_one_format(fmt)) if 'extension' in fmt else ''))

        notebook = readf(nb_file, fmt)
        if not fmt:
            text_representation = notebook.metadata.get('jupytext', {}).get('text_representation', {})
            ext = os.path.splitext(nb_file)[1]
            if text_representation.get('extension') == ext:
                fmt = {key: text_representation[key] for key in text_representation if
                       key in ['extension', 'format_name']}
            elif ext:
                fmt = {'extension': ext}

        # Update the metadata
        if args.update_metadata:
            log('[jupytext] Updating notebook metadata with {}'.format(args.update_metadata))
            # Are we updating a text file that has a metadata filter? #212
            if fmt['extension'] != '.ipynb' and \
                    notebook.metadata.get('jupytext', {}).get('notebook_metadata_filter') == '-all':
                notebook.metadata.get('jupytext', {}).pop('notebook_metadata_filter')
            recursive_update(notebook.metadata, args.update_metadata)

        # Read paired notebooks
        if args.sync:
            set_prefix_and_suffix(fmt, notebook, nb_file)
            notebook, inputs_nb_file, outputs_nb_file = load_paired_notebook(notebook, fmt, nb_file, log)

        # II. ### Apply commands onto the notebook ###
        # Pipe the notebook into the desired commands
        for cmd in args.pipe or []:
            notebook = pipe_notebook(notebook, cmd, args.pipe_fmt)

        # and/or test the desired commands onto the notebook
        for cmd in args.check or []:
            pipe_notebook(notebook, cmd, args.pipe_fmt, update=False)

        # III. ### Possible actions ###
        modified = args.update_metadata or args.pipe
        # a. Test round trip conversion
        if args.test or args.test_strict:
            try:
                test_round_trip_conversion(notebook, args.to,
                                           update=args.update,
                                           allow_expected_differences=not args.test_strict,
                                           stop_on_first_error=args.stop_on_first_error)
            except NotebookDifference as err:
                round_trip_conversion_errors += 1
                sys.stdout.write('{}: {}'.format(nb_file, str(err)))
            continue

        # b. Output to the desired file or format
        if nb_dest:
            if nb_dest == nb_file and not args.to:
                args.to = fmt

            # Test consistency between dest name and output format
            if args.to and nb_dest != '-':
                base_path(nb_dest, args.to)

            # Describe what jupytext is doing
            if os.path.isfile(nb_dest) and args.update:
                if not nb_dest.endswith('.ipynb'):
                    raise ValueError('--update is only for ipynb files')
                action = ' (destination file updated)'
                check_file_version(notebook, nb_file, nb_dest)
                combine_inputs_with_outputs(notebook, readf(nb_dest), fmt)
            elif os.path.isfile(nb_dest):
                action = ' (destination file replaced)'
            else:
                action = ''

            log('[jupytext] Writing {nb_dest}{format}{action}'
                .format(nb_dest=nb_dest,
                        format=' in format ' + short_form_one_format(
                            args.to) if args.to and 'format_name' in args.to else '',
                        action=action))
            writef_git_add(notebook, nb_dest, args.to)

        # c. Synchronize paired notebooks
        if args.sync:
            # Also update the original notebook if the notebook was modified
            if modified:
                inputs_nb_file = outputs_nb_file = None
            formats = notebook.metadata['jupytext']['formats']

            for ipynb in [True, False]:
                # Write first format last so that it is the most recent file
                for alt_path, alt_fmt in paired_paths(nb_file, fmt, formats)[::-1]:
                    # Write ipynb first for compatibility with our contents manager
                    if alt_path.endswith('.ipynb') != ipynb:
                        continue
                    # Do not write the ipynb file if it was not modified
                    # But, always write text representations to make sure they are the most recent
                    if alt_path == inputs_nb_file and alt_path == outputs_nb_file:
                        continue
                    log("[jupytext] Updating '{}'".format(alt_path))
                    writef_git_add(notebook, alt_path, alt_fmt)

    return round_trip_conversion_errors