text: """
  This module contains CleanCat fields specific to SQLAlchemy. SQLA is not
  a required dependency, hence to use these fields, you'll have to import
  them via `from cleancat.sqla import ...`.
  """
  
  from sqlalchemy import inspect
  
  from .base import EmbeddedReference, Reference, ReferenceNotFoundError
  
  
  def object_as_dict(obj):
      """Turn an SQLAlchemy model into a dict of field names and values.
  
      Based on https://stackoverflow.com/a/37350445/1579058
      """
      return {
          c.key: getattr(obj, c.key) for c in inspect(obj).mapper.column_attrs
      }
  
  
  class SQLAEmbeddedReference(EmbeddedReference):
      """
      Represents an embedded reference where the object class is an SQLAlchemy
      model.
  
      Examples of passed data and how it's handled:
      {'id': 'existing_id', 'foo': 'bar'} -> updates an existing model
      {'id': 'non-existing_id', 'foo': 'bar'} -> fails bcos the ID is not valid
      {'foo': 'bar'} -> creates a new model instance
      """
  
      def fetch_existing(self, pk):
          model_cls = self.object_class
          model = model_cls.query.get(pk)
          if not model:
              raise ReferenceNotFoundError
          return model
  
      def get_orig_data_from_existing(self, obj):
          return object_as_dict(obj)
  
  
  class SQLAReference(Reference):
      """
      Represents a reference to an SQLAlchemy model. Expects an ID string as
      input and returns a cleaned model instance (verifying that it exists
      first).
      """
  
      def __init__(self, object_class, pk_field='id', **kwargs):
          self.pk_field = pk_field
          super(SQLAReference, self).__init__(object_class, **kwargs)
  
      def fetch_object(self, model_id):
          """Fetch the model by its ID."""
          pk_field_instance = getattr(self.object_class, self.pk_field)
          qs = self.object_class.query.filter(pk_field_instance == model_id)
          model = qs.one_or_none()
          if not model:
              raise ReferenceNotFoundError
          return model
  
      def serialize(self, obj):
          if obj:
              return getattr(obj, self.pk_field)
  