class_docstr: Build introspection data for operations.
  
  Make an operation, introspect it, and build a structure representing
  everything we know about it.
class_docstr_tok: ["Build","introspection","data","for","operations",".","Make","an","operation",",","introspect","it",",","and","build","a","structure","representing","everything","we","know","about","it","."]
code: def __init__(self, operation_name):
      op = Operation.new_from_name(operation_name)
  
      self.description = op.get_description()
      self.flags = vips_lib.vips_operation_get_flags(op.pointer)
  
      # build a list of constructor arg [name, flags] pairs in arg order
      arguments = []
  
      def add_args(name, flags):
          if (flags & _CONSTRUCT) != 0:
              # libvips uses '-' to separate parts of arg names, but we
              # need '_' for Python
              name = name.replace("-", "_")
              arguments.append([name, flags])
  
      if at_least_libvips(8, 7):
          p_names = ffi.new("char**[1]")
          p_flags = ffi.new("int*[1]")
          p_n_args = ffi.new("int[1]")
          result = vips_lib.vips_object_get_args(
              op.vobject, p_names, p_flags, p_n_args
          )
          if result != 0:
              raise Error("unable to get arguments from operation")
          p_names = p_names[0]
          p_flags = p_flags[0]
          n_args = p_n_args[0]
  
          for i in range(0, n_args):
              add_args(_to_string(p_names[i]), p_flags[i])
      else:
  
          def add_construct(
              self, pspec, argument_class, argument_instance, a, b
          ):
              add_args(_to_string(pspec.name), argument_class.flags)
              return ffi.NULL
  
          cb = ffi.callback("VipsArgumentMapFn", add_construct)
          vips_lib.vips_argument_map(op.vobject, cb, ffi.NULL, ffi.NULL)
  
      # logger.debug('arguments = %s', self.arguments)
  
      # build a hash from arg name to detailed arg information
      self.details = {}
      for name, flags in arguments:
          self.details[name] = {
              "name": name,
              "flags": flags,
              "blurb": op.get_blurb(name),
              "type": op.get_typeof(name),
          }
  
      # lists of arg names by category
      self.required_input = []
      self.optional_input = []
      self.required_output = []
      self.optional_output = []
  
      # same, but with deprecated args filtered out ... this is the set we
      # show in documentation
      self.doc_optional_input = []
      self.doc_optional_output = []
  
      for name, flags in arguments:
          if (
              (flags & _INPUT) != 0
              and (flags & _REQUIRED) != 0
              and (flags & _DEPRECATED) == 0
          ):
              self.required_input.append(name)
  
              # required inputs which we MODIFY are also required outputs
              if (flags & _MODIFY) != 0:
                  self.required_output.append(name)
  
          if (
              (flags & _OUTPUT) != 0
              and (flags & _REQUIRED) != 0
              and (flags & _DEPRECATED) == 0
          ):
              self.required_output.append(name)
  
          # deprecated optional args get on to the main arg lists, but are
          # filtered from the documented set
          if (flags & _INPUT) != 0 and (flags & _REQUIRED) == 0:
              self.optional_input.append(name)
  
              if (flags & _DEPRECATED) == 0:
                  self.doc_optional_input.append(name)
  
          if (flags & _OUTPUT) != 0 and (flags & _REQUIRED) == 0:
              self.optional_output.append(name)
  
              if (flags & _DEPRECATED) == 0:
                  self.doc_optional_output.append(name)
  
      # find the first required input image arg, if any ... that will be self
      self.member_x = None
      for name in self.required_input:
          details = self.details[name]
          if details["type"] == GValue.image_type:
              self.member_x = name
              break
  
      # method args are required args, but without the image they are a
      # method on
      if self.member_x is not None:
          self.method_args = list(self.required_input)
          self.method_args.remove(self.member_x)
      else:
          self.method_args = self.required_input
  
imports: from __future__ import division, print_function
  import logging
  import pyvips
  from pyvips import ffi, vips_lib, Error, _to_bytes, _to_string, GValue, type_map, type_from_name, nickname_find, at_least_libvips
label_desc: Use image node_id 1 to create a new Introspect object from inherited base classes: object with example: obj = Introspect(operation_name)