code: def main(
      run_treebank,
      model_dir,
      model_name,
      add_specific_args=None,
      sub_argparse=None,
      build_model_filename=None,
      choose_charlm_method=None,
  ):
      """
      A main program for each of the run_xyz scripts
  
      It collects the arguments and runs the main method for each dataset provided.
      It also tries to look for an existing model and not overwrite it unless --force is provided
  
      model_name can be a callable expecting the args
        - the charlm, for example, needs this feature, since it makes
          both forward and backward models
      """
      logger.info(
          "Training program called with:\n" + " ".join(sys.argv)
      )
  
      paths = default_paths.get_default_paths()
  
      parser = build_argparse(sub_argparse)
      if add_specific_args is not None:
          add_specific_args(parser)
      if "--extra_args" in sys.argv:
          idx = sys.argv.index("--extra_args")
          extra_args = sys.argv[idx + 1 :]
          command_args = parser.parse_args(sys.argv[1:idx])
      else:
          command_args, extra_args = parser.parse_known_args()
  
      # Pass this through to the underlying model as well as use it here
      # we don't put --save_name here for the awkward situation of
      # --save_name being specified for an invocation with multiple treebanks
      if command_args.save_dir:
          extra_args.extend(["--save_dir", command_args.save_dir])
  
      if callable(model_name):
          model_name = model_name(command_args)
  
      mode = command_args.mode
      treebanks = []
  
      for treebank in command_args.treebanks:
          # this is a really annoying typo to make if you copy/paste a
          # UD directory name on the cluster and your job dies 30s after
          # being queued for an hour
          if treebank.endswith("/"):
              treebank = treebank[:-1]
          if treebank.lower() in ("ud_all", "all_ud"):
              ud_treebanks = common.get_ud_treebanks(paths["UDBASE"])
              if (
                  choose_charlm_method is not None
                  and command_args.charlm_only
              ):
                  logger.info(
                      "Filtering ud_all treebanks to only those which can use charlm for this model"
                  )
                  ud_treebanks = [
                      x
                      for x in ud_treebanks
                      if choose_charlm_method(
                          *treebank_to_short_name(x).split("_", 1),
                          "default",
                      )
                      is not None
                  ]
              if command_args.transformer_only:
                  logger.info(
                      "Filtering ud_all treebanks to only those which can use a transformer for this model"
                  )
                  ud_treebanks = [
                      x
                      for x in ud_treebanks
                      if treebank_to_short_name(x).split("_")[0]
                      in TRANSFORMERS
                  ]
              logger.info(
                  "Expanding %s to %s", treebank, " ".join(ud_treebanks)
              )
              treebanks.extend(ud_treebanks)
          else:
              treebanks.append(treebank)
  
      for treebank_idx, treebank in enumerate(treebanks):
          if treebank_idx > 0:
              logger.info("=========================================")
  
          short_name = treebank_to_short_name(treebank)
          logger.debug("%s: %s" % (treebank, short_name))
  
          save_name_args = []
          if model_name != "ete":
              # ete is several models at once, so we don't set --save_name
              # theoretically we could handle a parametrized save_name
              if command_args.save_name:
                  save_name = command_args.save_name
                  # if there's more than 1 treebank, we can't save them all to this save_name
                  # we have to override that value for each treebank
                  if len(treebanks) > 1:
                      save_name_dir, save_name_filename = os.path.split(
                          save_name
                      )
                      save_name_filename = "%s_%s" % (
                          short_name,
                          save_name_filename,
                      )
                      save_name = os.path.join(
                          save_name_dir, save_name_filename
                      )
                      logger.info(
                          "Save file for %s model for %s: %s",
                          short_name,
                          treebank,
                          save_name,
                      )
                  save_name_args = ["--save_name", save_name]
              # some run scripts can build the model filename
              # in order to check for models that are already created
              elif build_model_filename is None:
                  save_name = "%s_%s.pt" % (short_name, model_name)
                  logger.info(
                      "Save file for %s model: %s",
                      short_name,
                      save_name,
                  )
                  save_name_args = ["--save_name", save_name]
              else:
                  save_name_args = []
  
              if mode == Mode.TRAIN and not command_args.force:
                  if build_model_filename is not None:
                      model_path = build_model_filename(
                          paths, short_name, command_args, extra_args
                      )
                  elif command_args.save_dir:
                      model_path = os.path.join(
                          command_args.save_dir, save_name
                      )
                  else:
                      save_dir = os.path.join("saved_models", model_dir)
                      save_name_args.extend(["--save_dir", save_dir])
                      model_path = os.path.join(save_dir, save_name)
  
                  if model_path is None:
                      # this can happen with the identity lemmatizer, for example
                      pass
                  elif os.path.exists(model_path):
                      logger.info(
                          "%s: %s exists, skipping!"
                          % (treebank, model_path)
                      )
                      continue
                  else:
                      logger.info(
                          "%s: %s does not exist, training new model"
                          % (treebank, model_path)
                      )
  
          if command_args.temp_output and model_name != "ete":
              with tempfile.NamedTemporaryFile() as temp_output_file:
                  run_treebank(
                      mode,
                      paths,
                      treebank,
                      short_name,
                      temp_output_file.name,
                      command_args,
                      extra_args + save_name_args,
                  )
          else:
              run_treebank(
                  mode,
                  paths,
                  treebank,
                  short_name,
                  None,
                  command_args,
                  extra_args + save_name_args,
              )
  
imports: import argparse
  import glob
  import logging
  import os
  import pathlib
  import sys
  import tempfile
  from enum import Enum
  from stanza.resources.default_packages import default_charlms, lemma_charlms, pos_charlms, depparse_charlms, TRANSFORMERS, TRANSFORMER_LAYERS
  from stanza.models.common.constant import treebank_to_short_name
  from stanza.models.common.utils import ud_scores
  from stanza.resources.common import download, DEFAULT_MODEL_DIR, UnknownLanguageError
  from stanza.utils.datasets import common
  import stanza.utils.default_paths
  from stanza.utils import conll18_ud_eval
label_desc: Use image node_id 3 for calling a global function with example usage: main(run_treebank, model_dir, model_name, add_specific_args, sub_argparse, build_model_filename, choose_charlm_method) without return types