Repository: apache/airflow

Issue:
Typo in Sensor: GCSObjectsWtihPrefixExistenceSensor (should be GCSObjectsWithPrefixExistenceSensor)
Typo in Google Cloud Storage sensor: airflow/providers/google/cloud/sensors/gcs/GCSObjectsWithPrefixExistenceSensor

The word _With_ is spelled incorrectly. It should be: GCSObjects**With**PrefixExistenceSensor

**Apache Airflow version**: 2.0.0
**Environment**:
- **Cloud provider or hardware configuration**: Google Cloud
- **OS** (e.g. from /etc/os-release): Mac OS BigSur








Discussion:
Thanks for opening your first issue here! Be sure to follow the issue template!

You should change the name and then add the code below for backward compatibility.
```
class GCSObjectsWtihPrefixExistenceSensor(GCSObjectsWithPrefixExistenceSensor):
    """
    This class is deprecated.
    Please use `airflow.providers.google.cloud.sensors.gcs.GCSObjectsWithPrefixExistenceSensor`.
    """

    def __init__(self, *args, **kwargs):
        warnings.warn(
            """This class is deprecated.
            Please use `airflow.providers.google.cloud.sensors.gcs.GCSObjectsWithPrefixExistenceSensor`.""",
            DeprecationWarning,
            stacklevel=3,
        )
        super().__init__(*args, **kwargs)
```
It is also worth adding tests. To do it, update the [`deprecated_classes.py`](https://github.com/apache/airflow/blob/master/tests/deprecated_classes.py) file.


Resolving patch:
diff --git a/airflow/contrib/sensors/gcs_sensor.py b/airflow/contrib/sensors/gcs_sensor.py
--- a/airflow/contrib/sensors/gcs_sensor.py
+++ b/airflow/contrib/sensors/gcs_sensor.py
@@ -21,7 +21,7 @@
 
 from airflow.providers.google.cloud.sensors.gcs import (
     GCSObjectExistenceSensor,
-    GCSObjectsWtihPrefixExistenceSensor,
+    GCSObjectsWithPrefixExistenceSensor,
     GCSObjectUpdateSensor,
     GCSUploadSessionCompleteSensor,
 )
@@ -65,16 +65,16 @@ def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
 
 
-class GoogleCloudStoragePrefixSensor(GCSObjectsWtihPrefixExistenceSensor):
+class GoogleCloudStoragePrefixSensor(GCSObjectsWithPrefixExistenceSensor):
     """
     This class is deprecated.
-    Please use `airflow.providers.google.cloud.sensors.gcs.GCSObjectsWtihPrefixExistenceSensor`.
+    Please use `airflow.providers.google.cloud.sensors.gcs.GCSObjectsWithPrefixExistenceSensor`.
     """
 
     def __init__(self, *args, **kwargs):
         warnings.warn(
             """This class is deprecated.
-            Please use `airflow.providers.google.cloud.sensors.gcs.GCSObjectsWtihPrefixExistenceSensor`.""",
+            Please use `airflow.providers.google.cloud.sensors.gcs.GCSObjectsWithPrefixExistenceSensor`.""",
             DeprecationWarning,
             stacklevel=3,
         )
diff --git a/airflow/providers/google/cloud/sensors/gcs.py b/airflow/providers/google/cloud/sensors/gcs.py
--- a/airflow/providers/google/cloud/sensors/gcs.py
+++ b/airflow/providers/google/cloud/sensors/gcs.py
@@ -18,6 +18,7 @@
 """This module contains Google Cloud Storage sensors."""
 
 import os
+import warnings
 from datetime import datetime
 from typing import Callable, List, Optional, Sequence, Set, Union
 
@@ -167,7 +168,7 @@ def poke(self, context: dict) -> bool:
         return hook.is_updated_after(self.bucket, self.object, self.ts_func(context))
 
 
-class GCSObjectsWtihPrefixExistenceSensor(BaseSensorOperator):
+class GCSObjectsWithPrefixExistenceSensor(BaseSensorOperator):
     """
     Checks for the existence of GCS objects at a given prefix, passing matches via XCom.
 
@@ -239,6 +240,22 @@ def execute(self, context: dict) -> List[str]:
         return self._matches
 
 
+class GCSObjectsWtihPrefixExistenceSensor(GCSObjectsWithPrefixExistenceSensor):
+    """
+    This class is deprecated.
+    Please use `airflow.providers.google.cloud.sensors.gcs.GCSObjectsWithPrefixExistenceSensor`.
+    """
+
+    def __init__(self, *args, **kwargs):
+        warnings.warn(
+            """This class is deprecated.
+            Please use `airflow.providers.google.cloud.sensors.gcs.GCSObjectsWithPrefixExistenceSensor`.""",
+            DeprecationWarning,
+            stacklevel=3,
+        )
+        super().__init__(*args, **kwargs)
+
+
 def get_time():
     """
     This is just a wrapper of datetime.datetime.now to simplify mocking in the


Test patch:
diff --git a/tests/always/test_project_structure.py b/tests/always/test_project_structure.py
--- a/tests/always/test_project_structure.py
+++ b/tests/always/test_project_structure.py
@@ -220,6 +220,7 @@ class TestGoogleProviderProjectStructure(unittest.TestCase):
         'airflow.providers.google.cloud.operators.compute.ComputeEngineBaseOperator',
         'airflow.providers.google.cloud.sensors.gcs.GCSObjectExistenceSensor',
         'airflow.providers.google.cloud.sensors.gcs.GCSObjectUpdateSensor',
+        'airflow.providers.google.cloud.sensors.gcs.GCSObjectsWithPrefixExistenceSensor',
         'airflow.providers.google.cloud.sensors.gcs.GCSObjectsWtihPrefixExistenceSensor',
         'airflow.providers.google.cloud.sensors.gcs.GCSUploadSessionCompleteSensor',
     }
diff --git a/tests/deprecated_classes.py b/tests/deprecated_classes.py
--- a/tests/deprecated_classes.py
+++ b/tests/deprecated_classes.py
@@ -1416,7 +1416,7 @@
         "airflow.contrib.sensors.gcs_sensor.GoogleCloudStorageObjectUpdatedSensor",
     ),
     (
-        "airflow.providers.google.cloud.sensors.gcs.GCSObjectsWtihPrefixExistenceSensor",
+        "airflow.providers.google.cloud.sensors.gcs.GCSObjectsWithPrefixExistenceSensor",
         "airflow.contrib.sensors.gcs_sensor.GoogleCloudStoragePrefixSensor",
     ),
     (
diff --git a/tests/providers/google/cloud/sensors/test_gcs.py b/tests/providers/google/cloud/sensors/test_gcs.py
--- a/tests/providers/google/cloud/sensors/test_gcs.py
+++ b/tests/providers/google/cloud/sensors/test_gcs.py
@@ -25,7 +25,7 @@
 from airflow.models.dag import DAG, AirflowException
 from airflow.providers.google.cloud.sensors.gcs import (
     GCSObjectExistenceSensor,
-    GCSObjectsWtihPrefixExistenceSensor,
+    GCSObjectsWithPrefixExistenceSensor,
     GCSObjectUpdateSensor,
     GCSUploadSessionCompleteSensor,
     ts_function,
@@ -131,7 +131,7 @@ def test_should_pass_argument_to_hook(self, mock_hook):
 class TestGoogleCloudStoragePrefixSensor(TestCase):
     @mock.patch("airflow.providers.google.cloud.sensors.gcs.GCSHook")
     def test_should_pass_arguments_to_hook(self, mock_hook):
-        task = GCSObjectsWtihPrefixExistenceSensor(
+        task = GCSObjectsWithPrefixExistenceSensor(
             task_id="task-id",
             bucket=TEST_BUCKET,
             prefix=TEST_PREFIX,
@@ -152,7 +152,7 @@ def test_should_pass_arguments_to_hook(self, mock_hook):
 
     @mock.patch("airflow.providers.google.cloud.sensors.gcs.GCSHook")
     def test_should_return_false_on_empty_list(self, mock_hook):
-        task = GCSObjectsWtihPrefixExistenceSensor(
+        task = GCSObjectsWithPrefixExistenceSensor(
             task_id="task-id",
             bucket=TEST_BUCKET,
             prefix=TEST_PREFIX,
@@ -166,7 +166,7 @@ def test_should_return_false_on_empty_list(self, mock_hook):
 
     @mock.patch('airflow.providers.google.cloud.sensors.gcs.GCSHook')
     def test_execute(self, mock_hook):
-        task = GCSObjectsWtihPrefixExistenceSensor(
+        task = GCSObjectsWithPrefixExistenceSensor(
             task_id="task-id",
             bucket=TEST_BUCKET,
             prefix=TEST_PREFIX,
@@ -190,7 +190,7 @@ def test_execute(self, mock_hook):
 
     @mock.patch('airflow.providers.google.cloud.sensors.gcs.GCSHook')
     def test_execute_timeout(self, mock_hook):
-        task = GCSObjectsWtihPrefixExistenceSensor(
+        task = GCSObjectsWithPrefixExistenceSensor(
             task_id="task-id", bucket=TEST_BUCKET, prefix=TEST_PREFIX, poke_interval=0, timeout=1
         )
         mock_hook.return_value.list.return_value = []