code: def jupytext_single_file(nb_file, args, log):
      """Apply the jupytext command, with given arguments, to a single file"""
      if nb_file == "-" and args.sync:
          msg = "Missing notebook path."
          if args.set_formats is not None and os.path.isfile(
              args.set_formats
          ):
              msg += f" Maybe you mean 'jupytext --sync {args.set_formats}' ?"
          raise ValueError(msg)
  
      nb_dest = None
      if args.output:
          nb_dest = args.output
      elif nb_file == "-":
          nb_dest = "-"
      else:
          try:
              bp = base_path(nb_file, args.input_format)
          except InconsistentPath:
              if args.pre_commit_mode:
                  log(
                      "[jupytext] Ignoring unmatched input path {}{}".format(
                          nb_file,
                          f" for format {args.input_format}"
                          if args.input_format
                          else "",
                      )
                  )
                  return 0
              raise
          if args.output_format:
              nb_dest = full_path(bp, args.output_format)
  
      config = load_jupytext_config(os.path.abspath(nb_file))
  
      # Just acting on metadata / pipe => save in place
      save_in_place = not nb_dest and not args.sync
      if save_in_place:
          nb_dest = nb_file
  
      if nb_dest == "-":
          args.quiet = True
  
      # I. ### Read the notebook ###
      fmt = copy(args.input_format) or {}
      if not fmt:
          ext = os.path.splitext(nb_file)[1]
          if ext:
              fmt = {"extension": ext}
      if fmt:
          set_format_options(fmt, args.format_options)
      log(
          "[jupytext] Reading {}{}".format(
              nb_file if nb_file != "-" else "stdin",
              f" in format {short_form_one_format(fmt)}"
              if "extension" in fmt
              else "",
          )
      )
  
      notebook = read(nb_file, fmt=fmt, config=config)
      if "extension" in fmt and "format_name" not in fmt:
          text_representation = notebook.metadata.get(
              "jupytext", {}
          ).get("text_representation", {})
          if text_representation.get("extension") == fmt["extension"]:
              fmt["format_name"] = text_representation["format_name"]
  
      # Compute actual extension when using script/auto, and update nb_dest if necessary
      dest_fmt = args.output_format
      if dest_fmt and dest_fmt["extension"] == ".auto":
          dest_fmt = check_auto_ext(dest_fmt, notebook.metadata, "--to")
          if not args.output and nb_file != "-":
              nb_dest = full_path(
                  base_path(nb_file, args.input_format), dest_fmt
              )
  
      # Set the kernel
      set_kernel = args.set_kernel
      if (
          (not set_kernel)
          and args.execute
          and notebook.metadata.get("kernelspec", {}).get("name")
          is None
      ):
          set_kernel = "-"
  
      if set_kernel:
          if set_kernel == "-":
              language = (
                  notebook.metadata.get("jupytext", {}).get(
                      "main_language"
                  )
                  or notebook.metadata["kernelspec"]["language"]
              )
  
              if not language:
                  raise ValueError(
                      "Cannot infer a kernel as notebook language is not defined"
                  )
  
              kernelspec = kernelspec_from_language(language)
          else:
              try:
                  kernelspec = get_kernel_spec(set_kernel)
              except KeyError as err:
                  raise KeyError(
                      "Please choose a kernel name among {}".format(
                          find_kernel_specs().keys()
                      )
                  ) from err
  
              kernelspec = {
                  "name": args.set_kernel,
                  "language": kernelspec.language,
                  "display_name": kernelspec.display_name,
              }
  
          log(
              "[jupytext] Setting kernel {}".format(
                  kernelspec.get("name")
              )
          )
          args.update_metadata["kernelspec"] = kernelspec
  
      # Are we updating a text file that has a metadata filter? #212
      if args.update_metadata or args.format_options:
          if (
              notebook.metadata.get("jupytext", {}).get(
                  "notebook_metadata_filter"
              )
              == "-all"
          ):
              notebook.metadata.get("jupytext", {}).pop(
                  "notebook_metadata_filter"
              )
  
      # Update the metadata
      if args.update_metadata:
          log(
              "[jupytext] Updating notebook metadata with '{}'".format(
                  json.dumps(args.update_metadata)
              )
          )
  
          if (
              "kernelspec" in args.update_metadata
              and "main_language"
              in notebook.metadata.get("jupytext", {})
          ):
              notebook.metadata["jupytext"].pop("main_language")
  
          recursive_update(notebook.metadata, args.update_metadata)
  
      # Read paired notebooks
      nb_files = [nb_file, nb_dest]
      if args.sync:
          formats = notebook_formats(
              notebook, config, nb_file, fallback_on_current_fmt=False
          )
          set_prefix_and_suffix(fmt, formats, nb_file)
          try:
              (
                  notebook,
                  inputs_nb_file,
                  outputs_nb_file,
              ) = load_paired_notebook(
                  notebook,
                  fmt,
                  config,
                  formats,
                  nb_file,
                  log,
                  args.pre_commit_mode,
              )
              nb_files = [inputs_nb_file, outputs_nb_file]
          except NotAPairedNotebook as err:
              sys.stderr.write("[jupytext] Warning: " + str(err) + "\n")
              return 0
          except InconsistentVersions as err:
              sys.stderr.write("[jupytext] Error: " + str(err) + "\n")
              return 1
  
      # II. ### Apply commands onto the notebook ###
      # Pipe the notebook into the desired commands
      prefix = (
          None
          if nb_file == "-"
          else os.path.splitext(os.path.basename(nb_file))[0]
      )
      for cmd in args.pipe or []:
          notebook = pipe_notebook(
              notebook,
              cmd,
              args.pipe_fmt,
              prefix=prefix,
              warn_only=args.warn_only,
          )
  
      # and/or test the desired commands onto the notebook
      for cmd in args.check or []:
          pipe_notebook(
              notebook,
              cmd,
              args.pipe_fmt,
              update=False,
              prefix=prefix,
              warn_only=args.warn_only,
          )
  
      if (
          args.execute
          and args.pre_commit_mode
          and execution_counts_are_in_order(notebook)
          and not code_cells_have_changed(notebook, nb_files)
      ):
          log(
              f"[jupytext] Execution of {shlex.quote(nb_file)} "
              f"skipped as code cells have not changed and outputs are present."
          )
          args.execute = False
  
      # Execute the notebook
      if args.execute:
          kernel_name = notebook.metadata.get("kernelspec", {}).get(
              "name"
          )
          log(
              f"[jupytext] Executing notebook with kernel {kernel_name}"
          )
  
          if nb_dest is not None and nb_dest != "-":
              nb_path = os.path.dirname(nb_dest)
          elif nb_file != "-":
              nb_path = os.path.dirname(nb_file)
          else:
              nb_path = None
  
          run_path = args.run_path or nb_path
          if args.run_path and not os.path.isdir(run_path):
              # is this a relative directory?
              for base_dir in [nb_path, os.getcwd()]:
                  try_path = os.path.join(base_dir, run_path)
                  if os.path.isdir(try_path):
                      run_path = try_path
                      break
              if not os.path.isdir(run_path):
                  raise ValueError(
                      f"--run-path={args.run_path} is not a valid path"
                  )
  
          if run_path:
              resources = {"metadata": {"path": run_path}}
          else:
              resources = {}
  
          try:
              from nbconvert.preprocessors import ExecutePreprocessor
  
              exec_proc = ExecutePreprocessor(
                  timeout=None, kernel_name=kernel_name
              )
              exec_proc.preprocess(notebook, resources=resources)
          except (ImportError, RuntimeError) as err:
              if args.pre_commit_mode:
                  raise RuntimeError(
                      "An error occurred while executing the notebook. Please "
                      "make sure that you have listed 'nbconvert' and 'ipykernel' "
                      "under 'additional_dependencies' in the jupytext hook."
                  ) from err
              raise RuntimeError(
                  "An error occurred while executing the notebook. Please "
                  "make sure that 'nbconvert' and 'ipykernel' are installed."
              ) from err
  
      # III. ### Possible actions ###
      # a. Test round trip conversion
      if args.test or args.test_strict:
          try:
              # Round trip from an ipynb document
              if fmt["extension"] == ".ipynb":
                  test_round_trip_conversion(
                      notebook,
                      dest_fmt,
                      update=args.update,
                      allow_expected_differences=not args.test_strict,
                      stop_on_first_error=args.stop_on_first_error,
                  )
  
              # Round trip from a text file
              else:
                  with open(nb_file, encoding="utf-8") as fp:
                      org_text = fp.read()
  
                  # If the destination is not ipynb, we convert to/back that format
                  if dest_fmt["extension"] != ".ipynb":
                      dest_text = writes(notebook, fmt=dest_fmt)
                      notebook = reads(dest_text, fmt=dest_fmt)
  
                  text = writes(notebook, fmt=fmt, config=config)
  
                  if args.test_strict:
                      compare(text, org_text)
                  else:
                      # we ignore the YAML header in the comparison #414
                      comment = _SCRIPT_EXTENSIONS.get(
                          fmt["extension"], {}
                      ).get("comment", "")
                      # white spaces between the comment char and the YAML delimiters are allowed
                      if comment:
                          comment = comment + r"\s*"
                      yaml_header = re.compile(
                          r"^{comment}---\s*\n.*\n{comment}---\s*\n".format(
                              comment=comment
                          ),
                          re.MULTILINE | re.DOTALL,
                      )
                      compare(
                          re.sub(yaml_header, "", text),
                          re.sub(yaml_header, "", org_text),
                      )
  
          except (NotebookDifference, AssertionError) as err:
              sys.stdout.write(f"{nb_file}: {str(err)}")
              return 1
          return 0
  
      # b. Output to the desired file or format
      untracked_files = 0
  
      def lazy_write(
          path, fmt=None, action=None, update_timestamp_only=False
      ):
          """Write the notebook only if it has changed"""
          if path == "-":
              write(notebook, "-", fmt=fmt)
              return
  
          nonlocal untracked_files
          if update_timestamp_only:
              modified = False
          else:
              _, ext = os.path.splitext(path)
              fmt = copy(fmt or {})
              fmt = long_form_one_format(fmt, update={"extension": ext})
              new_content = writes(notebook, fmt=fmt, config=config)
              diff = None
              if not new_content.endswith("\n"):
                  new_content += "\n"
              if not os.path.isfile(path):
                  modified = True
              else:
                  with open(path, encoding="utf-8") as fp:
                      current_content = fp.read()
                  modified = new_content != current_content
                  if modified and args.show_changes:
                      diff = compare(
                          new_content,
                          current_content,
                          "",
                          "",
                          return_diff=True,
                      )
  
          if modified:
              # The text representation of the notebook has changed, we write it on disk
              if action is None:
                  message = f"[jupytext] Updating {shlex.quote(path)}"
              else:
                  message = "[jupytext] Writing {path}{format}{action}".format(
                      path=shlex.quote(path),
                      format=" in format " + short_form_one_format(fmt)
                      if fmt and "format_name" in fmt
                      else "",
                      action=action,
                  )
              if diff is not None:
                  message += " with this change:\n" + diff
  
              log(message)
              create_prefix_dir(path, fmt)
              with open(path, "w", encoding="utf-8") as fp:
                  fp.write(new_content)
  
          # Otherwise, we only update the timestamp of the text file to make sure
          # they remain more recent than the ipynb file, for compatibility with the
          # Jupytext contents manager for Jupyter
          if args.use_source_timestamp:
              log(
                  f"[jupytext] Setting the timestamp of {shlex.quote(path)} equal to that of {shlex.quote(nb_file)}"
              )
              os.utime(
                  path,
                  (os.stat(path).st_atime, os.stat(nb_file).st_mtime),
              )
          elif not modified and not path.endswith(".ipynb"):
              log(
                  f"[jupytext] Updating the timestamp of {shlex.quote(path)}"
              )
              os.utime(path, None)
  
          if args.pre_commit:
              system("git", "add", path)
  
          if args.pre_commit_mode and is_untracked(path):
              log(
                  f"[jupytext] Error: the git index is outdated.\n"
                  f"Please add the paired notebook with:\n"
                  f"    git add {shlex.quote(path)}"
              )
              untracked_files += 1
  
          return
  
      if nb_dest:
          if nb_dest == nb_file and not dest_fmt:
              dest_fmt = fmt
  
          # Test consistency between dest name and output format
          if dest_fmt and nb_dest != "-":
              base_path(nb_dest, dest_fmt)
  
          # Describe what jupytext is doing
          if save_in_place:
              action = ""
          elif 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)
              notebook = combine_inputs_with_outputs(
                  notebook, read(nb_dest), fmt=fmt
              )
          elif os.path.isfile(nb_dest):
              suggest_update = (
                  " [use --update to preserve cell outputs and ids]"
                  if nb_dest.endswith(".ipynb")
                  else ""
              )
              action = f" (destination file replaced{suggest_update})"
          else:
              action = ""
  
          formats = notebook.metadata.get("jupytext", {}).get("formats")
          formats = long_form_multiple_formats(formats)
          if formats:
              try:
                  base_path_out, _ = find_base_path_and_format(
                      nb_dest, formats
                  )
              except InconsistentPath:
                  # Drop 'formats' if the destination is not part of the paired notebooks
                  formats = {}
                  notebook.metadata.get("jupytext", {}).pop("formats")
  
          lazy_write(nb_dest, fmt=dest_fmt, action=action)
  
          nb_dest_in_pair = formats and any(
              os.path.exists(alt_path)
              and os.path.samefile(nb_dest, alt_path)
              for alt_path, _ in paired_paths(nb_file, fmt, formats)
          )
  
          if (
              nb_dest_in_pair
              and os.path.isfile(nb_file)
              and not nb_file.endswith(".ipynb")
              and os.path.isfile(nb_dest)
              and nb_dest.endswith(".ipynb")
          ):
              # If the destination is an ipynb file and is in the pair, then we
              # update the original text file timestamp, as required by our Content Manager
              # Otherwise Jupyter will refuse to open the paired notebook #335
              # NB: An alternative is --use-source-timestamp
              lazy_write(nb_file, update_timestamp_only=True)
  
      # c. Synchronize paired notebooks
      elif args.sync:
          write_pair(nb_file, formats, lazy_write)
  
      return untracked_files
  
imports: import argparse
  import glob
  import json
  import os
  import re
  import shlex
  import subprocess
  import sys
  import warnings
  from copy import copy
  from tempfile import NamedTemporaryFile
  from .combine import combine_inputs_with_outputs
  from .compare import NotebookDifference, compare, test_round_trip_conversion
  from .config import load_jupytext_config, notebook_formats
  from .formats import _BINARY_FORMAT_OPTIONS, _VALID_FORMAT_OPTIONS, JUPYTEXT_FORMATS, check_auto_ext, check_file_version, long_form_multiple_formats, long_form_one_format, short_form_one_format
  from .header import recursive_update
  from .jupytext import create_prefix_dir, read, reads, write, writes
  from .kernels import find_kernel_specs, get_kernel_spec, kernelspec_from_language
  from .languages import _SCRIPT_EXTENSIONS
  from .paired_paths import InconsistentPath, base_path, find_base_path_and_format, full_path, paired_paths
  from .pairs import latest_inputs_and_outputs, read_pair, write_pair
  from .version import __version__
label_desc: Use image node_id 6 for calling a global function with example usage: jupytext_single_file(nb_file, args, log) and returns: untracked_files, int, int, int, int, int