docs: def __query(p, k, v, accepted_keys=None, required_values=None, path=None, exact=True):
      """
      Query function given to visit method
  
      :param p: visited path in tuple form
      :param k: visited key
      :param v: visited value
      :param accepted_keys: list of keys where one must match k to satisfy query.
      :param required_values: list of values where one must match v to satisfy query
      :param path: exact path in tuple form that must match p to satisfy query
      :param exact: if True then key and value match uses contains function instead of ==
      :return: True if all criteria are satisfied, otherwise False
      """
  
      # if not k:
      #     print '__query p k:', p, k
      # print p, k, accepted_keys, required_values, path, exact
      def as_values_iterable(v):
          if isinstance(v, dict):
              return v.values()
          elif isinstance(v, six.string_types):
              return [v]
          else:
              # assume is already some iterable type
              return v
  
      if path and path != p:
          return False
  
      if accepted_keys:
          if isinstance(accepted_keys, six.string_types):
              accepted_keys = [accepted_keys]
          if len([akey for akey in accepted_keys if akey == k or (not exact and akey in k)]) == 0:
              return False
  
      if required_values:
          if isinstance(required_values, six.string_types):
              required_values = [required_values]
          # Find all terms in the vfilter that have a match somewhere in the values of the v dict. If the
          # list is shorter than vfilter then some terms did not match and this v fails the test.
          if len(required_values) > len([term for term in required_values for nv in as_values_iterable(v) if term == nv or (not exact and term in nv)]):
              return False
  
      return True