LSST Applications  22.0.1,22.0.1+01bcf6a671,22.0.1+046ee49490,22.0.1+05c7de27da,22.0.1+0c6914dbf6,22.0.1+1220d50b50,22.0.1+12fd109e95,22.0.1+1a1dd69893,22.0.1+1c910dc348,22.0.1+1ef34551f5,22.0.1+30170c3d08,22.0.1+39153823fd,22.0.1+611137eacc,22.0.1+771eb1e3e8,22.0.1+94e66cc9ed,22.0.1+9a075d06e2,22.0.1+a5ff6e246e,22.0.1+a7db719c1a,22.0.1+ba0d97e778,22.0.1+bfe1ee9056,22.0.1+c4e1e0358a,22.0.1+cc34b8281e,22.0.1+d640e2c0fa,22.0.1+d72a2e677a,22.0.1+d9a6b571bd,22.0.1+e485e9761b,22.0.1+ebe8d3385e
LSST Data Management Base Package
Public Member Functions | Static Public Attributes | List of all members
lsst.pipe.base.argumentParser.ArgumentParser Class Reference
Inheritance diagram for lsst.pipe.base.argumentParser.ArgumentParser:
lsst.pipe.base.argumentParser.InputOnlyArgumentParser lsst.pipe.drivers.constructCalibs.CalibArgumentParser lsst.pipe.tasks.ingest.IngestArgumentParser lsst.pipe.tasks.ingestCalibs.IngestCalibsArgumentParser lsst.pipe.tasks.ingestCuratedCalibs.IngestCuratedCalibsArgumentParser lsst.obs.decam.ingest.DecamIngestArgumentParser

Public Member Functions

def __init__ (self, name, usage="%(prog)s input [options]", **kwargs)
 
def add_id_argument (self, name, datasetType, help, level=None, doMakeDataRefList=True, ContainerClass=DataIdContainer)
 
def parse_args (self, config, args=None, log=None, override=None)
 
def handleCamera (self, namespace)
 
def convert_arg_line_to_args (self, arg_line)
 
def addReuseOption (self, choices)
 

Static Public Attributes

bool requireOutput = True
 

Detailed Description

Argument parser for command-line tasks that is based on
`argparse.ArgumentParser`.

Parameters
----------
name : `str`
    Name of top-level task; used to identify camera-specific override
    files.
usage : `str`, optional
    Command-line usage signature.
**kwargs
    Additional keyword arguments for `argparse.ArgumentParser`.

Notes
-----
Users may wish to add additional arguments before calling `parse_args`.

Definition at line 408 of file argumentParser.py.

Constructor & Destructor Documentation

◆ __init__()

def lsst.pipe.base.argumentParser.ArgumentParser.__init__ (   self,
  name,
  usage = "%(prog)s input [options]",
**  kwargs 
)

Definition at line 435 of file argumentParser.py.

435  def __init__(self, name, usage="%(prog)s input [options]", **kwargs):
436  self._name = name
437  self._dataIdArgDict = {} # Dict of data identifier specifications, by argument name
438  argparse.ArgumentParser.__init__(self,
439  usage=usage,
440  fromfile_prefix_chars='@',
441  epilog=textwrap.dedent("""Notes:
442  * --config, --config-file or --configfile, --id, --loglevel and @file may appear multiple times;
443  all values are used, in order left to right
444  * @file reads command-line options from the specified file:
445  * data may be distributed among multiple lines (e.g. one option per line)
446  * data after # is treated as a comment and ignored
447  * blank lines and lines starting with # are ignored
448  * To specify multiple values for an option, do not use = after the option name:
449  * right: --config-file foo bar
450  * wrong: --config-file=foo bar
451  """),
452  formatter_class=argparse.RawDescriptionHelpFormatter,
453  **kwargs)
454  self.add_argument(metavar='input', dest="rawInput",
455  help=f"path to input data repository, relative to ${DEFAULT_INPUT_NAME}")
456  self.add_argument("--calib", dest="rawCalib",
457  help=f"path to input calibration repository, relative to ${DEFAULT_CALIB_NAME}")
458  self.add_argument("--output", dest="rawOutput",
459  help="path to output data repository (need not exist), "
460  f"relative to ${DEFAULT_OUTPUT_NAME}")
461  self.add_argument("--rerun", dest="rawRerun", metavar="[INPUT:]OUTPUT",
462  help="rerun name: sets OUTPUT to ROOT/rerun/OUTPUT; "
463  "optionally sets ROOT to ROOT/rerun/INPUT")
464  self.add_argument("-c", "--config", nargs="*", action=ConfigValueAction,
465  help="config override(s), e.g. -c foo=newfoo bar.baz=3", metavar="NAME=VALUE")
466  self.add_argument("-C", "--config-file", "--configfile",
467  dest="configfile", nargs="*", action=ConfigFileAction,
468  help="config override file(s)")
469  self.add_argument("-L", "--loglevel", nargs="*", action=LogLevelAction,
470  help="logging level; supported levels are [trace|debug|info|warn|error|fatal]",
471  metavar="LEVEL|COMPONENT=LEVEL")
472  self.add_argument("--longlog", action="store_true", help="use a more verbose format for the logging")
473  self.add_argument("--debug", action="store_true", help="enable debugging output?")
474  self.add_argument("--doraise", action="store_true",
475  help="raise an exception on error (else log a message and continue)?")
476  self.add_argument("--noExit", action="store_true",
477  help="Do not exit even upon failure (i.e. return a struct to the calling script)")
478  self.add_argument("--profile", help="Dump cProfile statistics to filename")
479  self.add_argument("--show", nargs="+", default=(),
480  help="display the specified information to stdout and quit "
481  "(unless run is specified); information is "
482  "(config[=PATTERN]|history=PATTERN|tasks|data|run)")
483  self.add_argument("-j", "--processes", type=int, default=1, help="Number of processes to use")
484  self.add_argument("-t", "--timeout", type=float,
485  help="Timeout for multiprocessing; maximum wall time (sec)")
486  self.add_argument("--clobber-output", action="store_true", dest="clobberOutput", default=False,
487  help=("remove and re-create the output directory if it already exists "
488  "(safe with -j, but not all other forms of parallel execution)"))
489  self.add_argument("--clobber-config", action="store_true", dest="clobberConfig", default=False,
490  help=("backup and then overwrite existing config files instead of checking them "
491  "(safe with -j, but not all other forms of parallel execution)"))
492  self.add_argument("--no-backup-config", action="store_true", dest="noBackupConfig", default=False,
493  help="Don't copy config to file~N backup.")
494  self.add_argument("--clobber-versions", action="store_true", dest="clobberVersions", default=False,
495  help=("backup and then overwrite existing package versions instead of checking"
496  "them (safe with -j, but not all other forms of parallel execution)"))
497  self.add_argument("--no-versions", action="store_true", dest="noVersions", default=False,
498  help="don't check package versions; useful for development")
499  lsstLog.configure_prop("""
500 log4j.rootLogger=INFO, A1
501 log4j.appender.A1=ConsoleAppender
502 log4j.appender.A1.Target=System.out
503 log4j.appender.A1.layout=PatternLayout
504 log4j.appender.A1.layout.ConversionPattern=%c %p: %m%n
505 """)
506 
507  # Forward all Python logging to lsst.log
508  lgr = logging.getLogger()
509  lgr.setLevel(logging.INFO) # same as in log4cxx config above
510  lgr.addHandler(lsstLog.LogHandler())
511 

Member Function Documentation

◆ add_id_argument()

def lsst.pipe.base.argumentParser.ArgumentParser.add_id_argument (   self,
  name,
  datasetType,
  help,
  level = None,
  doMakeDataRefList = True,
  ContainerClass = DataIdContainer 
)
Add a data ID argument.


Parameters
----------
name : `str`
    Data ID argument (including leading dashes, if wanted).
datasetType : `str` or `DynamicDatasetType`-type
    Type of dataset. Supply a string for a fixed dataset type.
    For a dynamically determined dataset type, supply
    a `DynamicDatasetType`, such a `DatasetArgument`.
help : `str`
    Help string for the argument.
level : `str`
    The lowest hierarchy level to descend to for this dataset type,
    for example `"amp"` for `"raw"` or `"ccd"` for `"calexp"`.
    Use `""` to use the mapper's default for the dataset type.
    Some container classes may also support `None`, which means
    the level should not be restricted; however the default class,
    `DataIdContainer`, does not support `None`.
doMakeDataRefList : bool, optional
    If `True` (default), construct data references.
ContainerClass : `class`, optional
Class to contain data IDs and data references; the default class
`DataIdContainer` will work for many, but not all, cases.
For example if the dataset type is specified on the command line
then use `DynamicDatasetType`.

Notes
-----
If ``datasetType`` is an instance of `DatasetArgument`,
then add a second argument to specify the dataset type.

The associated data is put into ``namespace.<dataIdArgument.name>``
as an instance of `ContainerClass`; the container includes fields:

- ``idList``: a list of data ID dicts.
- ``refList``: a list of `~lsst.daf.persistence.Butler`
    data references (empty if ``doMakeDataRefList`` is  `False`).

Definition at line 512 of file argumentParser.py.

513  ContainerClass=DataIdContainer):
514  """Add a data ID argument.
515 
516 
517  Parameters
518  ----------
519  name : `str`
520  Data ID argument (including leading dashes, if wanted).
521  datasetType : `str` or `DynamicDatasetType`-type
522  Type of dataset. Supply a string for a fixed dataset type.
523  For a dynamically determined dataset type, supply
524  a `DynamicDatasetType`, such a `DatasetArgument`.
525  help : `str`
526  Help string for the argument.
527  level : `str`
528  The lowest hierarchy level to descend to for this dataset type,
529  for example `"amp"` for `"raw"` or `"ccd"` for `"calexp"`.
530  Use `""` to use the mapper's default for the dataset type.
531  Some container classes may also support `None`, which means
532  the level should not be restricted; however the default class,
533  `DataIdContainer`, does not support `None`.
534  doMakeDataRefList : bool, optional
535  If `True` (default), construct data references.
536  ContainerClass : `class`, optional
537  Class to contain data IDs and data references; the default class
538  `DataIdContainer` will work for many, but not all, cases.
539  For example if the dataset type is specified on the command line
540  then use `DynamicDatasetType`.
541 
542  Notes
543  -----
544  If ``datasetType`` is an instance of `DatasetArgument`,
545  then add a second argument to specify the dataset type.
546 
547  The associated data is put into ``namespace.<dataIdArgument.name>``
548  as an instance of `ContainerClass`; the container includes fields:
549 
550  - ``idList``: a list of data ID dicts.
551  - ``refList``: a list of `~lsst.daf.persistence.Butler`
552  data references (empty if ``doMakeDataRefList`` is `False`).
553  """
554  argName = name.lstrip("-")
555 
556  if argName in self._dataIdArgDict:
557  raise RuntimeError(f"Data ID argument {name} already exists")
558  if argName in set(("camera", "config", "butler", "log", "obsPkg")):
559  raise RuntimeError(f"Data ID argument {name} is a reserved name")
560 
561  self.add_argument(name, nargs="*", action=IdValueAction, help=help,
562  metavar="KEY=VALUE1[^VALUE2[^VALUE3...]")
563 
564  dataIdArgument = DataIdArgument(
565  name=argName,
566  datasetType=datasetType,
567  level=level,
568  doMakeDataRefList=doMakeDataRefList,
569  ContainerClass=ContainerClass,
570  )
571 
572  if dataIdArgument.isDynamicDatasetType:
573  datasetType.addArgument(parser=self, idName=argName)
574 
575  self._dataIdArgDict[argName] = dataIdArgument
576 
daf::base::PropertySet * set
Definition: fits.cc:912

◆ addReuseOption()

def lsst.pipe.base.argumentParser.ArgumentParser.addReuseOption (   self,
  choices 
)
Add a "--reuse-outputs-from SUBTASK" option to the argument
parser.

CmdLineTasks that can be restarted at an intermediate step using
outputs from earlier (but still internal) steps should use this
method to allow the user to control whether that happens when
outputs from earlier steps are present.

Parameters
----------
choices : sequence
    A sequence of string names (by convention, top-level subtasks)
    that identify the steps that could be skipped when their
    outputs are already present.  The list is ordered, so when the
    user specifies one step on the command line, all previous steps
    may be skipped as well.  In addition to the choices provided,
    users may pass "all" to indicate that all steps may be thus
    skipped.

When this method is called, the ``namespace`` object returned by
``parse_args`` will contain a ``reuse`` attribute containing
a list of all steps that should be skipped if their outputs
are already present.
If no steps should be skipped, the ``reuse`` will be an empty list.

Definition at line 884 of file argumentParser.py.

884  def addReuseOption(self, choices):
885  """Add a "--reuse-outputs-from SUBTASK" option to the argument
886  parser.
887 
888  CmdLineTasks that can be restarted at an intermediate step using
889  outputs from earlier (but still internal) steps should use this
890  method to allow the user to control whether that happens when
891  outputs from earlier steps are present.
892 
893  Parameters
894  ----------
895  choices : sequence
896  A sequence of string names (by convention, top-level subtasks)
897  that identify the steps that could be skipped when their
898  outputs are already present. The list is ordered, so when the
899  user specifies one step on the command line, all previous steps
900  may be skipped as well. In addition to the choices provided,
901  users may pass "all" to indicate that all steps may be thus
902  skipped.
903 
904  When this method is called, the ``namespace`` object returned by
905  ``parse_args`` will contain a ``reuse`` attribute containing
906  a list of all steps that should be skipped if their outputs
907  are already present.
908  If no steps should be skipped, the ``reuse`` will be an empty list.
909  """
910  choices = list(choices)
911  choices.append("all")
912  self.add_argument("--reuse-outputs-from", dest="reuse", choices=choices,
913  default=[], action=ReuseAction,
914  help=("Skip the given subtask and its predecessors and reuse their outputs "
915  "if those outputs already exist. Use 'all' to specify all subtasks."))
916 
917 
daf::base::PropertyList * list
Definition: fits.cc:913

◆ convert_arg_line_to_args()

def lsst.pipe.base.argumentParser.ArgumentParser.convert_arg_line_to_args (   self,
  arg_line 
)
Allow files of arguments referenced by ``@<path>`` to contain
multiple values on each line.

Parameters
----------
arg_line : `str`
    Line of text read from an argument file.

Definition at line 867 of file argumentParser.py.

867  def convert_arg_line_to_args(self, arg_line):
868  """Allow files of arguments referenced by ``@<path>`` to contain
869  multiple values on each line.
870 
871  Parameters
872  ----------
873  arg_line : `str`
874  Line of text read from an argument file.
875  """
876  arg_line = arg_line.strip()
877  if not arg_line or arg_line.startswith("#"):
878  return
879  for arg in shlex.split(arg_line, comments=True, posix=True):
880  if not arg.strip():
881  continue
882  yield arg
883 

◆ handleCamera()

def lsst.pipe.base.argumentParser.ArgumentParser.handleCamera (   self,
  namespace 
)
Perform camera-specific operations before parsing the command-line.

Parameters
----------
namespace : `argparse.Namespace`
    Namespace (an ) with the following fields:

    - ``camera``: the camera name.
    - ``config``: the config passed to parse_args, with no overrides
      applied.
    - ``obsPkg``: the ``obs_`` package for this camera.
    - ``log``: a `lsst.log` Log.

Notes
-----
The default implementation does nothing.

Definition at line 847 of file argumentParser.py.

847  def handleCamera(self, namespace):
848  """Perform camera-specific operations before parsing the command-line.
849 
850  Parameters
851  ----------
852  namespace : `argparse.Namespace`
853  Namespace (an ) with the following fields:
854 
855  - ``camera``: the camera name.
856  - ``config``: the config passed to parse_args, with no overrides
857  applied.
858  - ``obsPkg``: the ``obs_`` package for this camera.
859  - ``log``: a `lsst.log` Log.
860 
861  Notes
862  -----
863  The default implementation does nothing.
864  """
865  pass
866 

◆ parse_args()

def lsst.pipe.base.argumentParser.ArgumentParser.parse_args (   self,
  config,
  args = None,
  log = None,
  override = None 
)
Parse arguments for a command-line task.

Parameters
----------
config : `lsst.pex.config.Config`
    Config for the task being run.
args : `list`, optional
    Argument list; if `None` then ``sys.argv[1:]`` is used.
log : `lsst.log.Log`, optional
    `~lsst.log.Log` instance; if `None` use the default log.
override : callable, optional
    A config override function. It must take the root config object
    as its only argument and must modify the config in place.
    This function is called after camera-specific overrides files
    are applied, and before command-line config overrides
    are applied (thus allowing the user the final word).

Returns
-------
namespace : `argparse.Namespace`
    A `~argparse.Namespace` instance containing fields:

    - ``camera``: camera name.
    - ``config``: the supplied config with all overrides applied,
        validated and frozen.
    - ``butler``: a `lsst.daf.persistence.Butler` for the data.
    - An entry for each of the data ID arguments registered by
        `add_id_argument`, of the type passed to its ``ContainerClass``
        keyword (`~lsst.pipe.base.DataIdContainer` by default). It
        includes public elements ``idList`` and ``refList``.
    - ``log``: a `lsst.log` Log.
    - An entry for each command-line argument,
        with the following exceptions:

      - config is the supplied config, suitably updated.
      - configfile, id and loglevel are all missing.
    - ``obsPkg``: name of the ``obs_`` package for this camera.

Definition at line 577 of file argumentParser.py.

577  def parse_args(self, config, args=None, log=None, override=None):
578  """Parse arguments for a command-line task.
579 
580  Parameters
581  ----------
582  config : `lsst.pex.config.Config`
583  Config for the task being run.
584  args : `list`, optional
585  Argument list; if `None` then ``sys.argv[1:]`` is used.
586  log : `lsst.log.Log`, optional
587  `~lsst.log.Log` instance; if `None` use the default log.
588  override : callable, optional
589  A config override function. It must take the root config object
590  as its only argument and must modify the config in place.
591  This function is called after camera-specific overrides files
592  are applied, and before command-line config overrides
593  are applied (thus allowing the user the final word).
594 
595  Returns
596  -------
597  namespace : `argparse.Namespace`
598  A `~argparse.Namespace` instance containing fields:
599 
600  - ``camera``: camera name.
601  - ``config``: the supplied config with all overrides applied,
602  validated and frozen.
603  - ``butler``: a `lsst.daf.persistence.Butler` for the data.
604  - An entry for each of the data ID arguments registered by
605  `add_id_argument`, of the type passed to its ``ContainerClass``
606  keyword (`~lsst.pipe.base.DataIdContainer` by default). It
607  includes public elements ``idList`` and ``refList``.
608  - ``log``: a `lsst.log` Log.
609  - An entry for each command-line argument,
610  with the following exceptions:
611 
612  - config is the supplied config, suitably updated.
613  - configfile, id and loglevel are all missing.
614  - ``obsPkg``: name of the ``obs_`` package for this camera.
615  """
616  if args is None:
617  args = sys.argv[1:]
618 
619  if len(args) < 1 or args[0].startswith("-") or args[0].startswith("@"):
620  self.print_help()
621  if len(args) == 1 and args[0] in ("-h", "--help"):
622  self.exit()
623  else:
624  self.exit(f"{self.prog}: error: Must specify input as first argument")
625 
626  # Note that --rerun may change namespace.input, but if it does
627  # we verify that the new input has the same mapper class.
628  namespace = argparse.Namespace()
629  namespace.input = _fixPath(DEFAULT_INPUT_NAME, args[0])
630  if not os.path.isdir(namespace.input):
631  self.error(f"Error: input={namespace.input!r} not found")
632 
633  namespace.config = config
634  namespace.log = log if log is not None else lsstLog.Log.getDefaultLogger()
635  mapperClass = dafPersist.Butler.getMapperClass(namespace.input)
636  if mapperClass is None:
637  self.error(f"Error: no mapper specified for input repo {namespace.input!r}")
638 
639  namespace.camera = mapperClass.getCameraName()
640  namespace.obsPkg = mapperClass.getPackageName()
641 
642  self.handleCamera(namespace)
643 
644  self._applyInitialOverrides(namespace)
645  if override is not None:
646  override(namespace.config)
647 
648  # Add data ID containers to namespace
649  for dataIdArgument in self._dataIdArgDict.values():
650  setattr(namespace, dataIdArgument.name, dataIdArgument.ContainerClass(level=dataIdArgument.level))
651 
652  namespace = argparse.ArgumentParser.parse_args(self, args=args, namespace=namespace)
653  del namespace.configfile
654 
655  self._parseDirectories(namespace)
656 
657  if namespace.clobberOutput:
658  if namespace.output is None:
659  self.error("--clobber-output is only valid with --output or --rerun")
660  elif namespace.output == namespace.input:
661  self.error("--clobber-output is not valid when the output and input repos are the same")
662  if os.path.exists(namespace.output):
663  namespace.log.info("Removing output repo %s for --clobber-output", namespace.output)
664  shutil.rmtree(namespace.output)
665 
666  namespace.log.debug("input=%s", namespace.input)
667  namespace.log.debug("calib=%s", namespace.calib)
668  namespace.log.debug("output=%s", namespace.output)
669 
670  obeyShowArgument(namespace.show, namespace.config, exit=False)
671 
672  # No environment variable or --output or --rerun specified.
673  if self.requireOutput and namespace.output is None and namespace.rerun is None:
674  self.error("no output directory specified.\n"
675  "An output directory must be specified with the --output or --rerun\n"
676  "command-line arguments.\n")
677 
678  butlerArgs = {} # common arguments for butler elements
679  if namespace.calib:
680  butlerArgs = {'mapperArgs': {'calibRoot': namespace.calib}}
681  if namespace.output:
682  outputs = {'root': namespace.output, 'mode': 'rw'}
683  inputs = {'root': namespace.input}
684  inputs.update(butlerArgs)
685  outputs.update(butlerArgs)
686  namespace.butler = dafPersist.Butler(inputs=inputs, outputs=outputs)
687  else:
688  outputs = {'root': namespace.input, 'mode': 'rw'}
689  outputs.update(butlerArgs)
690  namespace.butler = dafPersist.Butler(outputs=outputs)
691 
692  # convert data in each of the identifier lists to proper types
693  # this is done after constructing the butler,
694  # hence after parsing the command line,
695  # because it takes a long time to construct a butler
696  self._processDataIds(namespace)
697  if "data" in namespace.show:
698  for dataIdName in self._dataIdArgDict.keys():
699  for dataRef in getattr(namespace, dataIdName).refList:
700  print(f"{dataIdName} dataRef.dataId = {dataRef.dataId}")
701 
702  if namespace.show and "run" not in namespace.show:
703  sys.exit(0)
704 
705  if namespace.debug:
706  try:
707  import debug
708  assert debug # silence pyflakes
709  except ImportError:
710  print("Warning: no 'debug' module found", file=sys.stderr)
711  namespace.debug = False
712 
713  del namespace.loglevel
714 
715  if namespace.longlog:
716  lsstLog.configure_prop("""
717 log4j.rootLogger=INFO, A1
718 log4j.appender.A1=ConsoleAppender
719 log4j.appender.A1.Target=System.out
720 log4j.appender.A1.layout=PatternLayout
721 log4j.appender.A1.layout.ConversionPattern=%-5p %d{yyyy-MM-ddTHH:mm:ss.SSSZ} %c (%X{LABEL})(%F:%L)- %m%n
722 """)
723  del namespace.longlog
724 
725  namespace.config.validate()
726  namespace.config.freeze()
727 
728  return namespace
729 
def obeyShowArgument(showOpts, config=None, exit=False)

Member Data Documentation

◆ requireOutput

bool lsst.pipe.base.argumentParser.ArgumentParser.requireOutput = True
static

Definition at line 432 of file argumentParser.py.


The documentation for this class was generated from the following file: