docs: def factory(
          name,
          desc,
          type,
          subtypes=None,
          required=True,
          default=None,
          ctor=None,
          hide=False,
      ):
          """
          desc: >
              Creates a DocStringArg and recursively includes child
              docstrings if they are not JSON types.
          args:
              -   name: name
                  desc: The name of the argument
                  type: str
              -   name: desc
                  desc: A description of the argument
                  type: str
              -   name: type
                  desc: The type of the argument
                  type: str
              -   name: subtypes
                  desc: >
                      If @type is a list, dict or other data structure,
                      the contained objects should be of this type.
                      This should be a list of one item for lists, or a list
                      of 2 items for a dict.  More than 2 items is not
                      supported.
                  type: list
                  required: false
                  default: None
              -   name: required
                  desc: >
                      True if this is a mandatory argument, False if it
                      has a default value.  If False, @default should be
                      set appropriately.
                  type: bool
                  required: false
                  default: true
              -   name: default
                  desc: >
                      The default value for this argument.  This is ignored
                      if @required == True
                  type: any
              -   name: ctor
                  desc: >
                      Only use if @type is a class instance and not a JSON type
                      The constructor that the JSON object will be
                      unmarshalled to.  Either the Class.__init__, or a
                      factory function or factory static method.
                      Use the full path: module.submodule.Class.__init__
                  type: str
                  required: false
                  default: None
              -   name: hide
                  desc: >
                      Don't display this argument to the user.  Useful for
                      not showing arguments that are excluded from marshalling.
                      Note that this is only a hint to the client that will
                      render the JSON, the argument will still be sent
                  required: false
                  type: bool
                  default: false
          returns:
              desc: A DocStringArg instance with recursively populated
                    @docstring attributes for child arguments
              type: pymarshal.api_docs.docstring.DocStringArg
          """
          if ctor:
              type_assert(ctor, str)
              module_name, cls_name, method_name = ctor.rsplit('.', 2)
              module = importlib.import_module(module_name)
              cls = getattr(module, cls_name)
              method = getattr(cls, method_name)
              docstring = DocString.from_ctor(method)
          else:
              docstring = None
  
          return DocStringArg(
              name,
              desc,
              type,
              subtypes,
              required,
              default,
              docstring=docstring,
              hide=hide,
          )