You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airflow.apache.org by ds...@apache.org on 2022/02/08 23:08:37 UTC

[airflow] branch main updated: Add pre-commit check for docstring param types (#21398)

This is an automated email from the ASF dual-hosted git repository.

dstandish pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 0a3ff43  Add pre-commit check for docstring param types (#21398)
0a3ff43 is described below

commit 0a3ff43d41d33d05fb3996e61785919effa9a2fa
Author: Daniel Standish <15...@users.noreply.github.com>
AuthorDate: Tue Feb 8 15:07:54 2022 -0800

    Add pre-commit check for docstring param types (#21398)
    
    Param types can now be inferred by sphinx from type annotations, so we no longer need them in docstrings.
    
    This pre-commit check fails when type declarations are included in docstrings, and seems to do a reasonable job of not catching false positives.
---
 .pre-commit-config.yaml                            |  9 ++++
 BREEZE.rst                                         | 14 +++---
 STATIC_CODE_CHECKS.rst                             |  2 +
 airflow/jobs/backfill_job.py                       |  1 -
 airflow/models/dag.py                              |  3 --
 airflow/providers/amazon/aws/hooks/s3.py           |  1 -
 airflow/providers/amazon/aws/operators/eks.py      |  5 --
 .../kubernetes/backcompat/pod_runtime_info_env.py  |  2 -
 .../providers/elasticsearch/log/es_task_handler.py |  1 -
 airflow/providers/github/hooks/github.py           |  1 -
 airflow/providers/github/operators/github.py       |  4 --
 airflow/providers/github/sensors/github.py         |  9 ----
 airflow/providers/google/cloud/hooks/gcs.py        |  1 -
 .../google/cloud/log/stackdriver_task_handler.py   |  2 -
 .../providers/google/cloud/operators/dataproc.py   |  4 --
 airflow/providers/google/cloud/operators/gcs.py    |  1 -
 airflow/providers/google/cloud/operators/vision.py |  2 -
 .../google/cloud/utils/credentials_provider.py     |  1 -
 airflow/providers/http/operators/http.py           |  2 -
 .../providers/microsoft/azure/hooks/base_azure.py  |  1 -
 airflow/providers/microsoft/psrp/hooks/psrp.py     |  7 ---
 airflow/sensors/smart_sensor.py                    | 16 ++----
 breeze-complete                                    |  1 +
 dev/breeze/src/airflow_breeze/pre_commit_ids.py    |  1 +
 .../pre_commit/pre_commit_docstring_param_type.py  | 58 ++++++++++++++++++++++
 25 files changed, 81 insertions(+), 68 deletions(-)

diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index a8844fe..259303c 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -690,6 +690,15 @@ repos:
         pass_filenames: true
         files: \.github/workflows/.*\.yml$
         additional_dependencies: ['PyYAML', 'rich']
+      - id: docstring-params
+        name: Check that docstrings do not specify param types
+        entry: ./scripts/ci/pre_commit/pre_commit_docstring_param_type.py
+        language: python
+        pass_filenames: true
+        files: \.py$
+        pass_filenames: true
+        exclude: ^airflow/_vendor/
+        additional_dependencies: ['rich']
       - id: chart-schema-lint
         name: Lint chart/values.schema.json file
         entry: ./scripts/ci/pre_commit/pre_commit_chart_schema.py
diff --git a/BREEZE.rst b/BREEZE.rst
index c45004e..ffb72c7 100644
--- a/BREEZE.rst
+++ b/BREEZE.rst
@@ -2188,13 +2188,13 @@ This is the current syntax for  `./breeze <./breeze>`_:
                  changelog-duplicates check-apache-license check-builtin-literals
                  check-executables-have-shebangs check-extras-order check-hooks-apply
                  check-integrations check-merge-conflict check-xml daysago-import-check
-                 debug-statements detect-private-key doctoc dont-use-safe-filter end-of-file-fixer
-                 fix-encoding-pragma flake8 flynt codespell forbid-tabs helm-lint identity
-                 incorrect-use-of-LoggingMixin insert-license isort json-schema language-matters
-                 lint-dockerfile lint-openapi markdownlint mermaid mixed-line-ending mypy mypy-helm
-                 no-providers-in-core-examples no-relative-imports persist-credentials-disabled
-                 pre-commit-descriptions pre-commit-hook-names pretty-format-json
-                 provide-create-sessions providers-changelogs providers-init-file
+                 debug-statements detect-private-key docstring-params doctoc dont-use-safe-filter
+                 end-of-file-fixer fix-encoding-pragma flake8 flynt codespell forbid-tabs helm-lint
+                 identity incorrect-use-of-LoggingMixin insert-license isort json-schema
+                 language-matters lint-dockerfile lint-openapi markdownlint mermaid mixed-line-ending
+                 mypy mypy-helm no-providers-in-core-examples no-relative-imports
+                 persist-credentials-disabled pre-commit-descriptions pre-commit-hook-names
+                 pretty-format-json provide-create-sessions providers-changelogs providers-init-file
                  providers-subpackages-init-file provider-yamls pydevd pydocstyle python-no-log-warn
                  pyupgrade restrict-start_date rst-backticks setup-order setup-extra-packages
                  shellcheck sort-in-the-wild sort-spelling-wordlist stylelint trailing-whitespace
diff --git a/STATIC_CODE_CHECKS.rst b/STATIC_CODE_CHECKS.rst
index b65c8b7..08449f7 100644
--- a/STATIC_CODE_CHECKS.rst
+++ b/STATIC_CODE_CHECKS.rst
@@ -172,6 +172,8 @@ require Breeze Docker images to be installed locally.
 ------------------------------------ ---------------------------------------------------------------- ------------
 ``detect-private-key``                 Detects if private key is added to the repository
 ------------------------------------ ---------------------------------------------------------------- ------------
+``docstring-params``                   Checks that param types not specified in docstring
+------------------------------------ ---------------------------------------------------------------- ------------
 ``doctoc``                             Refreshes the table of contents for MD files
 ------------------------------------ ---------------------------------------------------------------- ------------
 ``dont-use-safe-filter``               Don't use safe in templates
diff --git a/airflow/jobs/backfill_job.py b/airflow/jobs/backfill_job.py
index 10a5d08..c1bbb43 100644
--- a/airflow/jobs/backfill_job.py
+++ b/airflow/jobs/backfill_job.py
@@ -135,7 +135,6 @@ class BackfillJob(BaseJob):
         :param run_backwards: Whether to process the dates from most to least recent
         :param run_at_least_once: If true, always run the DAG at least once even
             if no logical run exists within the time range.
-        :type: bool
         :param args:
         :param kwargs:
         """
diff --git a/airflow/models/dag.py b/airflow/models/dag.py
index 5cf1731..71cd2a6 100644
--- a/airflow/models/dag.py
+++ b/airflow/models/dag.py
@@ -2207,12 +2207,9 @@ class DAG(LoggingMixin):
         :param verbose: Make logging output more verbose
         :param conf: user defined dictionary passed from CLI
         :param rerun_failed_tasks:
-        :type: bool
         :param run_backwards:
-        :type: bool
         :param run_at_least_once: If true, always run the DAG at least once even
             if no logical run exists within the time range.
-        :type: bool
         """
         from airflow.jobs.backfill_job import BackfillJob
 
diff --git a/airflow/providers/amazon/aws/hooks/s3.py b/airflow/providers/amazon/aws/hooks/s3.py
index 0f3c045..9d3c604 100644
--- a/airflow/providers/amazon/aws/hooks/s3.py
+++ b/airflow/providers/amazon/aws/hooks/s3.py
@@ -132,7 +132,6 @@ class S3Hook(AwsBaseHook):
         Parses the S3 Url into a bucket name and key.
 
         :param s3url: The S3 Url to parse.
-        :rtype s3url: str
         :return: the parsed bucket name and key
         :rtype: tuple of str
         """
diff --git a/airflow/providers/amazon/aws/operators/eks.py b/airflow/providers/amazon/aws/operators/eks.py
index acc323e..ef40cab 100644
--- a/airflow/providers/amazon/aws/operators/eks.py
+++ b/airflow/providers/amazon/aws/operators/eks.py
@@ -77,7 +77,6 @@ class EksCreateClusterOperator(BaseOperator):
     :param compute: The type of compute architecture to generate along with the cluster. (templated)
          Defaults to 'nodegroup' to generate an EKS Managed Nodegroup.
     :param create_cluster_kwargs: Optional parameters to pass to the CreateCluster API (templated)
-    :type: Dict
     :param aws_conn_id: The Airflow connection used for AWS credentials. (templated)
          If this is None or empty then the default boto3 behaviour is used. If
          running Airflow in a distributed manner and aws_conn_id is None or
@@ -92,7 +91,6 @@ class EksCreateClusterOperator(BaseOperator):
     :param nodegroup_role_arn: *REQUIRED* The Amazon Resource Name (ARN) of the IAM role to associate with
          the Amazon EKS managed node group. (templated)
     :param create_nodegroup_kwargs: Optional parameters to pass to the CreateNodegroup API (templated)
-    :type: Dict
 
 
     If compute is assigned the value of 'fargate':
@@ -103,7 +101,6 @@ class EksCreateClusterOperator(BaseOperator):
     :param fargate_selectors: The selectors to match for pods to use this AWS Fargate profile. (templated)
     :param create_fargate_profile_kwargs: Optional parameters to pass to the CreateFargateProfile API
          (templated)
-    :type: Dict
 
     """
 
@@ -241,7 +238,6 @@ class EksCreateNodegroupOperator(BaseOperator):
     :param nodegroup_role_arn:
          The Amazon Resource Name (ARN) of the IAM role to associate with the managed nodegroup. (templated)
     :param create_nodegroup_kwargs: Optional parameters to pass to the Create Nodegroup API (templated)
-    :type: Dict
     :param aws_conn_id: The Airflow connection used for AWS credentials. (templated)
          If this is None or empty then the default boto3 behaviour is used. If
          running Airflow in a distributed manner and aws_conn_id is None or
@@ -324,7 +320,6 @@ class EksCreateFargateProfileOperator(BaseOperator):
     :param fargate_profile_name: The unique name to give your AWS Fargate profile. (templated)
     :param create_fargate_profile_kwargs: Optional parameters to pass to the CreateFargate Profile API
      (templated)
-    :type: Dict
 
     :param aws_conn_id: The Airflow connection used for AWS credentials. (templated)
          If this is None or empty then the default boto3 behaviour is used. If
diff --git a/airflow/providers/cncf/kubernetes/backcompat/pod_runtime_info_env.py b/airflow/providers/cncf/kubernetes/backcompat/pod_runtime_info_env.py
index 47d96c1..f08aecf 100644
--- a/airflow/providers/cncf/kubernetes/backcompat/pod_runtime_info_env.py
+++ b/airflow/providers/cncf/kubernetes/backcompat/pod_runtime_info_env.py
@@ -40,9 +40,7 @@ class PodRuntimeInfoEnv:
         Full list of options can be found in kubernetes documentation.
 
         :param name: the name of the environment variable
-        :type: name: str
         :param field_path: path to pod runtime info. Ex: metadata.namespace | status.podIP
-        :type: field_path: str
         """
         self.name = name
         self.field_path = field_path
diff --git a/airflow/providers/elasticsearch/log/es_task_handler.py b/airflow/providers/elasticsearch/log/es_task_handler.py
index c3f8d4f..35fed06 100644
--- a/airflow/providers/elasticsearch/log/es_task_handler.py
+++ b/airflow/providers/elasticsearch/log/es_task_handler.py
@@ -353,7 +353,6 @@ class ElasticsearchTaskHandler(FileTaskHandler, ExternalLoggingMixin, LoggingMix
         Creates an address for an external log collecting service.
 
         :param task_instance: task instance object
-        :type: task_instance: TaskInstance
         :param try_number: task instance try_number to read logs from.
         :return: URL to the external log collection service
         :rtype: str
diff --git a/airflow/providers/github/hooks/github.py b/airflow/providers/github/hooks/github.py
index 5338f49..3514b77 100644
--- a/airflow/providers/github/hooks/github.py
+++ b/airflow/providers/github/hooks/github.py
@@ -31,7 +31,6 @@ class GithubHook(BaseHook):
     Performs a connection to GitHub and retrieves client.
 
     :param github_conn_id: Reference to :ref:`GitHub connection id <howto/connection:github>`.
-    :type github_conn_id: str
     """
 
     conn_name_attr = 'github_conn_id'
diff --git a/airflow/providers/github/operators/github.py b/airflow/providers/github/operators/github.py
index 170b9a8..73e1181 100644
--- a/airflow/providers/github/operators/github.py
+++ b/airflow/providers/github/operators/github.py
@@ -38,13 +38,9 @@ class GithubOperator(BaseOperator):
         :ref:`howto/operator:GithubOperator`
 
     :param github_conn_id: reference to a pre-defined GitHub Connection
-    :type github_conn_id: str
     :param github_method: method name from GitHub Python SDK to be called
-    :type github_method: str
     :param github_method_args: required method parameters for the github_method. (templated)
-    :type github_method_args: dict
     :param result_processor: function to further process the response from GitHub API
-    :type result_processor: function
     """
 
     template_fields = ("github_method_args",)
diff --git a/airflow/providers/github/sensors/github.py b/airflow/providers/github/sensors/github.py
index 3d0265e..ff1f269 100644
--- a/airflow/providers/github/sensors/github.py
+++ b/airflow/providers/github/sensors/github.py
@@ -33,13 +33,9 @@ class GithubSensor(BaseSensorOperator):
     Base GithubSensor which can monitor for any change.
 
     :param github_conn_id: reference to a pre-defined Github Connection
-    :type github_conn_id: str
     :param method_name: method name from PyGithub to be executed
-    :type method_name: str
     :param method_params: parameters for the method method_name
-    :type method_params: dict
     :param result_processor: function that return boolean and act as a sensor response
-    :type result_processor: function
     """
 
     def __init__(
@@ -75,9 +71,7 @@ class BaseGithubRepositorySensor(GithubSensor):
     Base GitHub sensor at Repository level.
 
     :param github_conn_id: reference to a pre-defined GitHub Connection
-    :type github_conn_id: str
     :param repository_name: full qualified name of the repository to be monitored, ex. "apache/airflow"
-    :type repository_name: str
     """
 
     def __init__(
@@ -109,11 +103,8 @@ class GithubTagSensor(BaseGithubRepositorySensor):
     Monitors a github tag for its creation.
 
     :param github_conn_id: reference to a pre-defined Github Connection
-    :type github_conn_id: str
     :param tag_name: name of the tag to be monitored
-    :type tag_name: str
     :param repository_name: fully qualified name of the repository to be monitored, ex. "apache/airflow"
-    :type repository_name: str
     """
 
     template_fields = ("tag_name",)
diff --git a/airflow/providers/google/cloud/hooks/gcs.py b/airflow/providers/google/cloud/hooks/gcs.py
index 8a1e934..9d6cf2f 100644
--- a/airflow/providers/google/cloud/hooks/gcs.py
+++ b/airflow/providers/google/cloud/hooks/gcs.py
@@ -662,7 +662,6 @@ class GCSHook(GoogleBaseHook):
         :param bucket_name: name of the bucket which will be deleted
         :param force: false not allow to delete non empty bucket, set force=True
             allows to delete non empty bucket
-        :type: bool
         """
         client = self.get_conn()
         bucket = client.bucket(bucket_name)
diff --git a/airflow/providers/google/cloud/log/stackdriver_task_handler.py b/airflow/providers/google/cloud/log/stackdriver_task_handler.py
index 37365cd..2a47718 100644
--- a/airflow/providers/google/cloud/log/stackdriver_task_handler.py
+++ b/airflow/providers/google/cloud/log/stackdriver_task_handler.py
@@ -215,7 +215,6 @@ class StackdriverTaskHandler(logging.Handler):
         https://cloud.google.com/logging/docs/view/advanced-queries
 
         :param ti_labels: Task Instance's labels that will be used to search for logs
-        :type: Dict[str, str]
         :return: logs filter
         """
 
@@ -331,7 +330,6 @@ class StackdriverTaskHandler(logging.Handler):
         """
         Creates an address for an external log collecting service.
         :param task_instance: task instance object
-        :type: task_instance: TaskInstance
         :param try_number: task instance try_number to read logs from.
         :return: URL to the external log collection service
         :rtype: str
diff --git a/airflow/providers/google/cloud/operators/dataproc.py b/airflow/providers/google/cloud/operators/dataproc.py
index 4bb54e9..ce6e96e 100644
--- a/airflow/providers/google/cloud/operators/dataproc.py
+++ b/airflow/providers/google/cloud/operators/dataproc.py
@@ -2035,15 +2035,11 @@ class DataprocCreateBatchOperator(BaseOperator):
     Creates a batch workload.
 
     :param project_id: Required. The ID of the Google Cloud project that the cluster belongs to. (templated)
-    :type project_id: str
     :param region: Required. The Cloud Dataproc region in which to handle the request. (templated)
-    :type region: str
     :param batch: Required. The batch to create. (templated)
-    :type batch: google.cloud.dataproc_v1.types.Batch
     :param batch_id: Optional. The ID to use for the batch, which will become the final component
         of the batch's resource name.
         This value must be 4-63 characters. Valid characters are /[a-z][0-9]-/. (templated)
-    :type batch_id: str
     :param request_id: Optional. A unique id used to identify the request. If the server receives two
         ``CreateBatchRequest`` requests with the same id, then the second request will be ignored and
         the first ``google.longrunning.Operation`` created and stored in the backend is returned.
diff --git a/airflow/providers/google/cloud/operators/gcs.py b/airflow/providers/google/cloud/operators/gcs.py
index 8b26071..8565c89 100644
--- a/airflow/providers/google/cloud/operators/gcs.py
+++ b/airflow/providers/google/cloud/operators/gcs.py
@@ -865,7 +865,6 @@ class GCSDeleteBucketOperator(BaseOperator):
     :param bucket_name: name of the bucket which will be deleted
     :param force: false not allow to delete non empty bucket, set force=True
         allows to delete non empty bucket
-    :type: bool
     :param gcp_conn_id: The connection ID to use connecting to Google Cloud.
     :param impersonation_chain: Optional service account to impersonate using short-term
         credentials, or chained list of accounts required to get the access_token
diff --git a/airflow/providers/google/cloud/operators/vision.py b/airflow/providers/google/cloud/operators/vision.py
index 3f34917..b346b30 100644
--- a/airflow/providers/google/cloud/operators/vision.py
+++ b/airflow/providers/google/cloud/operators/vision.py
@@ -1043,7 +1043,6 @@ class CloudVisionAddProductToProductSetOperator(BaseOperator):
     :param product_id: (Required) The resource id of this Product.
     :param location: (Required) The region where the ProductSet is located. Valid regions (as of 2019-02-05)
         are: us-east1, us-west1, europe-west1, asia-east1
-    :type: str
     :param project_id: (Optional) The project in which the Product is located. If set to None or
         missing, the default project_id from the Google Cloud connection is used.
     :param retry: (Optional) A retry object used to retry requests. If `None` is
@@ -1127,7 +1126,6 @@ class CloudVisionRemoveProductFromProductSetOperator(BaseOperator):
     :param product_id: (Required) The resource id of this Product.
     :param location: (Required) The region where the ProductSet is located. Valid regions (as of 2019-02-05)
         are: us-east1, us-west1, europe-west1, asia-east1
-    :type: str
     :param project_id: (Optional) The project in which the Product is located. If set to None or
         missing, the default project_id from the Google Cloud connection is used.
     :param retry: (Optional) A retry object used to retry requests. If `None` is
diff --git a/airflow/providers/google/cloud/utils/credentials_provider.py b/airflow/providers/google/cloud/utils/credentials_provider.py
index 907e8e1..0af03d2 100644
--- a/airflow/providers/google/cloud/utils/credentials_provider.py
+++ b/airflow/providers/google/cloud/utils/credentials_provider.py
@@ -218,7 +218,6 @@ class _CredentialProvider(LoggingMixin):
         Get current credentials and project ID.
 
         :return: Google Auth Credentials
-        :type: Tuple[google.auth.credentials.Credentials, str]
         """
         if self.key_path:
             credentials, project_id = self._get_credentials_using_key_path()
diff --git a/airflow/providers/http/operators/http.py b/airflow/providers/http/operators/http.py
index eedd863..0622b8e 100644
--- a/airflow/providers/http/operators/http.py
+++ b/airflow/providers/http/operators/http.py
@@ -41,8 +41,6 @@ class SimpleHttpOperator(BaseOperator):
     :param method: The HTTP method to use, default = "POST"
     :param data: The data to pass. POST-data in POST/PUT and params
         in the URL for a GET request. (templated)
-    :type data: For POST/PUT, depends on the content-type parameter,
-        for GET a dictionary of key/value string pairs
     :param headers: The HTTP headers to be added to the GET request
     :param response_check: A check against the 'requests' response object.
         The callable takes the response object as the first positional argument
diff --git a/airflow/providers/microsoft/azure/hooks/base_azure.py b/airflow/providers/microsoft/azure/hooks/base_azure.py
index 3205809..85e634b 100644
--- a/airflow/providers/microsoft/azure/hooks/base_azure.py
+++ b/airflow/providers/microsoft/azure/hooks/base_azure.py
@@ -32,7 +32,6 @@ class AzureBaseHook(BaseHook):
     :param sdk_client: The SDKClient to use.
     :param conn_id: The :ref:`Azure connection id<howto/connection:azure>`
         which refers to the information to connect to the service.
-    :type: str
     """
 
     conn_name_attr = 'azure_conn_id'
diff --git a/airflow/providers/microsoft/psrp/hooks/psrp.py b/airflow/providers/microsoft/psrp/hooks/psrp.py
index 98f9190..d5f70b7 100644
--- a/airflow/providers/microsoft/psrp/hooks/psrp.py
+++ b/airflow/providers/microsoft/psrp/hooks/psrp.py
@@ -47,30 +47,23 @@ class PsrpHook(BaseHook):
     sessions.
 
     :param psrp_conn_id: Required. The name of the PSRP connection.
-    :type psrp_conn_id: str
     :param logging_level:
         Logging level for message streams which are received during remote execution.
         The default is to include all messages in the task log.
-    :type logging_level: int
     :param operation_timeout: Override the default WSMan timeout when polling the pipeline.
-    :type operation_timeout: float
     :param runspace_options:
         Optional dictionary which is passed when creating the runspace pool. See
         :py:class:`~pypsrp.powershell.RunspacePool` for a description of the
         available options.
-    :type runspace_options: dict
     :param wsman_options:
         Optional dictionary which is passed when creating the `WSMan` client. See
         :py:class:`~pypsrp.wsman.WSMan` for a description of the available options.
-    :type wsman_options: dict
     :param on_output_callback:
         Optional callback function to be called whenever an output response item is
         received during job status polling.
-    :type on_output_callback: OutputCallback
     :param exchange_keys:
         If true (default), automatically initiate a session key exchange when the
         hook is used as a context manager.
-    :type exchange_keys: bool
 
     You can provide an alternative `configuration_name` using either `runspace_options`
     or by setting this key as the extra fields of your connection.
diff --git a/airflow/sensors/smart_sensor.py b/airflow/sensors/smart_sensor.py
index 63c394e..23bce57 100644
--- a/airflow/sensors/smart_sensor.py
+++ b/airflow/sensors/smart_sensor.py
@@ -251,10 +251,7 @@ class SensorExceptionInfo:
             self._infra_failure_timeout = timezone.utcnow() + self._infra_failure_retry_window
 
     def should_fail_current_run(self):
-        """
-        :return: Should the sensor fail
-        :type: boolean
-        """
+        """:return: Should the sensor fail"""
         return not self.is_infra_failure or timezone.utcnow() > self._infra_failure_timeout
 
     @property
@@ -264,18 +261,11 @@ class SensorExceptionInfo:
 
     @property
     def is_infra_failure(self):
-        """
-
-        :return: If the exception is an infra failure
-        :type: boolean
-        """
+        """:return: If the exception is an infra failure"""
         return self._is_infra_failure
 
     def is_expired(self):
-        """
-        :return: If current exception need to be kept.
-        :type: boolean
-        """
+        """:return: If current exception need to be kept."""
         if not self._is_infra_failure:
             return True
         return timezone.utcnow() > self._infra_failure_timeout + datetime.timedelta(minutes=30)
diff --git a/breeze-complete b/breeze-complete
index 4049e1a..6b2f52e 100644
--- a/breeze-complete
+++ b/breeze-complete
@@ -97,6 +97,7 @@ check-xml
 daysago-import-check
 debug-statements
 detect-private-key
+docstring-params
 doctoc
 dont-use-safe-filter
 end-of-file-fixer
diff --git a/dev/breeze/src/airflow_breeze/pre_commit_ids.py b/dev/breeze/src/airflow_breeze/pre_commit_ids.py
index 7dbb49e..99bc6a7 100644
--- a/dev/breeze/src/airflow_breeze/pre_commit_ids.py
+++ b/dev/breeze/src/airflow_breeze/pre_commit_ids.py
@@ -45,6 +45,7 @@ PRE_COMMIT_LIST = [
     'daysago-import-check',
     'debug-statements',
     'detect-private-key',
+    'docstring-params',
     'doctoc',
     'dont-use-safe-filter',
     'end-of-file-fixer',
diff --git a/scripts/ci/pre_commit/pre_commit_docstring_param_type.py b/scripts/ci/pre_commit/pre_commit_docstring_param_type.py
new file mode 100755
index 0000000..38f7d40
--- /dev/null
+++ b/scripts/ci/pre_commit/pre_commit_docstring_param_type.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python3
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+import re
+import sys
+from pathlib import Path
+
+from rich.console import Console
+
+if __name__ not in ("__main__", "__mp_main__"):
+    raise SystemExit(
+        "This file is intended to be executed as an executable program. You cannot use it as a module."
+        f"To run this script, run the ./{__file__} command [FILE] ..."
+    )
+
+
+console = Console(color_system="standard", width=200)
+
+
+def _check_file(file: Path) -> list:
+    content = file.read_text()
+    return re.findall(r' +\:type .+?\:', content)
+
+
+def _join_with_newline(list_):
+    return '\n'.join(list_)
+
+
+if __name__ == '__main__':
+    error_list = []
+    for file in sys.argv[1:]:
+        matches = _check_file(Path(file))
+        if matches:
+            error_list.append((file, matches))
+    if error_list:
+        error_message = '\n'.join([f"{f}: \n{_join_with_newline(m)}" for f, m in error_list])
+        console.print(
+            f"""
+[red]Found files with types specified in docstring.
+This is no longer needed since sphinx can now infer types from type annotations.[/]
+{error_message}
+"""
+        )
+        sys.exit(1)