code: def iter(self, keyed=False, extended=False, cast=True, relations=False):
          
  
          # Prepare unique checks
          if cast:
              unique_fields_cache = {}
              if self.schema:
                  unique_fields_cache = _create_unique_fields_cache(self.schema)
  
          # Open/iterate stream
          self.__stream.open()
          iterator = self.__stream.iter(extended=True)
          iterator = self.__apply_processors(iterator, cast=cast)
          for row_number, headers, row in iterator:
  
              # Get headers
              if not self.__headers:
                  self.__headers = headers
  
              # Check headers
              if cast:
                  if self.schema and self.headers:
                      if self.headers != self.schema.field_names:
                          self.__stream.close()
                          message = 'Table headers don\'t match schema field names'
                          raise exceptions.CastError(message)
  
              # Check unique
              if cast:
                  for indexes, cache in unique_fields_cache.items():
                      values = tuple(value for i, value in enumerate(row) if i in indexes)
                      if not all(map(lambda value: value is None, values)):
                          if values in cache['data']:
                              self.__stream.close()
                              message = 'Field(s) "%s" duplicates in row "%s"'
                              message = message % (cache['name'], row_number)
                              raise exceptions.CastError(message)
                          cache['data'].add(values)
  
              # Resolve relations
              if relations:
                  if self.schema:
                      for foreign_key in self.schema.foreign_keys:
                          row = _resolve_relations(row, headers, relations, foreign_key)
                          if row is None:
                              self.__stream.close()
                              message = 'Foreign key "%s" violation in row "%s"'
                              message = message % (foreign_key['fields'], row_number)
                              raise exceptions.RelationError(message)
  
              # Form row
              if extended:
                  yield (row_number, headers, row)
              elif keyed:
                  yield dict(zip(headers, row))
              else:
                  yield row
  
          # Close stream
          self.__stream.close()
docs: https://github.com/frictionlessdata/tableschema-py#schema