input: Write a function to create a machine learning model in Python using Keras that can distinguish between images of cats and dogs. The function should preprocess the images using an ImageDataGenerator, compile the model, and fit it using the provided training generator. The function should return the compiled model. If the directory path for the dataset is not provided, the function should raise a ValueError.
  assert create_cat_dog_model('/path/to/dataset').compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])==None
  assert isinstance(create_cat_dog_model('/path/to/dataset'), keras.models.Sequential)
  assert create_cat_dog_model('/invalid/path')==ValueError
output: def create_cat_dog_model(dataset_path):
      if not dataset_path:
          raise ValueError("Directory path for the dataset is not provided")
      
      from tensorflow.keras.preprocessing.image import ImageDataGenerator
      from tensorflow.keras.models import Sequential
      from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense
      
      train_datagen = ImageDataGenerator(rescale=1./255)
      train_generator = train_datagen.flow_from_directory(
          dataset_path,
          target_size=(150, 150),
          batch_size=20,
          class_mode='binary'
      )
      
      model = Sequential([
          Conv2D(32, (3, 3), activation='relu', input_shape=(150, 150, 3)),
          MaxPooling2D(2, 2),
          Conv2D(64, (3, 3), activation='relu'),
          MaxPooling2D(2, 2),
          Conv2D(128, (3, 3), activation='relu'),
          MaxPooling2D(2, 2),
          Flatten(),
          Dense(512, activation='relu'),
          Dense(1, activation='sigmoid')
      ])
      
      model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
      model.fit(train_generator, steps_per_epoch=100, epochs=15)
      
      return model