class_docstr: Class for checking all interface specifications
class_docstr_tok: ["Class","for","checking","all","interface","specifications"]
docstr: Check input and output specs in an uri
  
  Parameters
  ----------
  uri : string
      python location of module - e.g 'sphinx.builder'
  
  Returns
  -------
docstr_tok: ["Check","input","and","output","specs","in","an","uri","Parameters","--","--","--","--","--","uri",":","string","python","location","of","module","-","e.g","'sphinx.builder'","Returns","--","--","--","-"]
code: def test_specs(self, uri):
      """Check input and output specs in an uri
  
      Parameters
      ----------
      uri : string
          python location of module - e.g 'sphinx.builder'
  
      Returns
      -------
      """
      from nipype.interfaces.base import BaseInterface
  
      # get the names of all classes and functions
      _, classes = self._parse_module(uri)
      if not classes:
          # print 'WARNING: Empty -',uri  # dbg
          return None
  
      # Make a shorter version of the uri that omits the package name for
      # titles
      allowed_keys = [
          "desc",
          "genfile",
          "xor",
          "requires",
          "desc",
          "nohash",
          "argstr",
          "position",
          "mandatory",
          "copyfile",
          "usedefault",
          "sep",
          "hash_files",
          "deprecated",
          "new_name",
          "min_ver",
          "max_ver",
          "name_source",
          "name_template",
          "keep_extension",
          "units",
          "output_name",
          "extensions",
      ]
      in_built = [
          "type",
          "copy",
          "parent",
          "instance_handler",
          "comparison_mode",
          "array",
          "default",
          "editor",
      ]
      bad_specs = []
      for c in classes:
          __import__(uri)
          try:
              with warnings.catch_warnings():
                  warnings.simplefilter("ignore")
                  classinst = sys.modules[uri].__dict__[c]
          except Exception:
              continue
  
          if not issubclass(classinst, BaseInterface):
              continue
          testdir = os.path.join(*(uri.split(".")[:-1] + ["tests"]))
          if not os.path.exists(testdir):
              os.makedirs(testdir)
          nonautotest = os.path.join(testdir, "test_%s.py" % c)
          testfile = os.path.join(testdir, "test_auto_%s.py" % c)
          if os.path.exists(testfile):
              os.unlink(testfile)
  
          if not os.path.exists(nonautotest):
              cmd = [
                  "# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT",
                  "from ..{} import {}".format(uri.split(".")[-1], c),
                  "",
              ]
              cmd.append("\ndef test_%s_inputs():" % c)
              input_fields = ""
              for traitname, trait in sorted(
                  classinst.input_spec().traits(transient=None).items()
              ):
                  input_fields += "%s=dict(" % traitname
                  for key, value in sorted(trait.__dict__.items()):
                      if key in in_built or key == "desc":
                          continue
                      input_fields += "{}={},\n    ".format(
                          key,
                          self._normalize_repr(value),
                      )
                  input_fields += "),\n    "
              cmd += ["    input_map = dict(%s)" % input_fields]
              cmd += ["    inputs = %s.input_spec()" % c]
              cmd += [
                  """
      for key, metadata in list(input_map.items()):
          for metakey, value in list(metadata.items()):
              assert getattr(inputs.traits()[key], metakey) == value"""
              ]
  
              fmt_cmd = black.format_str(
                  "\n".join(cmd), mode=black.FileMode()
              )
              with open(testfile, "w") as fp:
                  fp.writelines(fmt_cmd)
          else:
              print("%s has nonautotest" % c)
  
          for traitname, trait in sorted(
              classinst.input_spec().traits(transient=None).items()
          ):
              for key in sorted(trait.__dict__):
                  if key in in_built:
                      continue
                  parent_metadata = []
                  if "parent" in trait.__dict__:
                      parent_metadata = list(
                          getattr(trait, "parent").__dict__.keys()
                      )
                  if (
                      key
                      not in allowed_keys
                      + classinst._additional_metadata
                      + parent_metadata
                  ):
                      bad_specs.append(
                          [uri, c, "Inputs", traitname, key]
                      )
                  if (
                      key == "mandatory"
                      and trait.mandatory is not None
                      and not trait.mandatory
                  ):
                      bad_specs.append(
                          [
                              uri,
                              c,
                              "Inputs",
                              traitname,
                              "mandatory=False",
                          ]
                      )
                  if (
                      key == "usedefault"
                      and trait.__dict__[key] == False
                  ):
                      bad_specs.append(
                          [
                              uri,
                              c,
                              "Inputs",
                              traitname,
                              "usedefault=False",
                          ]
                      )
              # checking if traits that have default_value different that the trits default one
              # also have `usedefault` specified;
              # excluding TraitCompound
              # excluding Enum: always has default value (the first value)
              # excluding Tuple: takes tuple of inner traits default values as default, but doesn't use it
              # for Range assuming that if default == low, it's likely that usedefault should be False
              # (for Range traits takes low as a default default
              if (
                  trait.trait_type.__class__.__name__
                  not in ["TraitCompound", "Tuple", "Enum"]
                  and trait.default
                  and "usedefault" not in trait.__dict__
                  and "requires" not in trait.__dict__
                  and "xor" not in trait.__dict__
              ):
                  if (
                      trait.trait_type.__class__.__name__ == "Range"
                      and trait.default == trait.trait_type._low
                  ):
                      continue
                  bad_specs.append(
                      [
                          uri,
                          c,
                          "Inputs",
                          traitname,
                          "default value is set, no value for usedefault",
                      ]
                  )
  
          if not classinst.output_spec:
              continue
  
          if not os.path.exists(nonautotest):
              cmd = ["\ndef test_%s_outputs():" % c]
              input_fields = ""
              for traitname, trait in sorted(
                  classinst.output_spec().traits(transient=None).items()
              ):
                  input_fields += "%s=dict(" % traitname
                  for key, value in sorted(trait.__dict__.items()):
                      if key in in_built or key == "desc":
                          continue
                      input_fields += "{}={},\n    ".format(
                          key,
                          self._normalize_repr(value),
                      )
                  input_fields += "),\n    "
              cmd += ["    output_map = dict(%s)" % input_fields]
              cmd += ["    outputs = %s.output_spec()" % c]
              cmd += [
                  """
      for key, metadata in list(output_map.items()):
          for metakey, value in list(metadata.items()):
              assert getattr(outputs.traits()[key], metakey) == value"""
              ]
              fmt_cmd = black.format_str(
                  "\n".join(cmd), mode=black.FileMode()
              )
              with open(testfile, "a") as fp:
                  fp.writelines("\n\n" + fmt_cmd)
  
          for traitname, trait in sorted(
              classinst.output_spec().traits(transient=None).items()
          ):
              for key in sorted(trait.__dict__):
                  if key in in_built:
                      continue
                  parent_metadata = []
                  if "parent" in trait.__dict__:
                      parent_metadata = list(
                          getattr(trait, "parent").__dict__.keys()
                      )
                  if (
                      key
                      not in allowed_keys
                      + classinst._additional_metadata
                      + parent_metadata
                  ):
                      bad_specs.append(
                          [uri, c, "Outputs", traitname, key]
                      )
      return bad_specs
  
file_path: nipype/tools/checkspecs.py
imports: import os
  import re
  import sys
  import warnings
  import black
label_desc: Use image node_id 10 for calling the InterfaceChecker obj's underlying member method code with example usage: obj.test_specs(uri) and returns: bad_specs, None