docs: def generate_raml_resource_types(module):
      """Compile a Pale module's resource documentation into RAML format.
  
      RAML calls Pale resources 'resourceTypes'. This function converts Pale
      resources into the RAML resourceType format.
  
      The returned string should be appended to the RAML documentation string
      before it is returned.
      """
  
      from pale import extract_endpoints, extract_resources, is_pale_module
      if not is_pale_module(module):
          raise ValueError(
              """The passed in `module` (%s) is not a pale module. `paledoc`
              only works on modules with a `_module_type` set to equal
              `pale.ImplementationModule`.""")
  
      module_resource_types = extract_resources(module)
      raml_resource_types_unsorted = {}
  
      for resource in module_resource_types:
          resource_name = resource.__name__
          raml_resource_types_unsorted[resource_name] = document_resource(resource)
          if hasattr(resource, "_description"):
              modified_description = clean_description(resource._description)
              raml_resource_types_unsorted[resource_name]["description"] = modified_description
  
      raml_resource_types_doc = OrderedDict(sorted(raml_resource_types_unsorted.items(), key=lambda t: t[0]))
  
      output = StringIO()
      indent = "  "  # 2
  
      # blacklist of resources to ignore
      ignored_resources = []
  
      for resource_type in raml_resource_types_doc:
  
          this_resource_type = raml_resource_types_doc[resource_type]
  
          # add the name, ignoring the blacklist
          if resource_type not in ignored_resources:
              output.write(indent + resource_type + ":\n")
  
              indent += "  "  # 4
  
              # add the description
              if this_resource_type.get("description") != None:
                  modified_description = clean_description(this_resource_type["description"])
                  output.write(indent + "description: " + modified_description + "\n")
  
              # if there are no fields, set type directly:
              if len(this_resource_type["fields"]) == 0:
                  this_type = "object"
                  if this_resource_type.get("_underlying_model") != None:
                      if this_resource_type["_underlying_model"] != object:
                          if hasattr(this_resource_type._underlying_model, "_value_type") \
                          and this_resource_type["_underlying_model"]._value_type not in ignored_resources:
                              this_type = this_resource_type["_underlying_model"]._value_type
                  output.write(indent + "type: " + this_type + "\n")
  
                  indent = indent[:-2] # 2
  
              # if there are fields, use them as the properties, which implies type = object
              else:
  
                  output.write(indent + "properties:\n")
                  indent += "  "  # 6
  
                  sorted_fields = OrderedDict(sorted(this_resource_type["fields"].items(), key=lambda t: t[0]))
  
  
                  # add the field name, a.k.a. RAML type name
                  for field in sorted_fields:
                      output.write(indent + field + ":\n")
  
                      # add the query parameters, a.k.a. RAML properties
                      properties = sorted_fields[field]
  
                      indent += "  "  # 8
  
                      # if this type is a list of other types, set it to type 'array' and note the item types
                      # if not, add the type from the Pale type
                      if "_underlying_model" in this_resource_type and this_resource_type["_underlying_model"] == object:
                          output.write(indent + "type: base\n")
                      elif "item_type" in properties:
                          output.write(indent + "type: array\n")
                          output.write(indent + "items: " + properties["item_type"] + "\n")
                      elif "type" in properties:
                          output.write(indent + "type: " + properties["type"].replace(" ", "_") + "\n")
  
                      # if extended description exists, strip newlines and whitespace and add as description
                      if properties.get("extended_description") != None:
                          modified_description = clean_description(properties["extended_description"])
                          output.write(indent + "description: " + modified_description + "\n")
                      # otherwise, use description
                      elif properties.get("description") != None:
                          modified_description = clean_description(properties["description"])
                          output.write(indent + "description: " + modified_description + "\n")
  
                      if properties.get("default_fields") != None:
                          output.write(indent + "properties:\n")
                          indent += "  " # 10
                          for field_name in sorted(properties["default_fields"]):
                              # @TODO check if every default field is actually a string type
                              output.write(indent + field_name + ": string\n")
  
                          indent = indent[:-2] # 8
  
                      indent = indent[:-2] # 6
  
                  indent = indent[:-4] # 2
  
  
      raml_resource_types = output.getvalue()
      output.close()
      return raml_resource_types