You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airflow.apache.org by gi...@apache.org on 2022/07/20 13:16:33 UTC

[airflow-site] branch gh-pages updated: Deploying to gh-pages from @ 988ae480223f723efb0b2f97992d30f42128a0ef πŸš€

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

github-bot pushed a commit to branch gh-pages
in repository https://gitbox.apache.org/repos/asf/airflow-site.git


The following commit(s) were added to refs/heads/gh-pages by this push:
     new 017e98f4a1 Deploying to gh-pages from  @ 988ae480223f723efb0b2f97992d30f42128a0ef πŸš€
017e98f4a1 is described below

commit 017e98f4a12f0d5691f6533241b1d398bf5228b8
Author: ephraimbuddy <sp...@gmail.com>
AuthorDate: Wed Jul 20 13:16:26 2022 +0000

    Deploying to gh-pages from  @ 988ae480223f723efb0b2f97992d30f42128a0ef πŸš€
---
 _gen/packages-metadata.json                        | 1162 +++++------
 blog/airflow-1.10.10/index.html                    |    4 +-
 blog/airflow-1.10.12/index.html                    |    4 +-
 blog/airflow-1.10.8-1.10.9/index.html              |    4 +-
 blog/airflow-2.2.0/index.html                      |    4 +-
 blog/airflow-2.3.0/index.html                      |    4 +-
 blog/airflow-survey-2020/index.html                |    4 +-
 blog/airflow-survey-2022/index.html                |    4 +-
 blog/airflow-survey/index.html                     |    4 +-
 blog/airflow-two-point-oh-is-here/index.html       |    4 +-
 blog/airflow_summit_2021/index.html                |    4 +-
 blog/airflow_summit_2022/index.html                |    4 +-
 blog/announcing-new-website/index.html             |    4 +-
 blog/apache-airflow-for-newcomers/index.html       |    4 +-
 .../index.html                                     |    4 +-
 .../index.html                                     |    4 +-
 .../index.html                                     |    4 +-
 .../index.html                                     |    4 +-
 .../index.html                                     |    4 +-
 .../index.html                                     |    4 +-
 .../apache-airflow-providers-sftp/4.0.0/.buildinfo |    4 +
 .../_api/airflow/providers/sftp/hooks/index.html   |   11 +-
 .../airflow/providers/sftp/hooks/sftp/index.html   |  138 +-
 .../_api/airflow/providers/sftp/index.html         |   11 +-
 .../airflow/providers/sftp/operators/index.html    |   11 +-
 .../providers/sftp/operators/sftp/index.html       |   49 +-
 .../_api/airflow/providers/sftp/sensors/index.html |   11 +-
 .../airflow/providers/sftp/sensors/sftp/index.html |   23 +-
 .../airflow/providers/sftp/hooks/sftp.html         |  261 ++-
 .../airflow/providers/sftp/operators/sftp.html     |  140 +-
 .../airflow/providers/sftp/sensors/sftp.html       |   18 +-
 .../{stable => 4.0.0}/_modules/index.html          |    7 +-
 .../airflow/providers/sftp/hooks/index.rst.txt     |   15 +
 .../providers/sftp/hooks/sftp/index.rst.txt        |   58 +-
 .../_api/airflow/providers/sftp/index.rst.txt      |   17 +
 .../airflow/providers/sftp/operators/index.rst.txt |   15 +
 .../providers/sftp/operators/sftp/index.rst.txt    |   16 +-
 .../airflow/providers/sftp/sensors/index.rst.txt   |   15 +
 .../providers/sftp/sensors/sftp/index.rst.txt      |   47 +
 .../{stable => 4.0.0}/_sources/commits.rst.txt     |   19 +-
 .../_sources/connections/sftp.rst.txt              |   33 +-
 .../{stable => 4.0.0}/_sources/index.rst.txt       |    9 +-
 .../installing-providers-from-sources.rst.txt      |   18 +
 .../4.0.0/_static/_gen/css/main-custom.min.css     |    1 +
 .../4.0.0/_static/_gen/css/main.min.css            |    7 +
 .../4.0.0/_static/_gen/js/docs.js                  |    1 +
 .../_sphinx_javascript_frameworks_compat.js        |  134 ++
 .../{stable => 4.0.0}/_static/basic.css            |   38 +-
 .../4.0.0/_static/check-solid.svg                  |    4 +
 .../4.0.0/_static/clipboard.min.js                 |    7 +
 .../4.0.0/_static/copy-button.svg                  |    5 +
 .../4.0.0/_static/copybutton.css                   |   93 +
 .../4.0.0/_static/copybutton.js                    |  220 +++
 .../4.0.0/_static/copybutton_funcs.js              |   58 +
 .../4.0.0/_static/doctools.js                      |  264 +++
 .../4.0.0}/_static/documentation_options.js        |    2 +-
 .../4.0.0/_static/file.png                         |  Bin 0 -> 286 bytes
 .../4.0.0/_static/graphviz.css                     |   19 +
 .../_static/jquery-3.6.0.js}                       |  227 +--
 .../4.0.0/_static/jquery.js                        |    2 +
 .../4.0.0/_static/language_data.js                 |  199 ++
 .../4.0.0/_static/minus.png                        |  Bin 0 -> 90 bytes
 .../4.0.0/_static/pin_32.png                       |  Bin 0 -> 1201 bytes
 .../4.0.0/_static/plus.png                         |  Bin 0 -> 90 bytes
 .../4.0.0/_static/pygments.css                     |   74 +
 .../4.0.0/_static/searchtools.js                   |  531 +++++
 .../4.0.0/_static/underscore-1.13.1.js             | 2042 ++++++++++++++++++++
 .../4.0.0/_static/underscore.js                    |    6 +
 .../{stable => 4.0.0}/commits.html                 |  161 +-
 .../{stable => 4.0.0}/connections/sftp.html        |   41 +-
 .../{stable => 4.0.0}/genindex.html                |   31 +-
 .../{stable => 4.0.0}/index.html                   |  254 +--
 .../installing-providers-from-sources.html         |   45 +-
 .../4.0.0/objects.inv                              |  Bin 0 -> 845 bytes
 .../{stable => 4.0.0}/py-modindex.html             |    7 +-
 .../{stable => 4.0.0}/search.html                  |    7 +-
 .../4.0.0/searchindex.js                           |    1 +
 .../_api/airflow/providers/sftp/hooks/index.html   |   11 +-
 .../airflow/providers/sftp/hooks/sftp/index.html   |  138 +-
 .../stable/_api/airflow/providers/sftp/index.html  |   11 +-
 .../airflow/providers/sftp/operators/index.html    |   11 +-
 .../providers/sftp/operators/sftp/index.html       |   49 +-
 .../_api/airflow/providers/sftp/sensors/index.html |   11 +-
 .../airflow/providers/sftp/sensors/sftp/index.html |   23 +-
 .../airflow/providers/sftp/hooks/sftp.html         |  261 ++-
 .../airflow/providers/sftp/operators/sftp.html     |  140 +-
 .../airflow/providers/sftp/sensors/sftp.html       |   18 +-
 .../stable/_modules/index.html                     |    7 +-
 .../providers/sftp/hooks/sftp/index.rst.txt        |   58 +-
 .../providers/sftp/operators/sftp/index.rst.txt    |   16 +-
 .../stable/_sources/commits.rst.txt                |   19 +-
 .../stable/_sources/connections/sftp.rst.txt       |   33 +-
 .../stable/_sources/index.rst.txt                  |    9 +-
 .../_sphinx_javascript_frameworks_compat.js        |  134 ++
 .../stable/_static/basic.css                       |   38 +-
 .../stable/_static/doctools.js                     |  480 ++---
 .../stable/_static/documentation_options.js        |    6 +-
 .../_static/{jquery-3.5.1.js => jquery-3.6.0.js}   |  227 +--
 .../stable/_static/jquery.js                       |    4 +-
 .../stable/_static/language_data.js                |  100 +-
 .../stable/_static/searchtools.js                  |  784 ++++----
 .../stable/commits.html                            |  161 +-
 .../stable/connections/sftp.html                   |   41 +-
 .../stable/genindex.html                           |   31 +-
 .../stable/index.html                              |  254 +--
 .../stable/installing-providers-from-sources.html  |   45 +-
 .../stable/objects.inv                             |  Bin 822 -> 845 bytes
 .../stable/py-modindex.html                        |    7 +-
 .../stable/search.html                             |    7 +-
 .../stable/searchindex.js                          |    2 +-
 .../1.0.1/.buildinfo                               |    4 +
 .../airflow/providers/tabular/hooks/index.html     |    4 +-
 .../providers/tabular/hooks/tabular/index.html     |    4 +-
 .../_api/airflow/providers/tabular/index.html      |    4 +-
 .../providers/tabular/example_tabular/index.html   |    4 +-
 .../_api/tests/system/providers/tabular/index.html |    4 +-
 .../airflow/providers/tabular/hooks/tabular.html   |   11 +-
 .../{stable => 1.0.1}/_modules/index.html          |    4 +-
 .../system/providers/tabular/example_tabular.html  |    4 +-
 .../airflow/providers/tabular/hooks/index.rst.txt  |   15 +
 .../providers/tabular/hooks/tabular/index.rst.txt  |   88 +
 .../_api/airflow/providers/tabular/index.rst.txt   |   15 +
 .../tabular/example_tabular/index.rst.txt          |   19 +
 .../tests/system/providers/tabular/index.rst.txt   |   15 +
 .../{stable => 1.0.1}/_sources/commits.rst.txt     |   11 +
 .../1.0.1/_sources/connections.rst.txt             |   42 +
 .../{stable => 1.0.1}/_sources/index.rst.txt       |    2 +-
 .../installing-providers-from-sources.rst.txt      |   18 +
 .../1.0.1/_static/_gen/css/main-custom.min.css     |    1 +
 .../1.0.1/_static/_gen/css/main.min.css            |    7 +
 .../1.0.1/_static/_gen/js/docs.js                  |    1 +
 .../_sphinx_javascript_frameworks_compat.js        |  134 ++
 .../1.0.1}/_static/basic.css                       |   38 +-
 .../1.0.1/_static/check-solid.svg                  |    4 +
 .../1.0.1/_static/clipboard.min.js                 |    7 +
 .../1.0.1/_static/copy-button.svg                  |    5 +
 .../1.0.1/_static/copybutton.css                   |   93 +
 .../1.0.1/_static/copybutton.js                    |  220 +++
 .../1.0.1/_static/copybutton_funcs.js              |   58 +
 .../1.0.1/_static/doctools.js                      |  264 +++
 .../_static/documentation_options.js               |    2 +-
 .../1.0.1/_static/file.png                         |  Bin 0 -> 286 bytes
 .../1.0.1/_static/graphviz.css                     |   19 +
 .../1.0.1/_static/jquery-3.6.0.js}                 |  227 +--
 .../1.0.1/_static/jquery.js                        |    2 +
 .../1.0.1/_static/language_data.js                 |  199 ++
 .../1.0.1/_static/minus.png                        |  Bin 0 -> 90 bytes
 .../1.0.1/_static/pin_32.png                       |  Bin 0 -> 1201 bytes
 .../1.0.1/_static/plus.png                         |  Bin 0 -> 90 bytes
 .../1.0.1/_static/pygments.css                     |   74 +
 .../1.0.1/_static/searchtools.js                   |  531 +++++
 .../1.0.1/_static/underscore-1.13.1.js             | 2042 ++++++++++++++++++++
 .../1.0.1/_static/underscore.js                    |    6 +
 .../{stable => 1.0.1}/commits.html                 |   32 +-
 .../{stable => 1.0.1}/connections.html             |    4 +-
 .../{stable => 1.0.1}/genindex.html                |    4 +-
 .../{stable => 1.0.1}/index.html                   |   23 +-
 .../installing-providers-from-sources.html         |   26 +-
 .../{stable => 1.0.1}/objects.inv                  |  Bin 691 -> 691 bytes
 .../{stable => 1.0.1}/py-modindex.html             |    4 +-
 .../{stable => 1.0.1}/search.html                  |    4 +-
 .../1.0.1/searchindex.js                           |    1 +
 .../airflow/providers/tabular/hooks/index.html     |    4 +-
 .../providers/tabular/hooks/tabular/index.html     |    4 +-
 .../_api/airflow/providers/tabular/index.html      |    4 +-
 .../providers/tabular/example_tabular/index.html   |    4 +-
 .../_api/tests/system/providers/tabular/index.html |    4 +-
 .../airflow/providers/tabular/hooks/tabular.html   |   11 +-
 .../stable/_modules/index.html                     |    4 +-
 .../system/providers/tabular/example_tabular.html  |    4 +-
 .../stable/_sources/commits.rst.txt                |   11 +
 .../stable/_sources/index.rst.txt                  |    2 +-
 .../stable/_static/documentation_options.js        |    2 +-
 .../stable/commits.html                            |   32 +-
 .../stable/connections.html                        |    4 +-
 .../stable/genindex.html                           |    4 +-
 .../stable/index.html                              |   23 +-
 .../stable/installing-providers-from-sources.html  |   26 +-
 .../stable/objects.inv                             |  Bin 691 -> 691 bytes
 .../stable/py-modindex.html                        |    4 +-
 .../stable/search.html                             |    4 +-
 .../stable/searchindex.js                          |    2 +-
 .../core-extensions/connections.html               |   16 +-
 .../core-extensions/extra-links.html               |  110 +-
 .../core-extensions/logging.html                   |    6 +-
 .../core-extensions/secrets-backends.html          |    2 +-
 .../operators-and-hooks-ref/apache.html            |    2 +-
 .../operators-and-hooks-ref/aws.html               |    4 +-
 .../operators-and-hooks-ref/azure.html             |    6 +-
 .../operators-and-hooks-ref/google.html            |  390 ++--
 .../operators-and-hooks-ref/protocol.html          |    8 +-
 .../operators-and-hooks-ref/services.html          |    8 +-
 .../operators-and-hooks-ref/software.html          |   32 +-
 docs/apache-airflow-providers/packages-ref.html    |    8 +-
 index.html                                         |   32 +-
 search/index.html                                  |    4 +-
 sitemap.xml                                        |   98 +-
 use-cases/adobe/index.html                         |    4 +-
 use-cases/adyen/index.html                         |    4 +-
 use-cases/big-fish-games/index.html                |    4 +-
 use-cases/dish/index.html                          |    4 +-
 use-cases/experity/index.html                      |    4 +-
 use-cases/onefootball/index.html                   |    4 +-
 use-cases/plarium-krasnodar/index.html             |    4 +-
 use-cases/seniorlink/index.html                    |    4 +-
 use-cases/sift/index.html                          |    4 +-
 206 files changed, 11697 insertions(+), 3319 deletions(-)

diff --git a/_gen/packages-metadata.json b/_gen/packages-metadata.json
index a90df134b8..f09ddbb5fd 100644
--- a/_gen/packages-metadata.json
+++ b/_gen/packages-metadata.json
@@ -1,19 +1,32 @@
 [
   {
-    "package-name": "apache-airflow-providers-mysql",
-    "stable-version": "3.1.0",
+    "package-name": "apache-airflow-providers-jira",
+    "stable-version": "3.0.1",
     "all-versions": [
       "1.0.0",
       "1.0.1",
       "1.0.2",
-      "1.1.0",
+      "2.0.0",
+      "2.0.1",
+      "2.0.2",
+      "2.0.3",
+      "2.0.4",
+      "2.0.5",
+      "3.0.0",
+      "3.0.1"
+    ]
+  },
+  {
+    "package-name": "apache-airflow-providers-airbyte",
+    "stable-version": "3.1.0",
+    "all-versions": [
+      "1.0.0",
       "2.0.0",
       "2.1.0",
       "2.1.1",
-      "2.2.0",
-      "2.2.1",
-      "2.2.2",
-      "2.2.3",
+      "2.1.2",
+      "2.1.3",
+      "2.1.4",
       "3.0.0",
       "3.1.0"
     ]
@@ -41,99 +54,72 @@
     ]
   },
   {
-    "package-name": "apache-airflow-providers-cncf-kubernetes",
-    "stable-version": "4.2.0",
+    "package-name": "apache-airflow-providers-openfaas",
+    "stable-version": "3.0.0",
     "all-versions": [
       "1.0.0",
-      "1.0.1",
-      "1.0.2",
       "1.1.0",
-      "1.2.0",
+      "1.1.1",
       "2.0.0",
       "2.0.1",
       "2.0.2",
       "2.0.3",
-      "2.1.0",
-      "2.2.0",
-      "3.0.0",
-      "3.0.1",
-      "3.0.2",
-      "3.1.0",
-      "3.1.1",
-      "3.1.2",
-      "4.0.0",
-      "4.0.1",
-      "4.0.2",
-      "4.1.0",
-      "4.2.0"
+      "3.0.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-jira",
-    "stable-version": "3.0.1",
+    "package-name": "apache-airflow-providers-opsgenie",
+    "stable-version": "4.0.0",
     "all-versions": [
       "1.0.0",
       "1.0.1",
       "1.0.2",
       "2.0.0",
       "2.0.1",
-      "2.0.2",
-      "2.0.3",
-      "2.0.4",
-      "2.0.5",
       "3.0.0",
-      "3.0.1"
-    ]
-  },
-  {
-    "package-name": "apache-airflow-providers-celery",
-    "stable-version": "3.0.0",
-    "all-versions": [
-      "1.0.0",
-      "1.0.1",
-      "2.0.0",
-      "2.1.0",
-      "2.1.1",
-      "2.1.2",
-      "2.1.3",
-      "2.1.4",
-      "3.0.0"
+      "3.0.1",
+      "3.0.2",
+      "3.0.3",
+      "3.1.0",
+      "4.0.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-apache-hdfs",
-    "stable-version": "3.0.1",
+    "package-name": "apache-airflow-providers-apache-beam",
+    "stable-version": "4.0.0",
     "all-versions": [
       "1.0.0",
       "1.0.1",
       "2.0.0",
-      "2.1.0",
-      "2.1.1",
-      "2.2.0",
-      "2.2.1",
-      "2.2.2",
-      "2.2.3",
       "3.0.0",
-      "3.0.1"
+      "3.0.1",
+      "3.1.0",
+      "3.2.0",
+      "3.2.1",
+      "3.3.0",
+      "3.4.0",
+      "4.0.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-apache-pinot",
+    "package-name": "apache-airflow-providers-microsoft-mssql",
     "stable-version": "3.1.0",
     "all-versions": [
       "1.0.0",
       "1.0.1",
+      "1.1.0",
       "2.0.0",
       "2.0.1",
-      "2.0.2",
-      "2.0.3",
-      "2.0.4",
+      "2.1.0",
+      "2.1.1",
+      "2.1.2",
+      "2.1.3",
       "3.0.0",
       "3.1.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-segment",
+    "package-name": "apache-airflow-providers-apache-sqoop",
     "stable-version": "3.0.0",
     "all-versions": [
       "1.0.0",
@@ -141,147 +127,180 @@
       "2.0.0",
       "2.0.1",
       "2.0.2",
-      "2.0.3",
-      "2.0.4",
+      "2.1.0",
+      "2.1.1",
+      "2.1.2",
+      "2.1.3",
       "3.0.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-qubole",
-    "stable-version": "3.1.0",
+    "package-name": "apache-airflow-providers-salesforce",
+    "stable-version": "5.0.0",
     "all-versions": [
       "1.0.0",
       "1.0.1",
-      "1.0.2",
       "2.0.0",
-      "2.0.1",
-      "2.1.0",
-      "2.1.1",
-      "2.1.2",
-      "2.1.3",
       "3.0.0",
-      "3.1.0"
+      "3.1.0",
+      "3.2.0",
+      "3.3.0",
+      "3.4.0",
+      "3.4.1",
+      "3.4.2",
+      "3.4.3",
+      "3.4.4",
+      "4.0.0",
+      "5.0.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-jdbc",
-    "stable-version": "3.1.0",
+    "package-name": "apache-airflow-providers-zendesk",
+    "stable-version": "4.0.0",
     "all-versions": [
       "1.0.0",
       "1.0.1",
       "2.0.0",
       "2.0.1",
-      "2.1.0",
-      "2.1.1",
-      "2.1.2",
-      "2.1.3",
       "3.0.0",
-      "3.1.0"
+      "3.0.1",
+      "3.0.2",
+      "3.0.3",
+      "4.0.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-grpc",
+    "package-name": "apache-airflow-providers-microsoft-winrm",
     "stable-version": "3.0.0",
     "all-versions": [
       "1.0.0",
       "1.0.1",
       "1.1.0",
+      "1.2.0",
       "2.0.0",
       "2.0.1",
       "2.0.2",
       "2.0.3",
       "2.0.4",
+      "2.0.5",
       "3.0.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-snowflake",
+    "package-name": "apache-airflow-providers-apache-hive",
     "stable-version": "3.1.0",
+    "all-versions": [
+      "1.0.0",
+      "1.0.1",
+      "1.0.2",
+      "1.0.3",
+      "2.0.0",
+      "2.0.1",
+      "2.0.2",
+      "2.0.3",
+      "2.1.0",
+      "2.2.0",
+      "2.3.0",
+      "2.3.1",
+      "2.3.2",
+      "2.3.3",
+      "3.0.0",
+      "3.1.0"
+    ]
+  },
+  {
+    "package-name": "apache-airflow-providers-sftp",
+    "stable-version": "4.0.0",
     "all-versions": [
       "1.0.0",
       "1.1.0",
       "1.1.1",
       "1.2.0",
-      "1.3.0",
       "2.0.0",
       "2.1.0",
       "2.1.1",
       "2.2.0",
       "2.3.0",
-      "2.3.1",
       "2.4.0",
+      "2.4.1",
       "2.5.0",
       "2.5.1",
       "2.5.2",
       "2.6.0",
-      "2.7.0",
       "3.0.0",
-      "3.1.0"
+      "4.0.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-microsoft-mssql",
-    "stable-version": "3.1.0",
+    "package-name": "apache-airflow-providers-samba",
+    "stable-version": "4.0.0",
+    "all-versions": [
+      "1.0.0",
+      "1.0.1",
+      "2.0.0",
+      "3.0.0",
+      "3.0.1",
+      "3.0.2",
+      "3.0.3",
+      "3.0.4",
+      "4.0.0"
+    ]
+  },
+  {
+    "package-name": "apache-airflow-providers-apache-cassandra",
+    "stable-version": "3.0.0",
     "all-versions": [
       "1.0.0",
       "1.0.1",
-      "1.1.0",
       "2.0.0",
       "2.0.1",
       "2.1.0",
       "2.1.1",
       "2.1.2",
       "2.1.3",
-      "3.0.0",
-      "3.1.0"
+      "3.0.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-facebook",
-    "stable-version": "3.0.1",
+    "package-name": "apache-airflow-providers-plexus",
+    "stable-version": "3.0.0",
     "all-versions": [
       "1.0.0",
       "1.0.1",
-      "1.1.0",
       "2.0.0",
       "2.0.1",
-      "2.1.0",
-      "2.2.0",
-      "2.2.1",
-      "2.2.2",
-      "2.2.3",
-      "3.0.0",
-      "3.0.1"
+      "2.0.2",
+      "2.0.3",
+      "2.0.4",
+      "3.0.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-neo4j",
+    "package-name": "apache-airflow-providers-imap",
     "stable-version": "3.0.0",
     "all-versions": [
       "1.0.0",
       "1.0.1",
       "2.0.0",
       "2.0.1",
-      "2.0.2",
       "2.1.0",
-      "2.1.1",
-      "2.1.2",
-      "2.1.3",
+      "2.2.0",
+      "2.2.1",
+      "2.2.2",
+      "2.2.3",
       "3.0.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-apache-hive",
+    "package-name": "apache-airflow-providers-apache-druid",
     "stable-version": "3.1.0",
     "all-versions": [
       "1.0.0",
       "1.0.1",
-      "1.0.2",
-      "1.0.3",
+      "1.1.0",
       "2.0.0",
       "2.0.1",
       "2.0.2",
-      "2.0.3",
       "2.1.0",
       "2.2.0",
       "2.3.0",
@@ -293,57 +312,77 @@
     ]
   },
   {
-    "package-name": "apache-airflow-providers-common-sql",
-    "stable-version": "1.0.0",
-    "all-versions": [
-      "1.0.0"
-    ]
-  },
-  {
-    "package-name": "helm-chart",
-    "stable-version": "1.6.0",
+    "package-name": "apache-airflow-providers-amazon",
+    "stable-version": "4.1.0",
     "all-versions": [
       "1.0.0",
       "1.1.0",
       "1.2.0",
       "1.3.0",
       "1.4.0",
-      "1.5.0",
-      "1.6.0"
-    ]
-  },
-  {
-    "package-name": "apache-airflow-providers-dbt-cloud",
-    "stable-version": "2.0.1",
-    "all-versions": [
-      "1.0.1",
-      "1.0.2",
       "2.0.0",
-      "2.0.1"
+      "2.1.0",
+      "2.2.0",
+      "2.3.0",
+      "2.4.0",
+      "2.5.0",
+      "2.6.0",
+      "3.0.0",
+      "3.1.1",
+      "3.2.0",
+      "3.3.0",
+      "3.4.0",
+      "4.0.0",
+      "4.1.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-apache-pig",
-    "stable-version": "3.0.0",
+    "package-name": "apache-airflow-providers-oracle",
+    "stable-version": "3.2.0",
     "all-versions": [
       "1.0.0",
       "1.0.1",
+      "1.1.0",
       "2.0.0",
       "2.0.1",
-      "2.0.2",
-      "2.0.3",
-      "2.0.4",
-      "3.0.0"
+      "2.1.0",
+      "2.2.0",
+      "2.2.1",
+      "2.2.2",
+      "2.2.3",
+      "3.0.0",
+      "3.1.0",
+      "3.2.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-pagerduty",
+    "package-name": "apache-airflow-providers-mysql",
+    "stable-version": "3.1.0",
+    "all-versions": [
+      "1.0.0",
+      "1.0.1",
+      "1.0.2",
+      "1.1.0",
+      "2.0.0",
+      "2.1.0",
+      "2.1.1",
+      "2.2.0",
+      "2.2.1",
+      "2.2.2",
+      "2.2.3",
+      "3.0.0",
+      "3.1.0"
+    ]
+  },
+  {
+    "package-name": "apache-airflow-providers-neo4j",
     "stable-version": "3.0.0",
     "all-versions": [
       "1.0.0",
       "1.0.1",
       "2.0.0",
       "2.0.1",
+      "2.0.2",
       "2.1.0",
       "2.1.1",
       "2.1.2",
@@ -352,70 +391,49 @@
     ]
   },
   {
-    "package-name": "apache-airflow-providers-github",
-    "stable-version": "2.1.0",
+    "package-name": "apache-airflow-providers-papermill",
+    "stable-version": "3.0.0",
     "all-versions": [
       "1.0.0",
       "1.0.1",
       "1.0.2",
-      "1.0.3",
       "2.0.0",
-      "2.1.0"
+      "2.0.1",
+      "2.1.0",
+      "2.2.0",
+      "2.2.1",
+      "2.2.2",
+      "2.2.3",
+      "3.0.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-ftp",
+    "package-name": "apache-airflow-providers-apache-pinot",
     "stable-version": "3.1.0",
     "all-versions": [
       "1.0.0",
       "1.0.1",
-      "1.1.0",
       "2.0.0",
       "2.0.1",
-      "2.1.0",
-      "2.1.1",
-      "2.1.2",
+      "2.0.2",
+      "2.0.3",
+      "2.0.4",
       "3.0.0",
       "3.1.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-tabular",
-    "stable-version": "1.0.0",
-    "all-versions": [
-      "1.0.0"
-    ]
-  },
-  {
-    "package-name": "apache-airflow-providers-influxdb",
-    "stable-version": "2.0.0",
-    "all-versions": [
-      "1.0.0",
-      "1.1.0",
-      "1.1.1",
-      "1.1.2",
-      "1.1.3",
-      "2.0.0"
-    ]
-  },
-  {
-    "package-name": "apache-airflow-providers-postgres",
-    "stable-version": "5.1.0",
+    "package-name": "apache-airflow-providers-apache-pig",
+    "stable-version": "3.0.0",
     "all-versions": [
       "1.0.0",
       "1.0.1",
-      "1.0.2",
       "2.0.0",
-      "2.1.0",
-      "2.2.0",
-      "2.3.0",
-      "2.4.0",
-      "3.0.0",
-      "4.0.0",
-      "4.0.1",
-      "4.1.0",
-      "5.0.0",
-      "5.1.0"
+      "2.0.1",
+      "2.0.2",
+      "2.0.3",
+      "2.0.4",
+      "3.0.0"
     ]
   },
   {
@@ -449,34 +467,52 @@
     ]
   },
   {
-    "package-name": "apache-airflow-providers-papermill",
+    "package-name": "apache-airflow-providers-mongo",
     "stable-version": "3.0.0",
     "all-versions": [
       "1.0.0",
       "1.0.1",
-      "1.0.2",
       "2.0.0",
-      "2.0.1",
       "2.1.0",
       "2.2.0",
-      "2.2.1",
-      "2.2.2",
-      "2.2.3",
+      "2.3.0",
+      "2.3.1",
+      "2.3.2",
+      "2.3.3",
       "3.0.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-discord",
+    "package-name": "apache-airflow-providers-tableau",
+    "stable-version": "3.0.1",
+    "all-versions": [
+      "1.0.0",
+      "2.0.0",
+      "2.1.0",
+      "2.1.1",
+      "2.1.2",
+      "2.1.3",
+      "2.1.4",
+      "2.1.5",
+      "2.1.6",
+      "2.1.7",
+      "2.1.8",
+      "3.0.0",
+      "3.0.1"
+    ]
+  },
+  {
+    "package-name": "apache-airflow-providers-singularity",
     "stable-version": "3.0.0",
     "all-versions": [
       "1.0.0",
       "1.0.1",
+      "1.1.0",
       "2.0.0",
       "2.0.1",
       "2.0.2",
       "2.0.3",
       "2.0.4",
-      "2.1.4",
       "3.0.0"
     ]
   },
@@ -498,287 +534,279 @@
     ]
   },
   {
-    "package-name": "apache-airflow-providers-trino",
-    "stable-version": "3.1.0",
+    "package-name": "apache-airflow-providers-telegram",
+    "stable-version": "3.0.0",
     "all-versions": [
       "1.0.0",
+      "1.0.1",
+      "1.0.2",
       "2.0.0",
       "2.0.1",
       "2.0.2",
-      "2.1.0",
-      "2.1.1",
-      "2.1.2",
-      "2.2.0",
-      "2.3.0",
-      "3.0.0",
-      "3.1.0"
-    ]
-  },
-  {
-    "package-name": "apache-airflow-providers-sftp",
-    "stable-version": "3.0.0",
-    "all-versions": [
-      "1.0.0",
-      "1.1.0",
-      "1.1.1",
-      "1.2.0",
-      "2.0.0",
-      "2.1.0",
-      "2.1.1",
-      "2.2.0",
-      "2.3.0",
-      "2.4.0",
-      "2.4.1",
-      "2.5.0",
-      "2.5.1",
-      "2.5.2",
-      "2.6.0",
+      "2.0.3",
+      "2.0.4",
       "3.0.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-microsoft-psrp",
+    "package-name": "apache-airflow-providers-influxdb",
     "stable-version": "2.0.0",
     "all-versions": [
       "1.0.0",
-      "1.0.1",
       "1.1.0",
       "1.1.1",
       "1.1.2",
       "1.1.3",
-      "1.1.4",
       "2.0.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-sendgrid",
+    "package-name": "apache-airflow-providers-apache-livy",
     "stable-version": "3.0.0",
     "all-versions": [
       "1.0.0",
       "1.0.1",
-      "1.0.2",
+      "1.1.0",
       "2.0.0",
-      "2.0.1",
-      "2.0.2",
-      "2.0.3",
-      "2.0.4",
+      "2.1.0",
+      "2.2.0",
+      "2.2.1",
+      "2.2.2",
+      "2.2.3",
       "3.0.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-amazon",
+    "package-name": "apache-airflow-providers-microsoft-azure",
     "stable-version": "4.1.0",
     "all-versions": [
       "1.0.0",
       "1.1.0",
       "1.2.0",
       "1.3.0",
-      "1.4.0",
       "2.0.0",
-      "2.1.0",
-      "2.2.0",
-      "2.3.0",
-      "2.4.0",
-      "2.5.0",
-      "2.6.0",
       "3.0.0",
+      "3.1.0",
       "3.1.1",
       "3.2.0",
       "3.3.0",
       "3.4.0",
+      "3.5.0",
+      "3.6.0",
+      "3.7.0",
+      "3.7.1",
+      "3.7.2",
+      "3.8.0",
+      "3.9.0",
       "4.0.0",
       "4.1.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-apache-cassandra",
+    "package-name": "apache-airflow-providers-discord",
     "stable-version": "3.0.0",
     "all-versions": [
       "1.0.0",
       "1.0.1",
       "2.0.0",
       "2.0.1",
-      "2.1.0",
-      "2.1.1",
-      "2.1.2",
-      "2.1.3",
+      "2.0.2",
+      "2.0.3",
+      "2.0.4",
+      "2.1.4",
       "3.0.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-apache-kylin",
-    "stable-version": "3.0.0",
+    "package-name": "apache-airflow-providers-apache-drill",
+    "stable-version": "2.1.0",
     "all-versions": [
       "1.0.0",
       "1.0.1",
+      "1.0.2",
+      "1.0.3",
+      "1.0.4",
       "2.0.0",
-      "2.0.1",
-      "2.0.2",
-      "2.0.3",
-      "2.0.4",
-      "3.0.0"
+      "2.1.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-airbyte",
-    "stable-version": "3.1.0",
+    "package-name": "apache-airflow-providers-postgres",
+    "stable-version": "5.1.0",
     "all-versions": [
       "1.0.0",
+      "1.0.1",
+      "1.0.2",
       "2.0.0",
       "2.1.0",
-      "2.1.1",
-      "2.1.2",
-      "2.1.3",
-      "2.1.4",
+      "2.2.0",
+      "2.3.0",
+      "2.4.0",
       "3.0.0",
-      "3.1.0"
+      "4.0.0",
+      "4.0.1",
+      "4.1.0",
+      "5.0.0",
+      "5.1.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-jenkins",
-    "stable-version": "3.0.0",
+    "package-name": "apache-airflow-providers-microsoft-psrp",
+    "stable-version": "2.0.0",
     "all-versions": [
       "1.0.0",
       "1.0.1",
       "1.1.0",
+      "1.1.1",
+      "1.1.2",
+      "1.1.3",
+      "1.1.4",
+      "2.0.0"
+    ]
+  },
+  {
+    "package-name": "apache-airflow-providers-databricks",
+    "stable-version": "3.1.0",
+    "all-versions": [
+      "1.0.0",
+      "1.0.1",
       "2.0.0",
       "2.0.1",
       "2.0.2",
-      "2.0.3",
-      "2.0.4",
-      "2.0.5",
-      "2.0.6",
-      "2.0.7",
       "2.1.0",
-      "3.0.0"
+      "2.2.0",
+      "2.3.0",
+      "2.4.0",
+      "2.5.0",
+      "2.6.0",
+      "2.7.0",
+      "3.0.0",
+      "3.1.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-plexus",
-    "stable-version": "3.0.0",
+    "package-name": "apache-airflow-providers-presto",
+    "stable-version": "3.1.0",
     "all-versions": [
       "1.0.0",
       "1.0.1",
+      "1.0.2",
       "2.0.0",
       "2.0.1",
-      "2.0.2",
-      "2.0.3",
-      "2.0.4",
-      "3.0.0"
+      "2.1.0",
+      "2.1.1",
+      "2.1.2",
+      "2.2.0",
+      "2.2.1",
+      "3.0.0",
+      "3.1.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-opsgenie",
-    "stable-version": "4.0.0",
+    "package-name": "apache-airflow-providers-sendgrid",
+    "stable-version": "3.0.0",
     "all-versions": [
       "1.0.0",
       "1.0.1",
       "1.0.2",
       "2.0.0",
       "2.0.1",
-      "3.0.0",
-      "3.0.1",
-      "3.0.2",
-      "3.0.3",
-      "3.1.0",
-      "4.0.0"
+      "2.0.2",
+      "2.0.3",
+      "2.0.4",
+      "3.0.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-apache-livy",
+    "package-name": "apache-airflow-providers-cloudant",
     "stable-version": "3.0.0",
     "all-versions": [
       "1.0.0",
       "1.0.1",
-      "1.1.0",
       "2.0.0",
-      "2.1.0",
-      "2.2.0",
-      "2.2.1",
-      "2.2.2",
-      "2.2.3",
+      "2.0.1",
+      "2.0.2",
+      "2.0.3",
+      "2.0.4",
       "3.0.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-http",
-    "stable-version": "4.0.0",
+    "package-name": "apache-airflow-providers-exasol",
+    "stable-version": "3.1.0",
     "all-versions": [
       "1.0.0",
       "1.1.0",
       "1.1.1",
       "2.0.0",
       "2.0.1",
-      "2.0.2",
-      "2.0.3",
       "2.1.0",
       "2.1.1",
       "2.1.2",
+      "2.1.3",
       "3.0.0",
-      "4.0.0"
+      "3.1.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-microsoft-winrm",
+    "package-name": "apache-airflow-providers-common-sql",
+    "stable-version": "1.0.0",
+    "all-versions": [
+      "1.0.0"
+    ]
+  },
+  {
+    "package-name": "apache-airflow-providers-redis",
     "stable-version": "3.0.0",
     "all-versions": [
       "1.0.0",
       "1.0.1",
-      "1.1.0",
-      "1.2.0",
       "2.0.0",
       "2.0.1",
       "2.0.2",
       "2.0.3",
       "2.0.4",
-      "2.0.5",
       "3.0.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-samba",
-    "stable-version": "4.0.0",
+    "package-name": "apache-airflow-providers-ssh",
+    "stable-version": "3.1.0",
     "all-versions": [
       "1.0.0",
-      "1.0.1",
+      "1.1.0",
+      "1.2.0",
+      "1.3.0",
       "2.0.0",
+      "2.1.0",
+      "2.1.1",
+      "2.2.0",
+      "2.3.0",
+      "2.4.0",
+      "2.4.1",
+      "2.4.2",
+      "2.4.3",
+      "2.4.4",
       "3.0.0",
-      "3.0.1",
-      "3.0.2",
-      "3.0.3",
-      "3.0.4",
-      "4.0.0"
-    ]
-  },
-  {
-    "package-name": "apache-airflow-providers-apache-drill",
-    "stable-version": "2.1.0",
-    "all-versions": [
-      "1.0.0",
-      "1.0.1",
-      "1.0.2",
-      "1.0.3",
-      "1.0.4",
-      "2.0.0",
-      "2.1.0"
+      "3.1.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-docker",
+    "package-name": "apache-airflow-providers-snowflake",
     "stable-version": "3.1.0",
     "all-versions": [
       "1.0.0",
-      "1.0.1",
-      "1.0.2",
       "1.1.0",
+      "1.1.1",
       "1.2.0",
+      "1.3.0",
       "2.0.0",
       "2.1.0",
       "2.1.1",
       "2.2.0",
       "2.3.0",
+      "2.3.1",
       "2.4.0",
-      "2.4.1",
       "2.5.0",
       "2.5.1",
       "2.5.2",
@@ -789,49 +817,35 @@
     ]
   },
   {
-    "package-name": "apache-airflow-providers-zendesk",
-    "stable-version": "4.0.0",
+    "package-name": "apache-airflow-providers-trino",
+    "stable-version": "3.1.0",
     "all-versions": [
       "1.0.0",
-      "1.0.1",
       "2.0.0",
       "2.0.1",
+      "2.0.2",
+      "2.1.0",
+      "2.1.1",
+      "2.1.2",
+      "2.2.0",
+      "2.3.0",
       "3.0.0",
-      "3.0.1",
-      "3.0.2",
-      "3.0.3",
-      "4.0.0"
+      "3.1.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-openfaas",
-    "stable-version": "3.0.0",
+    "package-name": "apache-airflow-providers-odbc",
+    "stable-version": "3.1.0",
     "all-versions": [
       "1.0.0",
-      "1.1.0",
-      "1.1.1",
+      "1.0.1",
       "2.0.0",
       "2.0.1",
       "2.0.2",
       "2.0.3",
-      "3.0.0"
-    ]
-  },
-  {
-    "package-name": "apache-airflow-providers-apache-beam",
-    "stable-version": "4.0.0",
-    "all-versions": [
-      "1.0.0",
-      "1.0.1",
-      "2.0.0",
+      "2.0.4",
       "3.0.0",
-      "3.0.1",
-      "3.1.0",
-      "3.2.0",
-      "3.2.1",
-      "3.3.0",
-      "3.4.0",
-      "4.0.0"
+      "3.1.0"
     ]
   },
   {
@@ -850,99 +864,169 @@
     ]
   },
   {
-    "package-name": "apache-airflow-providers-ssh",
-    "stable-version": "3.1.0",
+    "package-name": "apache-airflow",
+    "stable-version": "2.3.3",
     "all-versions": [
-      "1.0.0",
-      "1.1.0",
-      "1.2.0",
-      "1.3.0",
+      "1.10.1",
+      "1.10.2",
+      "1.10.3",
+      "1.10.4",
+      "1.10.5",
+      "1.10.6",
+      "1.10.7",
+      "1.10.8",
+      "1.10.9",
+      "1.10.10",
+      "1.10.11",
+      "1.10.12",
+      "1.10.13",
+      "1.10.14",
+      "1.10.15",
       "2.0.0",
+      "2.0.1",
+      "2.0.2",
       "2.1.0",
       "2.1.1",
+      "2.1.2",
+      "2.1.3",
+      "2.1.4",
       "2.2.0",
+      "2.2.1",
+      "2.2.2",
+      "2.2.3",
+      "2.2.4",
+      "2.2.5",
       "2.3.0",
-      "2.4.0",
-      "2.4.1",
-      "2.4.2",
-      "2.4.3",
-      "2.4.4",
-      "3.0.0",
-      "3.1.0"
+      "2.3.1",
+      "2.3.2",
+      "2.3.3"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-oracle",
-    "stable-version": "3.2.0",
+    "package-name": "apache-airflow-providers-pagerduty",
+    "stable-version": "3.0.0",
     "all-versions": [
       "1.0.0",
       "1.0.1",
-      "1.1.0",
       "2.0.0",
       "2.0.1",
       "2.1.0",
-      "2.2.0",
-      "2.2.1",
-      "2.2.2",
-      "2.2.3",
-      "3.0.0",
-      "3.1.0",
-      "3.2.0"
+      "2.1.1",
+      "2.1.2",
+      "2.1.3",
+      "3.0.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-tableau",
-    "stable-version": "3.0.1",
+    "package-name": "apache-airflow-providers-grpc",
+    "stable-version": "3.0.0",
     "all-versions": [
       "1.0.0",
+      "1.0.1",
+      "1.1.0",
       "2.0.0",
+      "2.0.1",
+      "2.0.2",
+      "2.0.3",
+      "2.0.4",
+      "3.0.0"
+    ]
+  },
+  {
+    "package-name": "apache-airflow-providers-http",
+    "stable-version": "4.0.0",
+    "all-versions": [
+      "1.0.0",
+      "1.1.0",
+      "1.1.1",
+      "2.0.0",
+      "2.0.1",
+      "2.0.2",
+      "2.0.3",
       "2.1.0",
       "2.1.1",
       "2.1.2",
-      "2.1.3",
-      "2.1.4",
-      "2.1.5",
-      "2.1.6",
-      "2.1.7",
-      "2.1.8",
       "3.0.0",
-      "3.0.1"
+      "4.0.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-redis",
-    "stable-version": "3.0.0",
+    "package-name": "helm-chart",
+    "stable-version": "1.6.0",
+    "all-versions": [
+      "1.0.0",
+      "1.1.0",
+      "1.2.0",
+      "1.3.0",
+      "1.4.0",
+      "1.5.0",
+      "1.6.0"
+    ]
+  },
+  {
+    "package-name": "apache-airflow-providers-slack",
+    "stable-version": "5.1.0",
+    "all-versions": [
+      "1.0.0",
+      "2.0.0",
+      "3.0.0",
+      "4.0.0",
+      "4.0.1",
+      "4.1.0",
+      "4.2.0",
+      "4.2.1",
+      "4.2.2",
+      "4.2.3",
+      "5.0.0",
+      "5.1.0"
+    ]
+  },
+  {
+    "package-name": "apache-airflow-providers-cncf-kubernetes",
+    "stable-version": "4.2.0",
     "all-versions": [
       "1.0.0",
       "1.0.1",
+      "1.0.2",
+      "1.1.0",
+      "1.2.0",
       "2.0.0",
       "2.0.1",
       "2.0.2",
       "2.0.3",
-      "2.0.4",
-      "3.0.0"
+      "2.1.0",
+      "2.2.0",
+      "3.0.0",
+      "3.0.1",
+      "3.0.2",
+      "3.1.0",
+      "3.1.1",
+      "3.1.2",
+      "4.0.0",
+      "4.0.1",
+      "4.0.2",
+      "4.1.0",
+      "4.2.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-presto",
+    "package-name": "apache-airflow-providers-vertica",
     "stable-version": "3.1.0",
     "all-versions": [
       "1.0.0",
       "1.0.1",
-      "1.0.2",
       "2.0.0",
       "2.0.1",
       "2.1.0",
       "2.1.1",
       "2.1.2",
-      "2.2.0",
-      "2.2.1",
+      "2.1.3",
       "3.0.0",
       "3.1.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-apache-sqoop",
+    "package-name": "apache-airflow-providers-datadog",
     "stable-version": "3.0.0",
     "all-versions": [
       "1.0.0",
@@ -950,20 +1034,17 @@
       "2.0.0",
       "2.0.1",
       "2.0.2",
-      "2.1.0",
-      "2.1.1",
-      "2.1.2",
-      "2.1.3",
+      "2.0.3",
+      "2.0.4",
       "3.0.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-telegram",
+    "package-name": "apache-airflow-providers-segment",
     "stable-version": "3.0.0",
     "all-versions": [
       "1.0.0",
       "1.0.1",
-      "1.0.2",
       "2.0.0",
       "2.0.1",
       "2.0.2",
@@ -973,76 +1054,42 @@
     ]
   },
   {
-    "package-name": "apache-airflow-providers-google",
-    "stable-version": "8.2.0",
+    "package-name": "apache-airflow-providers-arangodb",
+    "stable-version": "2.0.0",
     "all-versions": [
-      "0.0.1",
-      "0.0.2",
       "1.0.0",
-      "2.0.0",
-      "2.1.0",
-      "2.2.0",
-      "3.0.0",
-      "4.0.0",
-      "5.0.0",
-      "5.1.0",
-      "6.0.0",
-      "6.1.0",
-      "6.2.0",
-      "6.3.0",
-      "6.4.0",
-      "6.5.0",
-      "6.6.0",
-      "6.7.0",
-      "6.8.0",
-      "7.0.0",
-      "8.0.0",
-      "8.1.0",
-      "8.2.0"
+      "2.0.0"
     ]
   },
-  {
-    "package-name": "apache-airflow-providers-apache-druid",
-    "stable-version": "3.1.0",
-    "all-versions": [
-      "1.0.0",
-      "1.0.1",
-      "1.1.0",
-      "2.0.0",
-      "2.0.1",
-      "2.0.2",
-      "2.1.0",
-      "2.2.0",
-      "2.3.0",
-      "2.3.1",
-      "2.3.2",
-      "2.3.3",
-      "3.0.0",
-      "3.1.0"
+  {
+    "package-name": "apache-airflow-providers-dbt-cloud",
+    "stable-version": "2.0.1",
+    "all-versions": [
+      "1.0.1",
+      "1.0.2",
+      "2.0.0",
+      "2.0.1"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-databricks",
+    "package-name": "apache-airflow-providers-qubole",
     "stable-version": "3.1.0",
     "all-versions": [
       "1.0.0",
       "1.0.1",
+      "1.0.2",
       "2.0.0",
       "2.0.1",
-      "2.0.2",
       "2.1.0",
-      "2.2.0",
-      "2.3.0",
-      "2.4.0",
-      "2.5.0",
-      "2.6.0",
-      "2.7.0",
+      "2.1.1",
+      "2.1.2",
+      "2.1.3",
       "3.0.0",
       "3.1.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-vertica",
+    "package-name": "apache-airflow-providers-jdbc",
     "stable-version": "3.1.0",
     "all-versions": [
       "1.0.0",
@@ -1058,62 +1105,54 @@
     ]
   },
   {
-    "package-name": "apache-airflow-providers-imap",
-    "stable-version": "3.0.0",
+    "package-name": "apache-airflow-providers-alibaba",
+    "stable-version": "2.0.1",
     "all-versions": [
       "1.0.0",
       "1.0.1",
+      "1.1.0",
+      "1.1.1",
       "2.0.0",
-      "2.0.1",
-      "2.1.0",
-      "2.2.0",
-      "2.2.1",
-      "2.2.2",
-      "2.2.3",
-      "3.0.0"
+      "2.0.1"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-odbc",
-    "stable-version": "3.1.0",
+    "package-name": "apache-airflow-providers-jenkins",
+    "stable-version": "3.0.0",
     "all-versions": [
       "1.0.0",
       "1.0.1",
+      "1.1.0",
       "2.0.0",
       "2.0.1",
       "2.0.2",
       "2.0.3",
       "2.0.4",
-      "3.0.0",
-      "3.1.0"
-    ]
-  },
-  {
-    "package-name": "apache-airflow-providers-arangodb",
-    "stable-version": "2.0.0",
-    "all-versions": [
-      "1.0.0",
-      "2.0.0"
+      "2.0.5",
+      "2.0.6",
+      "2.0.7",
+      "2.1.0",
+      "3.0.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-mongo",
-    "stable-version": "3.0.0",
+    "package-name": "apache-airflow-providers-ftp",
+    "stable-version": "3.1.0",
     "all-versions": [
       "1.0.0",
       "1.0.1",
+      "1.1.0",
       "2.0.0",
+      "2.0.1",
       "2.1.0",
-      "2.2.0",
-      "2.3.0",
-      "2.3.1",
-      "2.3.2",
-      "2.3.3",
-      "3.0.0"
+      "2.1.1",
+      "2.1.2",
+      "3.0.0",
+      "3.1.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-datadog",
+    "package-name": "apache-airflow-providers-apache-kylin",
     "stable-version": "3.0.0",
     "all-versions": [
       "1.0.0",
@@ -1127,115 +1166,101 @@
     ]
   },
   {
-    "package-name": "apache-airflow-providers-dingding",
-    "stable-version": "3.0.0",
+    "package-name": "apache-airflow-providers-facebook",
+    "stable-version": "3.0.1",
     "all-versions": [
       "1.0.0",
       "1.0.1",
-      "1.0.2",
+      "1.1.0",
       "2.0.0",
       "2.0.1",
-      "2.0.2",
-      "2.0.3",
-      "2.0.4",
-      "3.0.0"
+      "2.1.0",
+      "2.2.0",
+      "2.2.1",
+      "2.2.2",
+      "2.2.3",
+      "3.0.0",
+      "3.0.1"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-slack",
-    "stable-version": "5.1.0",
+    "package-name": "apache-airflow-providers-docker",
+    "stable-version": "3.1.0",
     "all-versions": [
       "1.0.0",
+      "1.0.1",
+      "1.0.2",
+      "1.1.0",
+      "1.2.0",
       "2.0.0",
+      "2.1.0",
+      "2.1.1",
+      "2.2.0",
+      "2.3.0",
+      "2.4.0",
+      "2.4.1",
+      "2.5.0",
+      "2.5.1",
+      "2.5.2",
+      "2.6.0",
+      "2.7.0",
       "3.0.0",
-      "4.0.0",
-      "4.0.1",
-      "4.1.0",
-      "4.2.0",
-      "4.2.1",
-      "4.2.2",
-      "4.2.3",
-      "5.0.0",
-      "5.1.0"
+      "3.1.0"
     ]
   },
   {
-    "package-name": "apache-airflow",
-    "stable-version": "2.3.3",
+    "package-name": "apache-airflow-providers-apache-hdfs",
+    "stable-version": "3.0.1",
     "all-versions": [
-      "1.10.1",
-      "1.10.2",
-      "1.10.3",
-      "1.10.4",
-      "1.10.5",
-      "1.10.6",
-      "1.10.7",
-      "1.10.8",
-      "1.10.9",
-      "1.10.10",
-      "1.10.11",
-      "1.10.12",
-      "1.10.13",
-      "1.10.14",
-      "1.10.15",
+      "1.0.0",
+      "1.0.1",
       "2.0.0",
-      "2.0.1",
-      "2.0.2",
       "2.1.0",
       "2.1.1",
-      "2.1.2",
-      "2.1.3",
-      "2.1.4",
       "2.2.0",
       "2.2.1",
       "2.2.2",
       "2.2.3",
-      "2.2.4",
-      "2.2.5",
-      "2.3.0",
-      "2.3.1",
-      "2.3.2",
-      "2.3.3"
-    ]
-  },
-  {
-    "package-name": "apache-airflow-providers-cloudant",
-    "stable-version": "3.0.0",
-    "all-versions": [
-      "1.0.0",
-      "1.0.1",
-      "2.0.0",
-      "2.0.1",
-      "2.0.2",
-      "2.0.3",
-      "2.0.4",
-      "3.0.0"
+      "3.0.0",
+      "3.0.1"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-exasol",
-    "stable-version": "3.1.0",
+    "package-name": "apache-airflow-providers-google",
+    "stable-version": "8.2.0",
     "all-versions": [
+      "0.0.1",
+      "0.0.2",
       "1.0.0",
-      "1.1.0",
-      "1.1.1",
       "2.0.0",
-      "2.0.1",
       "2.1.0",
-      "2.1.1",
-      "2.1.2",
-      "2.1.3",
+      "2.2.0",
       "3.0.0",
-      "3.1.0"
+      "4.0.0",
+      "5.0.0",
+      "5.1.0",
+      "6.0.0",
+      "6.1.0",
+      "6.2.0",
+      "6.3.0",
+      "6.4.0",
+      "6.5.0",
+      "6.6.0",
+      "6.7.0",
+      "6.8.0",
+      "7.0.0",
+      "8.0.0",
+      "8.1.0",
+      "8.2.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-singularity",
+    "package-name": "apache-airflow-providers-dingding",
     "stable-version": "3.0.0",
     "all-versions": [
       "1.0.0",
       "1.0.1",
-      "1.1.0",
+      "1.0.2",
       "2.0.0",
       "2.0.1",
       "2.0.2",
@@ -1264,61 +1289,38 @@
     ]
   },
   {
-    "package-name": "apache-airflow-providers-microsoft-azure",
-    "stable-version": "4.1.0",
+    "package-name": "apache-airflow-providers-tabular",
+    "stable-version": "1.0.1",
     "all-versions": [
       "1.0.0",
-      "1.1.0",
-      "1.2.0",
-      "1.3.0",
-      "2.0.0",
-      "3.0.0",
-      "3.1.0",
-      "3.1.1",
-      "3.2.0",
-      "3.3.0",
-      "3.4.0",
-      "3.5.0",
-      "3.6.0",
-      "3.7.0",
-      "3.7.1",
-      "3.7.2",
-      "3.8.0",
-      "3.9.0",
-      "4.0.0",
-      "4.1.0"
+      "1.0.1"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-alibaba",
-    "stable-version": "2.0.1",
+    "package-name": "apache-airflow-providers-celery",
+    "stable-version": "3.0.0",
     "all-versions": [
       "1.0.0",
       "1.0.1",
-      "1.1.0",
-      "1.1.1",
       "2.0.0",
-      "2.0.1"
+      "2.1.0",
+      "2.1.1",
+      "2.1.2",
+      "2.1.3",
+      "2.1.4",
+      "3.0.0"
     ]
   },
   {
-    "package-name": "apache-airflow-providers-salesforce",
-    "stable-version": "5.0.0",
+    "package-name": "apache-airflow-providers-github",
+    "stable-version": "2.1.0",
     "all-versions": [
       "1.0.0",
       "1.0.1",
+      "1.0.2",
+      "1.0.3",
       "2.0.0",
-      "3.0.0",
-      "3.1.0",
-      "3.2.0",
-      "3.3.0",
-      "3.4.0",
-      "3.4.1",
-      "3.4.2",
-      "3.4.3",
-      "3.4.4",
-      "4.0.0",
-      "5.0.0"
+      "2.1.0"
     ]
   }
 ]
\ No newline at end of file
diff --git a/blog/airflow-1.10.10/index.html b/blog/airflow-1.10.10/index.html
index a3477ceb92..1367178114 100644
--- a/blog/airflow-1.10.10/index.html
+++ b/blog/airflow-1.10.10/index.html
@@ -34,11 +34,11 @@
 <meta property="og:type" content="article" />
 <meta property="og:url" content="/blog/airflow-1.10.10/" /><meta property="og:image" content="/images/feature-image.png"/><meta property="article:section" content="blog" />
 <meta property="article:published_time" content="2020-04-09T00:00:00+00:00" />
-<meta property="article:modified_time" content="2022-07-18T12:13:19+02:00" /><meta property="og:site_name" content="Apache Airflow" />
+<meta property="article:modified_time" content="2022-07-20T15:07:14+02:00" /><meta property="og:site_name" content="Apache Airflow" />
 
 <meta itemprop="name" content="Apache Airflow 1.10.10">
 <meta itemprop="description" content="We are happy to present Apache Airflow 1.10.10"><meta itemprop="datePublished" content="2020-04-09T00:00:00+00:00" />
-<meta itemprop="dateModified" content="2022-07-18T12:13:19+02:00" />
+<meta itemprop="dateModified" content="2022-07-20T15:07:14+02:00" />
 <meta itemprop="wordCount" content="1143"><meta itemprop="image" content="/images/feature-image.png"/>
 <meta itemprop="keywords" content="release," /><meta name="twitter:card" content="summary_large_image"/>
 <meta name="twitter:image" content="/images/feature-image.png"/>
diff --git a/blog/airflow-1.10.12/index.html b/blog/airflow-1.10.12/index.html
index f4a9cd92fc..68d44d0b09 100644
--- a/blog/airflow-1.10.12/index.html
+++ b/blog/airflow-1.10.12/index.html
@@ -34,11 +34,11 @@
 <meta property="og:type" content="article" />
 <meta property="og:url" content="/blog/airflow-1.10.12/" /><meta property="og:image" content="/images/feature-image.png"/><meta property="article:section" content="blog" />
 <meta property="article:published_time" content="2020-08-25T00:00:00+00:00" />
-<meta property="article:modified_time" content="2022-07-18T12:13:19+02:00" /><meta property="og:site_name" content="Apache Airflow" />
+<meta property="article:modified_time" content="2022-07-20T15:07:14+02:00" /><meta property="og:site_name" content="Apache Airflow" />
 
 <meta itemprop="name" content="Apache Airflow 1.10.12">
 <meta itemprop="description" content="We are happy to present Apache Airflow 1.10.12"><meta itemprop="datePublished" content="2020-08-25T00:00:00+00:00" />
-<meta itemprop="dateModified" content="2022-07-18T12:13:19+02:00" />
+<meta itemprop="dateModified" content="2022-07-20T15:07:14+02:00" />
 <meta itemprop="wordCount" content="911"><meta itemprop="image" content="/images/feature-image.png"/>
 <meta itemprop="keywords" content="release," /><meta name="twitter:card" content="summary_large_image"/>
 <meta name="twitter:image" content="/images/feature-image.png"/>
diff --git a/blog/airflow-1.10.8-1.10.9/index.html b/blog/airflow-1.10.8-1.10.9/index.html
index b3d40c72e8..23878697a4 100644
--- a/blog/airflow-1.10.8-1.10.9/index.html
+++ b/blog/airflow-1.10.8-1.10.9/index.html
@@ -34,11 +34,11 @@
 <meta property="og:type" content="article" />
 <meta property="og:url" content="/blog/airflow-1.10.8-1.10.9/" /><meta property="og:image" content="/images/feature-image.png"/><meta property="article:section" content="blog" />
 <meta property="article:published_time" content="2020-02-23T00:00:00+00:00" />
-<meta property="article:modified_time" content="2022-07-18T12:13:19+02:00" /><meta property="og:site_name" content="Apache Airflow" />
+<meta property="article:modified_time" content="2022-07-20T15:07:14+02:00" /><meta property="og:site_name" content="Apache Airflow" />
 
 <meta itemprop="name" content="Apache Airflow 1.10.8 &amp; 1.10.9">
 <meta itemprop="description" content="We are happy to present the new 1.10.8 and 1.10.9 releases of Apache Airflow."><meta itemprop="datePublished" content="2020-02-23T00:00:00+00:00" />
-<meta itemprop="dateModified" content="2022-07-18T12:13:19+02:00" />
+<meta itemprop="dateModified" content="2022-07-20T15:07:14+02:00" />
 <meta itemprop="wordCount" content="437"><meta itemprop="image" content="/images/feature-image.png"/>
 <meta itemprop="keywords" content="release," /><meta name="twitter:card" content="summary_large_image"/>
 <meta name="twitter:image" content="/images/feature-image.png"/>
diff --git a/blog/airflow-2.2.0/index.html b/blog/airflow-2.2.0/index.html
index ce5ae33321..d86202c291 100644
--- a/blog/airflow-2.2.0/index.html
+++ b/blog/airflow-2.2.0/index.html
@@ -34,11 +34,11 @@
 <meta property="og:type" content="article" />
 <meta property="og:url" content="/blog/airflow-2.2.0/" /><meta property="og:image" content="/images/feature-image.png"/><meta property="article:section" content="blog" />
 <meta property="article:published_time" content="2021-10-11T00:00:00+00:00" />
-<meta property="article:modified_time" content="2022-07-18T12:13:19+02:00" /><meta property="og:site_name" content="Apache Airflow" />
+<meta property="article:modified_time" content="2022-07-20T15:07:14+02:00" /><meta property="og:site_name" content="Apache Airflow" />
 
 <meta itemprop="name" content="What&#39;s new in Apache Airflow 2.2.0">
 <meta itemprop="description" content="We&#39;re proud to announce that Apache Airflow 2.2.0 has been released."><meta itemprop="datePublished" content="2021-10-11T00:00:00+00:00" />
-<meta itemprop="dateModified" content="2022-07-18T12:13:19+02:00" />
+<meta itemprop="dateModified" content="2022-07-20T15:07:14+02:00" />
 <meta itemprop="wordCount" content="658"><meta itemprop="image" content="/images/feature-image.png"/>
 <meta itemprop="keywords" content="Release," /><meta name="twitter:card" content="summary_large_image"/>
 <meta name="twitter:image" content="/images/feature-image.png"/>
diff --git a/blog/airflow-2.3.0/index.html b/blog/airflow-2.3.0/index.html
index 1076822dac..9b048dc940 100644
--- a/blog/airflow-2.3.0/index.html
+++ b/blog/airflow-2.3.0/index.html
@@ -34,11 +34,11 @@
 <meta property="og:type" content="article" />
 <meta property="og:url" content="/blog/airflow-2.3.0/" /><meta property="og:image" content="/images/feature-image.png"/><meta property="article:section" content="blog" />
 <meta property="article:published_time" content="2022-04-30T00:00:00+00:00" />
-<meta property="article:modified_time" content="2022-07-18T12:13:19+02:00" /><meta property="og:site_name" content="Apache Airflow" />
+<meta property="article:modified_time" content="2022-07-20T15:07:14+02:00" /><meta property="og:site_name" content="Apache Airflow" />
 
 <meta itemprop="name" content="Apache Airflow 2.3.0 is here">
 <meta itemprop="description" content="We&#39;re proud to announce that Apache Airflow 2.3.0 has been released."><meta itemprop="datePublished" content="2022-04-30T00:00:00+00:00" />
-<meta itemprop="dateModified" content="2022-07-18T12:13:19+02:00" />
+<meta itemprop="dateModified" content="2022-07-20T15:07:14+02:00" />
 <meta itemprop="wordCount" content="708"><meta itemprop="image" content="/images/feature-image.png"/>
 <meta itemprop="keywords" content="Release," /><meta name="twitter:card" content="summary_large_image"/>
 <meta name="twitter:image" content="/images/feature-image.png"/>
diff --git a/blog/airflow-survey-2020/index.html b/blog/airflow-survey-2020/index.html
index 6db9e12c0e..548d5b15da 100644
--- a/blog/airflow-survey-2020/index.html
+++ b/blog/airflow-survey-2020/index.html
@@ -34,11 +34,11 @@
 <meta property="og:type" content="article" />
 <meta property="og:url" content="/blog/airflow-survey-2020/" /><meta property="og:image" content="/images/feature-image.png"/><meta property="article:section" content="blog" />
 <meta property="article:published_time" content="2021-03-09T00:00:00+00:00" />
-<meta property="article:modified_time" content="2022-07-18T12:13:19+02:00" /><meta property="og:site_name" content="Apache Airflow" />
+<meta property="article:modified_time" content="2022-07-20T15:07:14+02:00" /><meta property="og:site_name" content="Apache Airflow" />
 
 <meta itemprop="name" content="Airflow Survey 2020">
 <meta itemprop="description" content="We observe steady growth in number of users as well as in an amount of active contributors. So listening and understanding our community is of high importance."><meta itemprop="datePublished" content="2021-03-09T00:00:00+00:00" />
-<meta itemprop="dateModified" content="2022-07-18T12:13:19+02:00" />
+<meta itemprop="dateModified" content="2022-07-20T15:07:14+02:00" />
 <meta itemprop="wordCount" content="2136"><meta itemprop="image" content="/images/feature-image.png"/>
 <meta itemprop="keywords" content="community,survey,users," /><meta name="twitter:card" content="summary_large_image"/>
 <meta name="twitter:image" content="/images/feature-image.png"/>
diff --git a/blog/airflow-survey-2022/index.html b/blog/airflow-survey-2022/index.html
index bae8653c98..fc4cdd70c3 100644
--- a/blog/airflow-survey-2022/index.html
+++ b/blog/airflow-survey-2022/index.html
@@ -34,11 +34,11 @@
 <meta property="og:type" content="article" />
 <meta property="og:url" content="/blog/airflow-survey-2022/" /><meta property="og:image" content="/images/feature-image.png"/><meta property="article:section" content="blog" />
 <meta property="article:published_time" content="2022-06-17T00:00:00+00:00" />
-<meta property="article:modified_time" content="2022-07-18T12:13:19+02:00" /><meta property="og:site_name" content="Apache Airflow" />
+<meta property="article:modified_time" content="2022-07-20T15:07:14+02:00" /><meta property="og:site_name" content="Apache Airflow" />
 
 <meta itemprop="name" content="Airflow Survey 2022">
 <meta itemprop="description" content="2021 saw rapid adoption of Airflow 2, and continued growth of the community. This annual survey helps us understand how people are using Airflow, and where we can best focus our efforts going forward."><meta itemprop="datePublished" content="2022-06-17T00:00:00+00:00" />
-<meta itemprop="dateModified" content="2022-07-18T12:13:19+02:00" />
+<meta itemprop="dateModified" content="2022-07-20T15:07:14+02:00" />
 <meta itemprop="wordCount" content="3865"><meta itemprop="image" content="/images/feature-image.png"/>
 <meta itemprop="keywords" content="community,survey,users," /><meta name="twitter:card" content="summary_large_image"/>
 <meta name="twitter:image" content="/images/feature-image.png"/>
diff --git a/blog/airflow-survey/index.html b/blog/airflow-survey/index.html
index c0ca5acde9..e82c3e920e 100644
--- a/blog/airflow-survey/index.html
+++ b/blog/airflow-survey/index.html
@@ -34,11 +34,11 @@
 <meta property="og:type" content="article" />
 <meta property="og:url" content="/blog/airflow-survey/" /><meta property="og:image" content="/images/feature-image.png"/><meta property="article:section" content="blog" />
 <meta property="article:published_time" content="2019-12-11T00:00:00+00:00" />
-<meta property="article:modified_time" content="2022-07-18T12:13:19+02:00" /><meta property="og:site_name" content="Apache Airflow" />
+<meta property="article:modified_time" content="2022-07-20T15:07:14+02:00" /><meta property="og:site_name" content="Apache Airflow" />
 
 <meta itemprop="name" content="Airflow Survey 2019">
 <meta itemprop="description" content="Receiving and adjusting to our users’ feedback is a must. Let’s see who Airflow users are, how they play with it, and what they miss."><meta itemprop="datePublished" content="2019-12-11T00:00:00+00:00" />
-<meta itemprop="dateModified" content="2022-07-18T12:13:19+02:00" />
+<meta itemprop="dateModified" content="2022-07-20T15:07:14+02:00" />
 <meta itemprop="wordCount" content="1775"><meta itemprop="image" content="/images/feature-image.png"/>
 <meta itemprop="keywords" content="community,survey,users," /><meta name="twitter:card" content="summary_large_image"/>
 <meta name="twitter:image" content="/images/feature-image.png"/>
diff --git a/blog/airflow-two-point-oh-is-here/index.html b/blog/airflow-two-point-oh-is-here/index.html
index d0f5fb5525..9711f08d98 100644
--- a/blog/airflow-two-point-oh-is-here/index.html
+++ b/blog/airflow-two-point-oh-is-here/index.html
@@ -34,11 +34,11 @@
 <meta property="og:type" content="article" />
 <meta property="og:url" content="/blog/airflow-two-point-oh-is-here/" /><meta property="og:image" content="/images/feature-image.png"/><meta property="article:section" content="blog" />
 <meta property="article:published_time" content="2020-12-17T00:00:00+00:00" />
-<meta property="article:modified_time" content="2022-07-18T12:13:19+02:00" /><meta property="og:site_name" content="Apache Airflow" />
+<meta property="article:modified_time" content="2022-07-20T15:07:14+02:00" /><meta property="og:site_name" content="Apache Airflow" />
 
 <meta itemprop="name" content="Apache Airflow 2.0 is here!">
 <meta itemprop="description" content="We&#39;re proud to announce that Apache Airflow 2.0.0 has been released."><meta itemprop="datePublished" content="2020-12-17T00:00:00+00:00" />
-<meta itemprop="dateModified" content="2022-07-18T12:13:19+02:00" />
+<meta itemprop="dateModified" content="2022-07-20T15:07:14+02:00" />
 <meta itemprop="wordCount" content="1165"><meta itemprop="image" content="/images/feature-image.png"/>
 <meta itemprop="keywords" content="Release," /><meta name="twitter:card" content="summary_large_image"/>
 <meta name="twitter:image" content="/images/feature-image.png"/>
diff --git a/blog/airflow_summit_2021/index.html b/blog/airflow_summit_2021/index.html
index eeb1df5fa2..f4e568cbab 100644
--- a/blog/airflow_summit_2021/index.html
+++ b/blog/airflow_summit_2021/index.html
@@ -34,11 +34,11 @@
 <meta property="og:type" content="article" />
 <meta property="og:url" content="/blog/airflow_summit_2021/" /><meta property="og:image" content="/images/feature-image.png"/><meta property="article:section" content="blog" />
 <meta property="article:published_time" content="2021-03-21T00:00:00+00:00" />
-<meta property="article:modified_time" content="2022-07-18T12:13:19+02:00" /><meta property="og:site_name" content="Apache Airflow" />
+<meta property="article:modified_time" content="2022-07-20T15:07:14+02:00" /><meta property="og:site_name" content="Apache Airflow" />
 
 <meta itemprop="name" content="Airflow Summit 2021">
 <meta itemprop="description" content="We are thrilled about Airflow Summit 2021!"><meta itemprop="datePublished" content="2021-03-21T00:00:00+00:00" />
-<meta itemprop="dateModified" content="2022-07-18T12:13:19+02:00" />
+<meta itemprop="dateModified" content="2022-07-20T15:07:14+02:00" />
 <meta itemprop="wordCount" content="77"><meta itemprop="image" content="/images/feature-image.png"/>
 <meta itemprop="keywords" content="Community,Airflow Summit," /><meta name="twitter:card" content="summary_large_image"/>
 <meta name="twitter:image" content="/images/feature-image.png"/>
diff --git a/blog/airflow_summit_2022/index.html b/blog/airflow_summit_2022/index.html
index cf1d4741b9..776738dd06 100644
--- a/blog/airflow_summit_2022/index.html
+++ b/blog/airflow_summit_2022/index.html
@@ -34,11 +34,11 @@
 <meta property="og:type" content="article" />
 <meta property="og:url" content="/blog/airflow_summit_2022/" /><meta property="og:image" content="/images/feature-image.png"/><meta property="article:section" content="blog" />
 <meta property="article:published_time" content="2022-05-16T00:00:00+00:00" />
-<meta property="article:modified_time" content="2022-07-18T12:13:19+02:00" /><meta property="og:site_name" content="Apache Airflow" />
+<meta property="article:modified_time" content="2022-07-20T15:07:14+02:00" /><meta property="og:site_name" content="Apache Airflow" />
 
 <meta itemprop="name" content="Airflow Summit 2022">
 <meta itemprop="description" content="Airflow Summit 2022 is here"><meta itemprop="datePublished" content="2022-05-16T00:00:00+00:00" />
-<meta itemprop="dateModified" content="2022-07-18T12:13:19+02:00" />
+<meta itemprop="dateModified" content="2022-07-20T15:07:14+02:00" />
 <meta itemprop="wordCount" content="129"><meta itemprop="image" content="/images/feature-image.png"/>
 <meta itemprop="keywords" content="Community,Airflow Summit," /><meta name="twitter:card" content="summary_large_image"/>
 <meta name="twitter:image" content="/images/feature-image.png"/>
diff --git a/blog/announcing-new-website/index.html b/blog/announcing-new-website/index.html
index 889394f5fb..3728269643 100644
--- a/blog/announcing-new-website/index.html
+++ b/blog/announcing-new-website/index.html
@@ -34,11 +34,11 @@
 <meta property="og:type" content="article" />
 <meta property="og:url" content="/blog/announcing-new-website/" /><meta property="og:image" content="/images/feature-image.png"/><meta property="article:section" content="blog" />
 <meta property="article:published_time" content="2019-12-11T00:00:00+00:00" />
-<meta property="article:modified_time" content="2022-07-18T12:13:19+02:00" /><meta property="og:site_name" content="Apache Airflow" />
+<meta property="article:modified_time" content="2022-07-20T15:07:14+02:00" /><meta property="og:site_name" content="Apache Airflow" />
 
 <meta itemprop="name" content="New Airflow website">
 <meta itemprop="description" content="We are thrilled about our new website!"><meta itemprop="datePublished" content="2019-12-11T00:00:00+00:00" />
-<meta itemprop="dateModified" content="2022-07-18T12:13:19+02:00" />
+<meta itemprop="dateModified" content="2022-07-20T15:07:14+02:00" />
 <meta itemprop="wordCount" content="282"><meta itemprop="image" content="/images/feature-image.png"/>
 <meta itemprop="keywords" content="Community," /><meta name="twitter:card" content="summary_large_image"/>
 <meta name="twitter:image" content="/images/feature-image.png"/>
diff --git a/blog/apache-airflow-for-newcomers/index.html b/blog/apache-airflow-for-newcomers/index.html
index 755511afd7..1866b75b3a 100644
--- a/blog/apache-airflow-for-newcomers/index.html
+++ b/blog/apache-airflow-for-newcomers/index.html
@@ -35,12 +35,12 @@ Authoring Workflow in Apache Airflow. Airflow makes it easy to author workflows
 <meta property="og:type" content="article" />
 <meta property="og:url" content="/blog/apache-airflow-for-newcomers/" /><meta property="og:image" content="/images/feature-image.png"/><meta property="article:section" content="blog" />
 <meta property="article:published_time" content="2020-08-17T00:00:00+00:00" />
-<meta property="article:modified_time" content="2022-07-18T12:13:19+02:00" /><meta property="og:site_name" content="Apache Airflow" />
+<meta property="article:modified_time" content="2022-07-20T15:07:14+02:00" /><meta property="og:site_name" content="Apache Airflow" />
 
 <meta itemprop="name" content="Apache Airflow For Newcomers">
 <meta itemprop="description" content="Apache Airflow is a platform to programmatically author, schedule, and monitor workflows. A workflow is a sequence of tasks that processes a set of data. You can think of workflow as the path that describes how tasks go from being undone to done. Scheduling, on the other hand, is the process of planning, controlling, and optimizing when a particular task should be done.
 Authoring Workflow in Apache Airflow. Airflow makes it easy to author workflows using python scripts."><meta itemprop="datePublished" content="2020-08-17T00:00:00+00:00" />
-<meta itemprop="dateModified" content="2022-07-18T12:13:19+02:00" />
+<meta itemprop="dateModified" content="2022-07-20T15:07:14+02:00" />
 <meta itemprop="wordCount" content="1070"><meta itemprop="image" content="/images/feature-image.png"/>
 <meta itemprop="keywords" content="Community," /><meta name="twitter:card" content="summary_large_image"/>
 <meta name="twitter:image" content="/images/feature-image.png"/>
diff --git a/blog/apache-con-europe-2019-thoughts-and-insights-by-airflow-committers/index.html b/blog/apache-con-europe-2019-thoughts-and-insights-by-airflow-committers/index.html
index fdc25af161..74dcc3091c 100644
--- a/blog/apache-con-europe-2019-thoughts-and-insights-by-airflow-committers/index.html
+++ b/blog/apache-con-europe-2019-thoughts-and-insights-by-airflow-committers/index.html
@@ -34,11 +34,11 @@
 <meta property="og:type" content="article" />
 <meta property="og:url" content="/blog/apache-con-europe-2019-thoughts-and-insights-by-airflow-committers/" /><meta property="og:image" content="/images/feature-image.png"/><meta property="article:section" content="blog" />
 <meta property="article:published_time" content="2019-11-22T00:00:00+00:00" />
-<meta property="article:modified_time" content="2022-07-18T12:13:19+02:00" /><meta property="og:site_name" content="Apache Airflow" />
+<meta property="article:modified_time" content="2022-07-20T15:07:14+02:00" /><meta property="og:site_name" content="Apache Airflow" />
 
 <meta itemprop="name" content="ApacheCon Europe 2019 β€” Thoughts and Insights by Airflow Committers">
 <meta itemprop="description" content="Here come some thoughts by Airflow committers and contributors from the ApacheCon Europe 2019. Get to know the ASF community!"><meta itemprop="datePublished" content="2019-11-22T00:00:00+00:00" />
-<meta itemprop="dateModified" content="2022-07-18T12:13:19+02:00" />
+<meta itemprop="dateModified" content="2022-07-20T15:07:14+02:00" />
 <meta itemprop="wordCount" content="138"><meta itemprop="image" content="/images/feature-image.png"/>
 <meta itemprop="keywords" content="Community," /><meta name="twitter:card" content="summary_large_image"/>
 <meta name="twitter:image" content="/images/feature-image.png"/>
diff --git a/blog/documenting-using-local-development-environments/index.html b/blog/documenting-using-local-development-environments/index.html
index 3e43b14e58..d08bf29840 100644
--- a/blog/documenting-using-local-development-environments/index.html
+++ b/blog/documenting-using-local-development-environments/index.html
@@ -34,11 +34,11 @@
 <meta property="og:type" content="article" />
 <meta property="og:url" content="/blog/documenting-using-local-development-environments/" /><meta property="og:image" content="/images/feature-image.png"/><meta property="article:section" content="blog" />
 <meta property="article:published_time" content="2019-11-22T00:00:00+00:00" />
-<meta property="article:modified_time" content="2022-07-18T12:13:19+02:00" /><meta property="og:site_name" content="Apache Airflow" />
+<meta property="article:modified_time" content="2022-07-20T15:07:14+02:00" /><meta property="og:site_name" content="Apache Airflow" />
 
 <meta itemprop="name" content="Documenting using local development environment">
 <meta itemprop="description" content="The story behind documenting local development environment of Apache Airflow"><meta itemprop="datePublished" content="2019-11-22T00:00:00+00:00" />
-<meta itemprop="dateModified" content="2022-07-18T12:13:19+02:00" />
+<meta itemprop="dateModified" content="2022-07-20T15:07:14+02:00" />
 <meta itemprop="wordCount" content="256"><meta itemprop="image" content="/images/feature-image.png"/>
 <meta itemprop="keywords" content="Development," /><meta name="twitter:card" content="summary_large_image"/>
 <meta name="twitter:image" content="/images/feature-image.png"/>
diff --git a/blog/experience-in-google-season-of-docs-2019-with-apache-airflow/index.html b/blog/experience-in-google-season-of-docs-2019-with-apache-airflow/index.html
index 67ecf72e07..7223797032 100644
--- a/blog/experience-in-google-season-of-docs-2019-with-apache-airflow/index.html
+++ b/blog/experience-in-google-season-of-docs-2019-with-apache-airflow/index.html
@@ -35,12 +35,12 @@ About Me I have been writing tech articles on medium as well as my blog for the
 <meta property="og:type" content="article" />
 <meta property="og:url" content="/blog/experience-in-google-season-of-docs-2019-with-apache-airflow/" /><meta property="og:image" content="/images/feature-image.png"/><meta property="article:section" content="blog" />
 <meta property="article:published_time" content="2019-12-20T00:00:00+00:00" />
-<meta property="article:modified_time" content="2022-07-18T12:13:19+02:00" /><meta property="og:site_name" content="Apache Airflow" />
+<meta property="article:modified_time" content="2022-07-20T15:07:14+02:00" /><meta property="og:site_name" content="Apache Airflow" />
 
 <meta itemprop="name" content="Experience in Google Season of Docs 2019 with Apache Airflow">
 <meta itemprop="description" content="I came across Google Season of Docs (GSoD) almost by accident, thanks to my extensive HackerNews and Twitter addiction. I was familiar with the Google Summer of Code but not with this program. It turns out it was the inaugural phase. I read the details, and the process felt a lot like GSoC except that this was about documentation.
 About Me I have been writing tech articles on medium as well as my blog for the past 1."><meta itemprop="datePublished" content="2019-12-20T00:00:00+00:00" />
-<meta itemprop="dateModified" content="2022-07-18T12:13:19+02:00" />
+<meta itemprop="dateModified" content="2022-07-20T15:07:14+02:00" />
 <meta itemprop="wordCount" content="1521"><meta itemprop="image" content="/images/feature-image.png"/>
 <meta itemprop="keywords" content="Documentation," /><meta name="twitter:card" content="summary_large_image"/>
 <meta name="twitter:image" content="/images/feature-image.png"/>
diff --git a/blog/experience-with-airflow-as-an-outreachy-intern/index.html b/blog/experience-with-airflow-as-an-outreachy-intern/index.html
index ccf81158a8..834b27a285 100644
--- a/blog/experience-with-airflow-as-an-outreachy-intern/index.html
+++ b/blog/experience-with-airflow-as-an-outreachy-intern/index.html
@@ -35,12 +35,12 @@ Contribution Period The first thing I had to do was choose a project under an or
 <meta property="og:type" content="article" />
 <meta property="og:url" content="/blog/experience-with-airflow-as-an-outreachy-intern/" /><meta property="og:image" content="/images/feature-image.png"/><meta property="article:section" content="blog" />
 <meta property="article:published_time" content="2020-08-30T00:00:00+00:00" />
-<meta property="article:modified_time" content="2022-07-18T12:13:19+02:00" /><meta property="og:site_name" content="Apache Airflow" />
+<meta property="article:modified_time" content="2022-07-20T15:07:14+02:00" /><meta property="og:site_name" content="Apache Airflow" />
 
 <meta itemprop="name" content="Journey with Airflow as an Outreachy Intern">
 <meta itemprop="description" content="Outreachy is a program which organises three months paid internships with FOSS projects for people who are typically underrepresented in those projects.
 Contribution Period The first thing I had to do was choose a project under an organisation. After going through all the projects I chose β€œExtending the REST API of Apache Airflow”, because I had a good idea of what REST API(s) are, so I thought it would be easier to get started with the contributions."><meta itemprop="datePublished" content="2020-08-30T00:00:00+00:00" />
-<meta itemprop="dateModified" content="2022-07-18T12:13:19+02:00" />
+<meta itemprop="dateModified" content="2022-07-20T15:07:14+02:00" />
 <meta itemprop="wordCount" content="528"><meta itemprop="image" content="/images/feature-image.png"/>
 <meta itemprop="keywords" content="Community," /><meta name="twitter:card" content="summary_large_image"/>
 <meta name="twitter:image" content="/images/feature-image.png"/>
diff --git a/blog/implementing-stable-api-for-apache-airflow/index.html b/blog/implementing-stable-api-for-apache-airflow/index.html
index 159d9fbbb4..bba36af98f 100644
--- a/blog/implementing-stable-api-for-apache-airflow/index.html
+++ b/blog/implementing-stable-api-for-apache-airflow/index.html
@@ -34,11 +34,11 @@
 <meta property="og:type" content="article" />
 <meta property="og:url" content="/blog/implementing-stable-api-for-apache-airflow/" /><meta property="og:image" content="/images/feature-image.png"/><meta property="article:section" content="blog" />
 <meta property="article:published_time" content="2020-07-19T00:00:00+00:00" />
-<meta property="article:modified_time" content="2022-07-18T12:13:19+02:00" /><meta property="og:site_name" content="Apache Airflow" />
+<meta property="article:modified_time" content="2022-07-20T15:07:14+02:00" /><meta property="og:site_name" content="Apache Airflow" />
 
 <meta itemprop="name" content="Implementing Stable API for Apache Airflow">
 <meta itemprop="description" content="An Outreachy intern&#39;s progress report on contributing to Apache Airflow REST API."><meta itemprop="datePublished" content="2020-07-19T00:00:00+00:00" />
-<meta itemprop="dateModified" content="2022-07-18T12:13:19+02:00" />
+<meta itemprop="dateModified" content="2022-07-20T15:07:14+02:00" />
 <meta itemprop="wordCount" content="703"><meta itemprop="image" content="/images/feature-image.png"/>
 <meta itemprop="keywords" content="REST API," /><meta name="twitter:card" content="summary_large_image"/>
 <meta name="twitter:image" content="/images/feature-image.png"/>
diff --git a/blog/its-a-breeze-to-develop-apache-airflow/index.html b/blog/its-a-breeze-to-develop-apache-airflow/index.html
index 25efb3caea..f39fe2b7ea 100644
--- a/blog/its-a-breeze-to-develop-apache-airflow/index.html
+++ b/blog/its-a-breeze-to-develop-apache-airflow/index.html
@@ -34,11 +34,11 @@
 <meta property="og:type" content="article" />
 <meta property="og:url" content="/blog/its-a-breeze-to-develop-apache-airflow/" /><meta property="og:image" content="/images/feature-image.png"/><meta property="article:section" content="blog" />
 <meta property="article:published_time" content="2019-11-22T00:00:00+00:00" />
-<meta property="article:modified_time" content="2022-07-18T12:13:19+02:00" /><meta property="og:site_name" content="Apache Airflow" />
+<meta property="article:modified_time" content="2022-07-20T15:07:14+02:00" /><meta property="og:site_name" content="Apache Airflow" />
 
 <meta itemprop="name" content="It&#39;s a &#34;Breeze&#34; to develop Apache Airflow">
 <meta itemprop="description" content="A Principal Software Engineer&#39;s journey to developer productivity. Learn how Jarek and his team sped up and simplified Airflow development for the community."><meta itemprop="datePublished" content="2019-11-22T00:00:00+00:00" />
-<meta itemprop="dateModified" content="2022-07-18T12:13:19+02:00" />
+<meta itemprop="dateModified" content="2022-07-20T15:07:14+02:00" />
 <meta itemprop="wordCount" content="124"><meta itemprop="image" content="/images/feature-image.png"/>
 <meta itemprop="keywords" content="Development," /><meta name="twitter:card" content="summary_large_image"/>
 <meta name="twitter:image" content="/images/feature-image.png"/>
diff --git a/docs/apache-airflow-providers-sftp/4.0.0/.buildinfo b/docs/apache-airflow-providers-sftp/4.0.0/.buildinfo
new file mode 100644
index 0000000000..ec258f35f0
--- /dev/null
+++ b/docs/apache-airflow-providers-sftp/4.0.0/.buildinfo
@@ -0,0 +1,4 @@
+# Sphinx build info version 1
+# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
+config: a5f359f6e2aa121c1f22b91c725278e8
+tags: 645f666f9bcd5a90fca523b33c5a78b7
diff --git a/docs/apache-airflow-providers-sftp/stable/_api/airflow/providers/sftp/hooks/index.html b/docs/apache-airflow-providers-sftp/4.0.0/_api/airflow/providers/sftp/hooks/index.html
similarity index 99%
copy from docs/apache-airflow-providers-sftp/stable/_api/airflow/providers/sftp/hooks/index.html
copy to docs/apache-airflow-providers-sftp/4.0.0/_api/airflow/providers/sftp/hooks/index.html
index 21ed6c9edf..95ef447b48 100644
--- a/docs/apache-airflow-providers-sftp/stable/_api/airflow/providers/sftp/hooks/index.html
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_api/airflow/providers/sftp/hooks/index.html
@@ -5,7 +5,7 @@
 <!DOCTYPE html>
 <!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
 <!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
-    <html xmlns="http://www.w3.org/1999/xhtml">
+    <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
 <head>
         <meta charset="utf-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1">
@@ -284,7 +284,7 @@
 <div id="docs-version-selector" class="docs-version-selector sidebar__version-selector">
     <a class="dropdown-toggle" href="#" id="versionDropdown" role="button" data-toggle="dropdown" aria-haspopup="true"
        aria-expanded="false">
-        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">3.0.0</span>
+        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">4.0.0</span>
     </a>
     <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
 
@@ -421,7 +421,7 @@
 <div id="docs-version-selector" class="docs-version-selector sidebar__version-selector">
     <a class="dropdown-toggle" href="#" id="versionDropdown" role="button" data-toggle="dropdown" aria-haspopup="true"
        aria-expanded="false">
-        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">3.0.0</span>
+        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">4.0.0</span>
     </a>
     <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
 
@@ -579,9 +579,9 @@
                                     <div class="body" role="main">
                                         
   <div class="section" id="module-airflow.providers.sftp.hooks">
-<span id="airflow-providers-sftp-hooks"></span><h1><a class="reference internal" href="#module-airflow.providers.sftp.hooks" title="airflow.providers.sftp.hooks"><code class="xref py py-mod docutils literal notranslate"><span class="pre">airflow.providers.sftp.hooks</span></code></a><a class="headerlink" href="#module-airflow.providers.sftp.hooks" title="Permalink to this headline">ΒΆ</a></h1>
+<span id="airflow-providers-sftp-hooks"></span><h1><a class="reference internal" href="#module-airflow.providers.sftp.hooks" title="airflow.providers.sftp.hooks"><code class="xref py py-mod docutils literal notranslate"><span class="pre">airflow.providers.sftp.hooks</span></code></a><a class="headerlink" href="#module-airflow.providers.sftp.hooks" title="Permalink to this heading">ΒΆ</a></h1>
 <div class="section" id="submodules">
-<h2>Submodules<a class="headerlink" href="#submodules" title="Permalink to this headline">ΒΆ</a></h2>
+<h2>Submodules<a class="headerlink" href="#submodules" title="Permalink to this heading">ΒΆ</a></h2>
 <div class="toctree-wrapper compound">
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="sftp/index.html"><code class="xref py py-mod docutils literal notranslate"><span class="pre">airflow.providers.sftp.hooks.sftp</span></code></a></li>
@@ -833,6 +833,7 @@
         <script data-url_root="../../../../../" id="documentation_options" src="../../../../../_static/documentation_options.js"></script>
         <script src="../../../../../_static/jquery.js"></script>
         <script src="../../../../../_static/underscore.js"></script>
+        <script src="../../../../../_static/_sphinx_javascript_frameworks_compat.js"></script>
         <script src="../../../../../_static/doctools.js"></script>
         <script src="../../../../../_static/clipboard.min.js"></script>
         <script src="../../../../../_static/copybutton.js"></script>
diff --git a/docs/apache-airflow-providers-sftp/stable/_api/airflow/providers/sftp/hooks/sftp/index.html b/docs/apache-airflow-providers-sftp/4.0.0/_api/airflow/providers/sftp/hooks/sftp/index.html
similarity index 90%
copy from docs/apache-airflow-providers-sftp/stable/_api/airflow/providers/sftp/hooks/sftp/index.html
copy to docs/apache-airflow-providers-sftp/4.0.0/_api/airflow/providers/sftp/hooks/sftp/index.html
index 5a0666d52a..6cb3e47c17 100644
--- a/docs/apache-airflow-providers-sftp/stable/_api/airflow/providers/sftp/hooks/sftp/index.html
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_api/airflow/providers/sftp/hooks/sftp/index.html
@@ -5,7 +5,7 @@
 <!DOCTYPE html>
 <!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
 <!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
-    <html xmlns="http://www.w3.org/1999/xhtml">
+    <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
 <head>
         <meta charset="utf-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1">
@@ -284,7 +284,7 @@
 <div id="docs-version-selector" class="docs-version-selector sidebar__version-selector">
     <a class="dropdown-toggle" href="#" id="versionDropdown" role="button" data-toggle="dropdown" aria-haspopup="true"
        aria-expanded="false">
-        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">3.0.0</span>
+        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">4.0.0</span>
     </a>
     <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
 
@@ -421,7 +421,7 @@
 <div id="docs-version-selector" class="docs-version-selector sidebar__version-selector">
     <a class="dropdown-toggle" href="#" id="versionDropdown" role="button" data-toggle="dropdown" aria-haspopup="true"
        aria-expanded="false">
-        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">3.0.0</span>
+        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">4.0.0</span>
     </a>
     <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
 
@@ -581,12 +581,12 @@
                                     <div class="body" role="main">
                                         
   <div class="section" id="module-airflow.providers.sftp.hooks.sftp">
-<span id="airflow-providers-sftp-hooks-sftp"></span><h1><a class="reference internal" href="#module-airflow.providers.sftp.hooks.sftp" title="airflow.providers.sftp.hooks.sftp"><code class="xref py py-mod docutils literal notranslate"><span class="pre">airflow.providers.sftp.hooks.sftp</span></code></a><a class="headerlink" href="#module-airflow.providers.sftp.hooks.sftp" title="Permalink to this headline">ΒΆ</a></h1>
+<span id="airflow-providers-sftp-hooks-sftp"></span><h1><a class="reference internal" href="#module-airflow.providers.sftp.hooks.sftp" title="airflow.providers.sftp.hooks.sftp"><code class="xref py py-mod docutils literal notranslate"><span class="pre">airflow.providers.sftp.hooks.sftp</span></code></a><a class="headerlink" href="#module-airflow.providers.sftp.hooks.sftp" title="Permalink to this heading">ΒΆ</a></h1>
 <p>This module contains SFTP hook.</p>
 <div class="section" id="module-contents">
-<h2>Module Contents<a class="headerlink" href="#module-contents" title="Permalink to this headline">ΒΆ</a></h2>
+<h2>Module Contents<a class="headerlink" href="#module-contents" title="Permalink to this heading">ΒΆ</a></h2>
 <div class="section" id="classes">
-<h3>Classes<a class="headerlink" href="#classes" title="Permalink to this headline">ΒΆ</a></h3>
+<h3>Classes<a class="headerlink" href="#classes" title="Permalink to this heading">ΒΆ</a></h3>
 <table class="autosummary longtable docutils align-default">
 <colgroup>
 <col style="width: 10%" />
@@ -600,8 +600,8 @@
 </table>
 <dl class="py class">
 <dt class="sig sig-object py" id="airflow.providers.sftp.hooks.sftp.SFTPHook">
-<em class="property"><span class="pre">class</span><span class="w"> </span></em><span class="sig-prename descclassname"><span class="pre">airflow.providers.sftp.hooks.sftp.</span></span><span class="sig-name descname"><span class="pre">SFTPHook</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">ssh_conn_id</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">'sftp_default'</span></spa [...]
-<dd><p>Bases: <a class="reference external" href="/docs/apache-airflow-providers-ssh/stable/_api/airflow/providers/ssh/hooks/ssh/index.html#airflow.providers.ssh.hooks.ssh.SSHHook" title="(in apache-airflow-providers-ssh v3.0.0)"><code class="xref py py-obj docutils literal notranslate"><span class="pre">airflow.providers.ssh.hooks.ssh.SSHHook</span></code></a></p>
+<em class="property"><span class="pre">class</span><span class="w"> </span></em><span class="sig-prename descclassname"><span class="pre">airflow.providers.sftp.hooks.sftp.</span></span><span class="sig-name descname"><span class="pre">SFTPHook</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">ssh_conn_id</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">'sftp_default'</span></spa [...]
+<dd><p>Bases: <a class="reference external" href="/docs/apache-airflow-providers-ssh/stable/_api/airflow/providers/ssh/hooks/ssh/index.html#airflow.providers.ssh.hooks.ssh.SSHHook" title="(in apache-airflow-providers-ssh v3.1.0)"><code class="xref py py-obj docutils literal notranslate"><span class="pre">airflow.providers.ssh.hooks.ssh.SSHHook</span></code></a></p>
 <p>This hook is inherited from SSH hook. Please refer to SSH hook for the input
 arguments.</p>
 <p>Interact with SFTP.</p>
@@ -609,7 +609,7 @@ arguments.</p>
 <dt class="field-odd">Pitfalls:</dt>
 <dd class="field-odd"><ul class="simple">
 <li><p>In contrast with FTPHook describe_directory only returns size, type and
-modify. It doesn't return unix.owner, unix.mode, perm, unix.group and
+modify. It doesn’t return unix.owner, unix.mode, perm, unix.group and
 unique.</p></li>
 <li><dl class="simple">
 <dt>retrieve_file and store_file only take a local full path and not a</dt><dd><p>buffer.</p>
@@ -622,14 +622,12 @@ permissions.</p></li>
 </dd>
 </dl>
 <p>Errors that may occur throughout but should be handled downstream.</p>
-<p>For consistency reasons with SSHHook, the preferred parameter is &quot;ssh_conn_id&quot;.
-Please note that it is still possible to use the parameter &quot;ftp_conn_id&quot;
-to initialize the hook, but it will be removed in future Airflow versions.</p>
+<p>For consistency reasons with SSHHook, the preferred parameter is β€œssh_conn_id”.</p>
 <dl class="field-list simple">
 <dt class="field-odd">Parameters</dt>
 <dd class="field-odd"><ul class="simple">
-<li><p><strong>ssh_conn_id</strong> (<em>Optional</em><em>[</em><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a><em>]</em>) -- The <a class="reference internal" href="../../../../../../connections/sftp.html#howto-connection-sftp"><span class="std std-ref">sftp connection id</span></a></p></li>
-<li><p><strong>(</strong><strong>Outdated</strong><strong>)</strong> (<em>ftp_conn_id</em>) -- The <a class="reference internal" href="../../../../../../connections/sftp.html#howto-connection-sftp"><span class="std std-ref">sftp connection id</span></a></p></li>
+<li><p><strong>ssh_conn_id</strong> (<em>Optional</em><em>[</em><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a><em>]</em>) – The <a class="reference internal" href="../../../../../../connections/sftp.html#howto-connection-sftp"><span class="std std-ref">sftp connection id</span></a></p></li>
+<li><p><strong>ssh_hook</strong> (<em>Optional</em><em>[</em><a class="reference external" href="/docs/apache-airflow-providers-ssh/stable/_api/airflow/providers/ssh/hooks/ssh/index.html#airflow.providers.ssh.hooks.ssh.SSHHook" title="(in apache-airflow-providers-ssh v3.1.0)"><em>airflow.providers.ssh.hooks.ssh.SSHHook</em></a><em>]</em>) – Optional SSH hook (included to support passing of an SSH hook to the SFTP operator)</p></li>
 </ul>
 </dd>
 </dl>
@@ -664,15 +662,18 @@ to initialize the hook, but it will be removed in future Airflow versions.</p>
 <dl class="py method">
 <dt class="sig sig-object py" id="airflow.providers.sftp.hooks.sftp.SFTPHook.get_conn">
 <span class="sig-name descname"><span class="pre">get_conn</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">self</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../../../../../../_modules/airflow/providers/sftp/hooks/sftp.html#SFTPHook.get_conn"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#airflow.providers.sftp.hooks.sftp.SFTPHook.get_conn" ti [...]
-<dd><p>Returns an SFTP connection object</p>
+<dd><p>Opens an SFTP connection to the remote host</p>
 <dl class="field-list simple">
+<dt class="field-odd">Return type</dt>
+<dd class="field-odd"><p>paramiko.SFTPClient</p>
+</dd>
 </dl>
 </dd></dl>
 
 <dl class="py method">
 <dt class="sig sig-object py" id="airflow.providers.sftp.hooks.sftp.SFTPHook.close_conn">
 <span class="sig-name descname"><span class="pre">close_conn</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">self</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../../../../../../_modules/airflow/providers/sftp/hooks/sftp.html#SFTPHook.close_conn"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#airflow.providers.sftp.hooks.sftp.SFTPHook.close_co [...]
-<dd><p>Closes the connection</p>
+<dd><p>Closes the SFTP connection</p>
 <dl class="field-list simple">
 </dl>
 </dd></dl>
@@ -684,7 +685,7 @@ to initialize the hook, but it will be removed in future Airflow versions.</p>
 on the remote system (where the MLSD command is supported).</p>
 <dl class="field-list simple">
 <dt class="field-odd">Parameters</dt>
-<dd class="field-odd"><p><strong>path</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a>) -- full path to the remote directory</p>
+<dd class="field-odd"><p><strong>path</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a>) – full path to the remote directory</p>
 </dd>
 </dl>
 </dd></dl>
@@ -695,7 +696,43 @@ on the remote system (where the MLSD command is supported).</p>
 <dd><p>Returns a list of files on the remote system.</p>
 <dl class="field-list simple">
 <dt class="field-odd">Parameters</dt>
-<dd class="field-odd"><p><strong>path</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a>) -- full path to the remote directory to list</p>
+<dd class="field-odd"><p><strong>path</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a>) – full path to the remote directory to list</p>
+</dd>
+</dl>
+</dd></dl>
+
+<dl class="py method">
+<dt class="sig sig-object py" id="airflow.providers.sftp.hooks.sftp.SFTPHook.mkdir">
+<span class="sig-name descname"><span class="pre">mkdir</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">self</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">path</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">mode</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">777</span></span></em><span class="sig-paren">)</span><a cla [...]
+<dd><p>Creates a directory on the remote system.</p>
+<dl class="field-list simple">
+<dt class="field-odd">Parameters</dt>
+<dd class="field-odd"><ul class="simple">
+<li><p><strong>path</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a>) – full path to the remote directory to create</p></li>
+<li><p><strong>mode</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#int" title="(in Python v3.10)"><em>int</em></a>) – permissions to set the directory with</p></li>
+</ul>
+</dd>
+</dl>
+</dd></dl>
+
+<dl class="py method">
+<dt class="sig sig-object py" id="airflow.providers.sftp.hooks.sftp.SFTPHook.isdir">
+<span class="sig-name descname"><span class="pre">isdir</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">self</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">path</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../../../../../../_modules/airflow/providers/sftp/hooks/sftp.html#SFTPHook.isdir"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class= [...]
+<dd><p>Checks if the path provided is a directory or not.</p>
+<dl class="field-list simple">
+<dt class="field-odd">Parameters</dt>
+<dd class="field-odd"><p><strong>path</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a>) – full path to the remote directory to check</p>
+</dd>
+</dl>
+</dd></dl>
+
+<dl class="py method">
+<dt class="sig sig-object py" id="airflow.providers.sftp.hooks.sftp.SFTPHook.isfile">
+<span class="sig-name descname"><span class="pre">isfile</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">self</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">path</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../../../../../../_modules/airflow/providers/sftp/hooks/sftp.html#SFTPHook.isfile"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a clas [...]
+<dd><p>Checks if the path provided is a file or not.</p>
+<dl class="field-list simple">
+<dt class="field-odd">Parameters</dt>
+<dd class="field-odd"><p><strong>path</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a>) – full path to the remote file to check</p>
 </dd>
 </dl>
 </dd></dl>
@@ -707,8 +744,8 @@ on the remote system (where the MLSD command is supported).</p>
 <dl class="field-list simple">
 <dt class="field-odd">Parameters</dt>
 <dd class="field-odd"><ul class="simple">
-<li><p><strong>path</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a>) -- full path to the remote directory to create</p></li>
-<li><p><strong>mode</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#int" title="(in Python v3.10)"><em>int</em></a>) -- int representation of octal mode for directory</p></li>
+<li><p><strong>path</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a>) – full path to the remote directory to create</p></li>
+<li><p><strong>mode</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#int" title="(in Python v3.10)"><em>int</em></a>) – int representation of octal mode for directory</p></li>
 </ul>
 </dd>
 </dl>
@@ -720,7 +757,7 @@ on the remote system (where the MLSD command is supported).</p>
 <dd><p>Deletes a directory on the remote system.</p>
 <dl class="field-list simple">
 <dt class="field-odd">Parameters</dt>
-<dd class="field-odd"><p><strong>path</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a>) -- full path to the remote directory to delete</p>
+<dd class="field-odd"><p><strong>path</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a>) – full path to the remote directory to delete</p>
 </dd>
 </dl>
 </dd></dl>
@@ -734,8 +771,8 @@ at that location</p>
 <dl class="field-list simple">
 <dt class="field-odd">Parameters</dt>
 <dd class="field-odd"><ul class="simple">
-<li><p><strong>remote_full_path</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a>) -- full path to the remote file</p></li>
-<li><p><strong>local_full_path</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a>) -- full path to the local file</p></li>
+<li><p><strong>remote_full_path</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a>) – full path to the remote file</p></li>
+<li><p><strong>local_full_path</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a>) – full path to the local file</p></li>
 </ul>
 </dd>
 </dl>
@@ -743,15 +780,15 @@ at that location</p>
 
 <dl class="py method">
 <dt class="sig sig-object py" id="airflow.providers.sftp.hooks.sftp.SFTPHook.store_file">
-<span class="sig-name descname"><span class="pre">store_file</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">self</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">remote_full_path</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">local_full_path</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="../../../../../../_modules/airflow/providers/sftp/hook [...]
+<span class="sig-name descname"><span class="pre">store_file</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">self</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">remote_full_path</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">local_full_path</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">confirm</span></span><span class="o"><span class="pre">=</span>< [...]
 <dd><p>Transfers a local file to the remote location.
 If local_full_path_or_buffer is a string path, the file will be read
 from that location</p>
 <dl class="field-list simple">
 <dt class="field-odd">Parameters</dt>
 <dd class="field-odd"><ul class="simple">
-<li><p><strong>remote_full_path</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a>) -- full path to the remote file</p></li>
-<li><p><strong>local_full_path</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a>) -- full path to the local file</p></li>
+<li><p><strong>remote_full_path</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a>) – full path to the remote file</p></li>
+<li><p><strong>local_full_path</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a>) – full path to the local file</p></li>
 </ul>
 </dd>
 </dl>
@@ -763,7 +800,7 @@ from that location</p>
 <dd><p>Removes a file on the FTP Server</p>
 <dl class="field-list simple">
 <dt class="field-odd">Parameters</dt>
-<dd class="field-odd"><p><strong>path</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a>) -- full path to the remote file</p>
+<dd class="field-odd"><p><strong>path</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a>) – full path to the remote file</p>
 </dd>
 </dl>
 </dd></dl>
@@ -774,7 +811,7 @@ from that location</p>
 <dd><p>Returns modification time.</p>
 <dl class="field-list simple">
 <dt class="field-odd">Parameters</dt>
-<dd class="field-odd"><p><strong>path</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a>) -- full path to the remote file</p>
+<dd class="field-odd"><p><strong>path</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a>) – full path to the remote file</p>
 </dd>
 </dl>
 </dd></dl>
@@ -785,7 +822,35 @@ from that location</p>
 <dd><p>Returns True if a remote entity exists</p>
 <dl class="field-list simple">
 <dt class="field-odd">Parameters</dt>
-<dd class="field-odd"><p><strong>path</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a>) -- full path to the remote file or directory</p>
+<dd class="field-odd"><p><strong>path</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a>) – full path to the remote file or directory</p>
+</dd>
+</dl>
+</dd></dl>
+
+<dl class="py method">
+<dt class="sig sig-object py" id="airflow.providers.sftp.hooks.sftp.SFTPHook.walktree">
+<span class="sig-name descname"><span class="pre">walktree</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">self</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">path</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">fcallback</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">dcallback</span></span></em>, <em class="sig-param"><span class="n"><span class="pre [...]
+<dd><p>Recursively descend, depth first, the directory tree rooted at
+path, calling discreet callback functions for each regular file,
+directory and unknown file type.</p>
+<dl class="field-list simple">
+<dt class="field-odd">Parameters</dt>
+<dd class="field-odd"><ul class="simple">
+<li><p><strong>path</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a>) – root of remote directory to descend, use β€˜.’ to start at
+<code class="xref py py-attr docutils literal notranslate"><span class="pre">pwd</span></code></p></li>
+<li><p><strong>fcallback</strong> (<em>callable</em>) – callback function to invoke for a regular file.
+(form: <code class="docutils literal notranslate"><span class="pre">func(str)</span></code>)</p></li>
+<li><p><strong>dcallback</strong> (<em>callable</em>) – callback function to invoke for a directory. (form: <code class="docutils literal notranslate"><span class="pre">func(str)</span></code>)</p></li>
+<li><p><strong>ucallback</strong> (<em>callable</em>) – callback function to invoke for an unknown file type.
+(form: <code class="docutils literal notranslate"><span class="pre">func(str)</span></code>)</p></li>
+<li><p><strong>recurse</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#bool" title="(in Python v3.10)"><em>bool</em></a>) – <em>Default: True</em> - should it recurse</p></li>
+</ul>
+</dd>
+<dt class="field-even">Returns</dt>
+<dd class="field-even"><p>None</p>
+</dd>
+<dt class="field-odd">Return type</dt>
+<dd class="field-odd"><p>None</p>
 </dd>
 </dl>
 </dd></dl>
@@ -798,9 +863,9 @@ It is possible to filter results by giving prefix and/or delimiter parameters.</
 <dl class="field-list simple">
 <dt class="field-odd">Parameters</dt>
 <dd class="field-odd"><ul class="simple">
-<li><p><strong>path</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a>) -- path from which tree will be built</p></li>
-<li><p><strong>prefix</strong> (<em>Optional</em><em>[</em><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a><em>]</em>) -- if set paths will be added if start with prefix</p></li>
-<li><p><strong>delimiter</strong> (<em>Optional</em><em>[</em><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a><em>]</em>) -- if set paths will be added if end with delimiter</p></li>
+<li><p><strong>path</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a>) – path from which tree will be built</p></li>
+<li><p><strong>prefix</strong> (<em>Optional</em><em>[</em><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a><em>]</em>) – if set paths will be added if start with prefix</p></li>
+<li><p><strong>delimiter</strong> (<em>Optional</em><em>[</em><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a><em>]</em>) – if set paths will be added if end with delimiter</p></li>
 </ul>
 </dd>
 <dt class="field-even">Returns</dt>
@@ -827,8 +892,8 @@ It is possible to filter results by giving prefix and/or delimiter parameters.</
 <dl class="field-list simple">
 <dt class="field-odd">Parameters</dt>
 <dd class="field-odd"><ul class="simple">
-<li><p><strong>path</strong> -- path to be checked</p></li>
-<li><p><strong>fnmatch_pattern</strong> -- The pattern that will be matched with <cite>fnmatch</cite></p></li>
+<li><p><strong>path</strong> – path to be checked</p></li>
+<li><p><strong>fnmatch_pattern</strong> – The pattern that will be matched with <cite>fnmatch</cite></p></li>
 </ul>
 </dd>
 <dt class="field-even">Returns</dt>
@@ -934,6 +999,9 @@ It is possible to filter results by giving prefix and/or delimiter parameters.</
 <li><a class="reference internal" href="#airflow.providers.sftp.hooks.sftp.SFTPHook.close_conn">close_conn</a></li>
 <li><a class="reference internal" href="#airflow.providers.sftp.hooks.sftp.SFTPHook.describe_directory">describe_directory</a></li>
 <li><a class="reference internal" href="#airflow.providers.sftp.hooks.sftp.SFTPHook.list_directory">list_directory</a></li>
+<li><a class="reference internal" href="#airflow.providers.sftp.hooks.sftp.SFTPHook.mkdir">mkdir</a></li>
+<li><a class="reference internal" href="#airflow.providers.sftp.hooks.sftp.SFTPHook.isdir">isdir</a></li>
+<li><a class="reference internal" href="#airflow.providers.sftp.hooks.sftp.SFTPHook.isfile">isfile</a></li>
 <li><a class="reference internal" href="#airflow.providers.sftp.hooks.sftp.SFTPHook.create_directory">create_directory</a></li>
 <li><a class="reference internal" href="#airflow.providers.sftp.hooks.sftp.SFTPHook.delete_directory">delete_directory</a></li>
 <li><a class="reference internal" href="#airflow.providers.sftp.hooks.sftp.SFTPHook.retrieve_file">retrieve_file</a></li>
@@ -941,6 +1009,7 @@ It is possible to filter results by giving prefix and/or delimiter parameters.</
 <li><a class="reference internal" href="#airflow.providers.sftp.hooks.sftp.SFTPHook.delete_file">delete_file</a></li>
 <li><a class="reference internal" href="#airflow.providers.sftp.hooks.sftp.SFTPHook.get_mod_time">get_mod_time</a></li>
 <li><a class="reference internal" href="#airflow.providers.sftp.hooks.sftp.SFTPHook.path_exists">path_exists</a></li>
+<li><a class="reference internal" href="#airflow.providers.sftp.hooks.sftp.SFTPHook.walktree">walktree</a></li>
 <li><a class="reference internal" href="#airflow.providers.sftp.hooks.sftp.SFTPHook.get_tree_map">get_tree_map</a></li>
 <li><a class="reference internal" href="#airflow.providers.sftp.hooks.sftp.SFTPHook.test_connection">test_connection</a></li>
 <li><a class="reference internal" href="#airflow.providers.sftp.hooks.sftp.SFTPHook.get_file_by_pattern">get_file_by_pattern</a></li>
@@ -1116,6 +1185,7 @@ It is possible to filter results by giving prefix and/or delimiter parameters.</
         <script data-url_root="../../../../../../" id="documentation_options" src="../../../../../../_static/documentation_options.js"></script>
         <script src="../../../../../../_static/jquery.js"></script>
         <script src="../../../../../../_static/underscore.js"></script>
+        <script src="../../../../../../_static/_sphinx_javascript_frameworks_compat.js"></script>
         <script src="../../../../../../_static/doctools.js"></script>
         <script src="../../../../../../_static/clipboard.min.js"></script>
         <script src="../../../../../../_static/copybutton.js"></script>
diff --git a/docs/apache-airflow-providers-sftp/stable/_api/airflow/providers/sftp/index.html b/docs/apache-airflow-providers-sftp/4.0.0/_api/airflow/providers/sftp/index.html
similarity index 99%
copy from docs/apache-airflow-providers-sftp/stable/_api/airflow/providers/sftp/index.html
copy to docs/apache-airflow-providers-sftp/4.0.0/_api/airflow/providers/sftp/index.html
index 348848a24c..6b92109f85 100644
--- a/docs/apache-airflow-providers-sftp/stable/_api/airflow/providers/sftp/index.html
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_api/airflow/providers/sftp/index.html
@@ -5,7 +5,7 @@
 <!DOCTYPE html>
 <!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
 <!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
-    <html xmlns="http://www.w3.org/1999/xhtml">
+    <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
 <head>
         <meta charset="utf-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1">
@@ -284,7 +284,7 @@
 <div id="docs-version-selector" class="docs-version-selector sidebar__version-selector">
     <a class="dropdown-toggle" href="#" id="versionDropdown" role="button" data-toggle="dropdown" aria-haspopup="true"
        aria-expanded="false">
-        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">3.0.0</span>
+        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">4.0.0</span>
     </a>
     <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
 
@@ -421,7 +421,7 @@
 <div id="docs-version-selector" class="docs-version-selector sidebar__version-selector">
     <a class="dropdown-toggle" href="#" id="versionDropdown" role="button" data-toggle="dropdown" aria-haspopup="true"
        aria-expanded="false">
-        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">3.0.0</span>
+        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">4.0.0</span>
     </a>
     <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
 
@@ -577,9 +577,9 @@
                                     <div class="body" role="main">
                                         
   <div class="section" id="module-airflow.providers.sftp">
-<span id="airflow-providers-sftp"></span><h1><a class="reference internal" href="#module-airflow.providers.sftp" title="airflow.providers.sftp"><code class="xref py py-mod docutils literal notranslate"><span class="pre">airflow.providers.sftp</span></code></a><a class="headerlink" href="#module-airflow.providers.sftp" title="Permalink to this headline">ΒΆ</a></h1>
+<span id="airflow-providers-sftp"></span><h1><a class="reference internal" href="#module-airflow.providers.sftp" title="airflow.providers.sftp"><code class="xref py py-mod docutils literal notranslate"><span class="pre">airflow.providers.sftp</span></code></a><a class="headerlink" href="#module-airflow.providers.sftp" title="Permalink to this heading">ΒΆ</a></h1>
 <div class="section" id="subpackages">
-<h2>Subpackages<a class="headerlink" href="#subpackages" title="Permalink to this headline">ΒΆ</a></h2>
+<h2>Subpackages<a class="headerlink" href="#subpackages" title="Permalink to this heading">ΒΆ</a></h2>
 <div class="toctree-wrapper compound">
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="hooks/index.html"><code class="xref py py-mod docutils literal notranslate"><span class="pre">airflow.providers.sftp.hooks</span></code></a><ul>
@@ -842,6 +842,7 @@
         <script data-url_root="../../../../" id="documentation_options" src="../../../../_static/documentation_options.js"></script>
         <script src="../../../../_static/jquery.js"></script>
         <script src="../../../../_static/underscore.js"></script>
+        <script src="../../../../_static/_sphinx_javascript_frameworks_compat.js"></script>
         <script src="../../../../_static/doctools.js"></script>
         <script src="../../../../_static/clipboard.min.js"></script>
         <script src="../../../../_static/copybutton.js"></script>
diff --git a/docs/apache-airflow-providers-sftp/stable/_api/airflow/providers/sftp/operators/index.html b/docs/apache-airflow-providers-sftp/4.0.0/_api/airflow/providers/sftp/operators/index.html
similarity index 99%
copy from docs/apache-airflow-providers-sftp/stable/_api/airflow/providers/sftp/operators/index.html
copy to docs/apache-airflow-providers-sftp/4.0.0/_api/airflow/providers/sftp/operators/index.html
index e2a8a0d710..45ac1a8635 100644
--- a/docs/apache-airflow-providers-sftp/stable/_api/airflow/providers/sftp/operators/index.html
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_api/airflow/providers/sftp/operators/index.html
@@ -5,7 +5,7 @@
 <!DOCTYPE html>
 <!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
 <!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
-    <html xmlns="http://www.w3.org/1999/xhtml">
+    <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
 <head>
         <meta charset="utf-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1">
@@ -284,7 +284,7 @@
 <div id="docs-version-selector" class="docs-version-selector sidebar__version-selector">
     <a class="dropdown-toggle" href="#" id="versionDropdown" role="button" data-toggle="dropdown" aria-haspopup="true"
        aria-expanded="false">
-        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">3.0.0</span>
+        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">4.0.0</span>
     </a>
     <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
 
@@ -421,7 +421,7 @@
 <div id="docs-version-selector" class="docs-version-selector sidebar__version-selector">
     <a class="dropdown-toggle" href="#" id="versionDropdown" role="button" data-toggle="dropdown" aria-haspopup="true"
        aria-expanded="false">
-        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">3.0.0</span>
+        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">4.0.0</span>
     </a>
     <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
 
@@ -579,9 +579,9 @@
                                     <div class="body" role="main">
                                         
   <div class="section" id="module-airflow.providers.sftp.operators">
-<span id="airflow-providers-sftp-operators"></span><h1><a class="reference internal" href="#module-airflow.providers.sftp.operators" title="airflow.providers.sftp.operators"><code class="xref py py-mod docutils literal notranslate"><span class="pre">airflow.providers.sftp.operators</span></code></a><a class="headerlink" href="#module-airflow.providers.sftp.operators" title="Permalink to this headline">ΒΆ</a></h1>
+<span id="airflow-providers-sftp-operators"></span><h1><a class="reference internal" href="#module-airflow.providers.sftp.operators" title="airflow.providers.sftp.operators"><code class="xref py py-mod docutils literal notranslate"><span class="pre">airflow.providers.sftp.operators</span></code></a><a class="headerlink" href="#module-airflow.providers.sftp.operators" title="Permalink to this heading">ΒΆ</a></h1>
 <div class="section" id="submodules">
-<h2>Submodules<a class="headerlink" href="#submodules" title="Permalink to this headline">ΒΆ</a></h2>
+<h2>Submodules<a class="headerlink" href="#submodules" title="Permalink to this heading">ΒΆ</a></h2>
 <div class="toctree-wrapper compound">
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="sftp/index.html"><code class="xref py py-mod docutils literal notranslate"><span class="pre">airflow.providers.sftp.operators.sftp</span></code></a></li>
@@ -833,6 +833,7 @@
         <script data-url_root="../../../../../" id="documentation_options" src="../../../../../_static/documentation_options.js"></script>
         <script src="../../../../../_static/jquery.js"></script>
         <script src="../../../../../_static/underscore.js"></script>
+        <script src="../../../../../_static/_sphinx_javascript_frameworks_compat.js"></script>
         <script src="../../../../../_static/doctools.js"></script>
         <script src="../../../../../_static/clipboard.min.js"></script>
         <script src="../../../../../_static/copybutton.js"></script>
diff --git a/docs/apache-airflow-providers-sftp/stable/_api/airflow/providers/sftp/operators/sftp/index.html b/docs/apache-airflow-providers-sftp/4.0.0/_api/airflow/providers/sftp/operators/sftp/index.html
similarity index 94%
copy from docs/apache-airflow-providers-sftp/stable/_api/airflow/providers/sftp/operators/sftp/index.html
copy to docs/apache-airflow-providers-sftp/4.0.0/_api/airflow/providers/sftp/operators/sftp/index.html
index 4b32912439..e9492fc78e 100644
--- a/docs/apache-airflow-providers-sftp/stable/_api/airflow/providers/sftp/operators/sftp/index.html
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_api/airflow/providers/sftp/operators/sftp/index.html
@@ -5,7 +5,7 @@
 <!DOCTYPE html>
 <!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
 <!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
-    <html xmlns="http://www.w3.org/1999/xhtml">
+    <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
 <head>
         <meta charset="utf-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1">
@@ -284,7 +284,7 @@
 <div id="docs-version-selector" class="docs-version-selector sidebar__version-selector">
     <a class="dropdown-toggle" href="#" id="versionDropdown" role="button" data-toggle="dropdown" aria-haspopup="true"
        aria-expanded="false">
-        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">3.0.0</span>
+        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">4.0.0</span>
     </a>
     <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
 
@@ -421,7 +421,7 @@
 <div id="docs-version-selector" class="docs-version-selector sidebar__version-selector">
     <a class="dropdown-toggle" href="#" id="versionDropdown" role="button" data-toggle="dropdown" aria-haspopup="true"
        aria-expanded="false">
-        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">3.0.0</span>
+        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">4.0.0</span>
     </a>
     <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
 
@@ -581,12 +581,12 @@
                                     <div class="body" role="main">
                                         
   <div class="section" id="module-airflow.providers.sftp.operators.sftp">
-<span id="airflow-providers-sftp-operators-sftp"></span><h1><a class="reference internal" href="#module-airflow.providers.sftp.operators.sftp" title="airflow.providers.sftp.operators.sftp"><code class="xref py py-mod docutils literal notranslate"><span class="pre">airflow.providers.sftp.operators.sftp</span></code></a><a class="headerlink" href="#module-airflow.providers.sftp.operators.sftp" title="Permalink to this headline">ΒΆ</a></h1>
+<span id="airflow-providers-sftp-operators-sftp"></span><h1><a class="reference internal" href="#module-airflow.providers.sftp.operators.sftp" title="airflow.providers.sftp.operators.sftp"><code class="xref py py-mod docutils literal notranslate"><span class="pre">airflow.providers.sftp.operators.sftp</span></code></a><a class="headerlink" href="#module-airflow.providers.sftp.operators.sftp" title="Permalink to this heading">ΒΆ</a></h1>
 <p>This module contains SFTP operator.</p>
 <div class="section" id="module-contents">
-<h2>Module Contents<a class="headerlink" href="#module-contents" title="Permalink to this headline">ΒΆ</a></h2>
+<h2>Module Contents<a class="headerlink" href="#module-contents" title="Permalink to this heading">ΒΆ</a></h2>
 <div class="section" id="classes">
-<h3>Classes<a class="headerlink" href="#classes" title="Permalink to this headline">ΒΆ</a></h3>
+<h3>Classes<a class="headerlink" href="#classes" title="Permalink to this heading">ΒΆ</a></h3>
 <table class="autosummary longtable docutils align-default">
 <colgroup>
 <col style="width: 10%" />
@@ -594,7 +594,7 @@
 </colgroup>
 <tbody>
 <tr class="row-odd"><td><p><a class="reference internal" href="#airflow.providers.sftp.operators.sftp.SFTPOperation" title="airflow.providers.sftp.operators.sftp.SFTPOperation"><code class="xref py py-obj docutils literal notranslate"><span class="pre">SFTPOperation</span></code></a></p></td>
-<td><p>Operation that can be used with SFTP/</p></td>
+<td><p>Operation that can be used with SFTP</p></td>
 </tr>
 <tr class="row-even"><td><p><a class="reference internal" href="#airflow.providers.sftp.operators.sftp.SFTPOperator" title="airflow.providers.sftp.operators.sftp.SFTPOperator"><code class="xref py py-obj docutils literal notranslate"><span class="pre">SFTPOperator</span></code></a></p></td>
 <td><p>SFTPOperator for transferring files from remote host to local or vice a versa.</p></td>
@@ -604,7 +604,7 @@
 <dl class="py class">
 <dt class="sig sig-object py" id="airflow.providers.sftp.operators.sftp.SFTPOperation">
 <em class="property"><span class="pre">class</span><span class="w"> </span></em><span class="sig-prename descclassname"><span class="pre">airflow.providers.sftp.operators.sftp.</span></span><span class="sig-name descname"><span class="pre">SFTPOperation</span></span><a class="reference internal" href="../../../../../../_modules/airflow/providers/sftp/operators/sftp.html#SFTPOperation"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#air [...]
-<dd><p>Operation that can be used with SFTP/</p>
+<dd><p>Operation that can be used with SFTP</p>
 <dl class="py attribute">
 <dt class="sig sig-object py" id="airflow.providers.sftp.operators.sftp.SFTPOperation.PUT">
 <span class="sig-name descname"><span class="pre">PUT</span></span><em class="property"><span class="w"> </span><span class="pre">=</span> <span class="pre">put</span></em><a class="reference internal" href="../../../../../../_modules/airflow/providers/sftp/operators/sftp.html#SFTPOperation.PUT"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#airflow.providers.sftp.operators.sftp.SFTPOperation.PUT" title="Permalink to this definition"> [...]
@@ -619,31 +619,33 @@
 
 <dl class="py class">
 <dt class="sig sig-object py" id="airflow.providers.sftp.operators.sftp.SFTPOperator">
-<em class="property"><span class="pre">class</span><span class="w"> </span></em><span class="sig-prename descclassname"><span class="pre">airflow.providers.sftp.operators.sftp.</span></span><span class="sig-name descname"><span class="pre">SFTPOperator</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="o"><span class="pre">*</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">ssh_hook</span></span><span class="o"><span class="pre">=</s [...]
-<dd><p>Bases: <a class="reference external" href="/docs/apache-airflow/stable/_api/airflow/models/index.html#airflow.models.BaseOperator" title="(in apache-airflow v2.1.4)"><code class="xref py py-obj docutils literal notranslate"><span class="pre">airflow.models.BaseOperator</span></code></a></p>
+<em class="property"><span class="pre">class</span><span class="w"> </span></em><span class="sig-prename descclassname"><span class="pre">airflow.providers.sftp.operators.sftp.</span></span><span class="sig-name descname"><span class="pre">SFTPOperator</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="o"><span class="pre">*</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">ssh_hook</span></span><span class="o"><span class="pre">=</s [...]
+<dd><p>Bases: <code class="xref py py-obj docutils literal notranslate"><span class="pre">airflow.models.BaseOperator</span></code></p>
 <p>SFTPOperator for transferring files from remote host to local or vice a versa.
-This operator uses ssh_hook to open sftp transport channel that serve as basis
+This operator uses sftp_hook to open sftp transport channel that serve as basis
 for file transfer.</p>
 <dl class="field-list simple">
 <dt class="field-odd">Parameters</dt>
 <dd class="field-odd"><ul class="simple">
-<li><p><strong>ssh_hook</strong> -- predefined ssh_hook to use for remote execution.
-Either <cite>ssh_hook</cite> or <cite>ssh_conn_id</cite> needs to be provided.</p></li>
-<li><p><strong>ssh_conn_id</strong> -- <a class="reference external" href="/docs/apache-airflow-providers-ssh/stable/connections/ssh.html#howto-connection-ssh" title="(in apache-airflow-providers-ssh v3.0.0)"><span class="xref std std-ref">ssh connection id</span></a>
+<li><p><strong>ssh_conn_id</strong> (<em>Optional</em><em>[</em><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a><em>]</em>) – <a class="reference external" href="/docs/apache-airflow-providers-ssh/stable/connections/ssh.html#howto-connection-ssh" title="(in apache-airflow-providers-ssh v3.1.0)"><span class="xref std std-ref">ssh connection id</span></a>
 from airflow Connections. <cite>ssh_conn_id</cite> will be ignored if <cite>ssh_hook</cite>
-is provided.</p></li>
-<li><p><strong>remote_host</strong> -- remote host to connect (templated)
+or <cite>sftp_hook</cite> is provided.</p></li>
+<li><p><strong>sftp_hook</strong> (<em>Optional</em><em>[</em><a class="reference internal" href="../../hooks/sftp/index.html#airflow.providers.sftp.hooks.sftp.SFTPHook" title="airflow.providers.sftp.hooks.sftp.SFTPHook"><em>airflow.providers.sftp.hooks.sftp.SFTPHook</em></a><em>]</em>) – predefined SFTPHook to use
+Either <cite>sftp_hook</cite> or <cite>ssh_conn_id</cite> needs to be provided.</p></li>
+<li><p><strong>ssh_hook</strong> (<em>Optional</em><em>[</em><a class="reference external" href="/docs/apache-airflow-providers-ssh/stable/_api/airflow/providers/ssh/hooks/ssh/index.html#airflow.providers.ssh.hooks.ssh.SSHHook" title="(in apache-airflow-providers-ssh v3.1.0)"><em>airflow.providers.ssh.hooks.ssh.SSHHook</em></a><em>]</em>) – Deprecated - predefined SSHHook to use for remote execution
+Use <cite>sftp_hook</cite> instead.</p></li>
+<li><p><strong>remote_host</strong> (<em>Optional</em><em>[</em><a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a><em>]</em>) – remote host to connect (templated)
 Nullable. If provided, it will replace the <cite>remote_host</cite> which was
-defined in <cite>ssh_hook</cite> or predefined in the connection of <cite>ssh_conn_id</cite>.</p></li>
-<li><p><strong>local_filepath</strong> -- local file path to get or put. (templated)</p></li>
-<li><p><strong>remote_filepath</strong> -- remote file path to get or put. (templated)</p></li>
-<li><p><strong>operation</strong> -- specify operation 'get' or 'put', defaults to put</p></li>
-<li><p><strong>confirm</strong> -- specify if the SFTP operation should be confirmed, defaults to True</p></li>
-<li><p><strong>create_intermediate_dirs</strong> -- <p>create missing intermediate directories when
+defined in <cite>sftp_hook</cite>/<cite>ssh_hook</cite> or predefined in the connection of <cite>ssh_conn_id</cite>.</p></li>
+<li><p><strong>local_filepath</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a>) – local file path to get or put. (templated)</p></li>
+<li><p><strong>remote_filepath</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a>) – remote file path to get or put. (templated)</p></li>
+<li><p><strong>operation</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a>) – specify operation β€˜get’ or β€˜put’, defaults to put</p></li>
+<li><p><strong>confirm</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#bool" title="(in Python v3.10)"><em>bool</em></a>) – specify if the SFTP operation should be confirmed, defaults to True</p></li>
+<li><p><strong>create_intermediate_dirs</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#bool" title="(in Python v3.10)"><em>bool</em></a>) – <p>create missing intermediate directories when
 copying from remote to local and vice-versa. Default is False.</p>
 <p>Example: The following task would copy <code class="docutils literal notranslate"><span class="pre">file.txt</span></code> to the remote host
 at <code class="docutils literal notranslate"><span class="pre">/tmp/tmp1/tmp2/</span></code> while creating <code class="docutils literal notranslate"><span class="pre">tmp</span></code>,``tmp1`` and <code class="docutils literal notranslate"><span class="pre">tmp2</span></code> if they
-don't exist. If the parameter is not passed it would error as the directory
+don’t exist. If the parameter is not passed it would error as the directory
 does not exist.</p>
 <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">put_file</span> <span class="o">=</span> <span class="n">SFTPOperator</span><span class="p">(</span>
     <span class="n">task_id</span><span class="o">=</span><span class="s2">&quot;test_sftp&quot;</span><span class="p">,</span>
@@ -939,6 +941,7 @@ Context is the same dictionary used as when rendering jinja templates.</p>
         <script data-url_root="../../../../../../" id="documentation_options" src="../../../../../../_static/documentation_options.js"></script>
         <script src="../../../../../../_static/jquery.js"></script>
         <script src="../../../../../../_static/underscore.js"></script>
+        <script src="../../../../../../_static/_sphinx_javascript_frameworks_compat.js"></script>
         <script src="../../../../../../_static/doctools.js"></script>
         <script src="../../../../../../_static/clipboard.min.js"></script>
         <script src="../../../../../../_static/copybutton.js"></script>
diff --git a/docs/apache-airflow-providers-sftp/stable/_api/airflow/providers/sftp/sensors/index.html b/docs/apache-airflow-providers-sftp/4.0.0/_api/airflow/providers/sftp/sensors/index.html
similarity index 99%
copy from docs/apache-airflow-providers-sftp/stable/_api/airflow/providers/sftp/sensors/index.html
copy to docs/apache-airflow-providers-sftp/4.0.0/_api/airflow/providers/sftp/sensors/index.html
index 86769d8c65..d6fb20e73a 100644
--- a/docs/apache-airflow-providers-sftp/stable/_api/airflow/providers/sftp/sensors/index.html
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_api/airflow/providers/sftp/sensors/index.html
@@ -5,7 +5,7 @@
 <!DOCTYPE html>
 <!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
 <!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
-    <html xmlns="http://www.w3.org/1999/xhtml">
+    <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
 <head>
         <meta charset="utf-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1">
@@ -284,7 +284,7 @@
 <div id="docs-version-selector" class="docs-version-selector sidebar__version-selector">
     <a class="dropdown-toggle" href="#" id="versionDropdown" role="button" data-toggle="dropdown" aria-haspopup="true"
        aria-expanded="false">
-        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">3.0.0</span>
+        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">4.0.0</span>
     </a>
     <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
 
@@ -421,7 +421,7 @@
 <div id="docs-version-selector" class="docs-version-selector sidebar__version-selector">
     <a class="dropdown-toggle" href="#" id="versionDropdown" role="button" data-toggle="dropdown" aria-haspopup="true"
        aria-expanded="false">
-        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">3.0.0</span>
+        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">4.0.0</span>
     </a>
     <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
 
@@ -579,9 +579,9 @@
                                     <div class="body" role="main">
                                         
   <div class="section" id="module-airflow.providers.sftp.sensors">
-<span id="airflow-providers-sftp-sensors"></span><h1><a class="reference internal" href="#module-airflow.providers.sftp.sensors" title="airflow.providers.sftp.sensors"><code class="xref py py-mod docutils literal notranslate"><span class="pre">airflow.providers.sftp.sensors</span></code></a><a class="headerlink" href="#module-airflow.providers.sftp.sensors" title="Permalink to this headline">ΒΆ</a></h1>
+<span id="airflow-providers-sftp-sensors"></span><h1><a class="reference internal" href="#module-airflow.providers.sftp.sensors" title="airflow.providers.sftp.sensors"><code class="xref py py-mod docutils literal notranslate"><span class="pre">airflow.providers.sftp.sensors</span></code></a><a class="headerlink" href="#module-airflow.providers.sftp.sensors" title="Permalink to this heading">ΒΆ</a></h1>
 <div class="section" id="submodules">
-<h2>Submodules<a class="headerlink" href="#submodules" title="Permalink to this headline">ΒΆ</a></h2>
+<h2>Submodules<a class="headerlink" href="#submodules" title="Permalink to this heading">ΒΆ</a></h2>
 <div class="toctree-wrapper compound">
 <ul>
 <li class="toctree-l1"><a class="reference internal" href="sftp/index.html"><code class="xref py py-mod docutils literal notranslate"><span class="pre">airflow.providers.sftp.sensors.sftp</span></code></a></li>
@@ -833,6 +833,7 @@
         <script data-url_root="../../../../../" id="documentation_options" src="../../../../../_static/documentation_options.js"></script>
         <script src="../../../../../_static/jquery.js"></script>
         <script src="../../../../../_static/underscore.js"></script>
+        <script src="../../../../../_static/_sphinx_javascript_frameworks_compat.js"></script>
         <script src="../../../../../_static/doctools.js"></script>
         <script src="../../../../../_static/clipboard.min.js"></script>
         <script src="../../../../../_static/copybutton.js"></script>
diff --git a/docs/apache-airflow-providers-sftp/stable/_api/airflow/providers/sftp/sensors/sftp/index.html b/docs/apache-airflow-providers-sftp/4.0.0/_api/airflow/providers/sftp/sensors/sftp/index.html
similarity index 98%
copy from docs/apache-airflow-providers-sftp/stable/_api/airflow/providers/sftp/sensors/sftp/index.html
copy to docs/apache-airflow-providers-sftp/4.0.0/_api/airflow/providers/sftp/sensors/sftp/index.html
index e99ce130de..feed312fd0 100644
--- a/docs/apache-airflow-providers-sftp/stable/_api/airflow/providers/sftp/sensors/sftp/index.html
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_api/airflow/providers/sftp/sensors/sftp/index.html
@@ -5,7 +5,7 @@
 <!DOCTYPE html>
 <!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
 <!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
-    <html xmlns="http://www.w3.org/1999/xhtml">
+    <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
 <head>
         <meta charset="utf-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1">
@@ -284,7 +284,7 @@
 <div id="docs-version-selector" class="docs-version-selector sidebar__version-selector">
     <a class="dropdown-toggle" href="#" id="versionDropdown" role="button" data-toggle="dropdown" aria-haspopup="true"
        aria-expanded="false">
-        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">3.0.0</span>
+        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">4.0.0</span>
     </a>
     <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
 
@@ -421,7 +421,7 @@
 <div id="docs-version-selector" class="docs-version-selector sidebar__version-selector">
     <a class="dropdown-toggle" href="#" id="versionDropdown" role="button" data-toggle="dropdown" aria-haspopup="true"
        aria-expanded="false">
-        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">3.0.0</span>
+        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">4.0.0</span>
     </a>
     <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
 
@@ -581,12 +581,12 @@
                                     <div class="body" role="main">
                                         
   <div class="section" id="module-airflow.providers.sftp.sensors.sftp">
-<span id="airflow-providers-sftp-sensors-sftp"></span><h1><a class="reference internal" href="#module-airflow.providers.sftp.sensors.sftp" title="airflow.providers.sftp.sensors.sftp"><code class="xref py py-mod docutils literal notranslate"><span class="pre">airflow.providers.sftp.sensors.sftp</span></code></a><a class="headerlink" href="#module-airflow.providers.sftp.sensors.sftp" title="Permalink to this headline">ΒΆ</a></h1>
+<span id="airflow-providers-sftp-sensors-sftp"></span><h1><a class="reference internal" href="#module-airflow.providers.sftp.sensors.sftp" title="airflow.providers.sftp.sensors.sftp"><code class="xref py py-mod docutils literal notranslate"><span class="pre">airflow.providers.sftp.sensors.sftp</span></code></a><a class="headerlink" href="#module-airflow.providers.sftp.sensors.sftp" title="Permalink to this heading">ΒΆ</a></h1>
 <p>This module contains SFTP sensor.</p>
 <div class="section" id="module-contents">
-<h2>Module Contents<a class="headerlink" href="#module-contents" title="Permalink to this headline">ΒΆ</a></h2>
+<h2>Module Contents<a class="headerlink" href="#module-contents" title="Permalink to this heading">ΒΆ</a></h2>
 <div class="section" id="classes">
-<h3>Classes<a class="headerlink" href="#classes" title="Permalink to this headline">ΒΆ</a></h3>
+<h3>Classes<a class="headerlink" href="#classes" title="Permalink to this heading">ΒΆ</a></h3>
 <table class="autosummary longtable docutils align-default">
 <colgroup>
 <col style="width: 10%" />
@@ -601,15 +601,15 @@
 <dl class="py class">
 <dt class="sig sig-object py" id="airflow.providers.sftp.sensors.sftp.SFTPSensor">
 <em class="property"><span class="pre">class</span><span class="w"> </span></em><span class="sig-prename descclassname"><span class="pre">airflow.providers.sftp.sensors.sftp.</span></span><span class="sig-name descname"><span class="pre">SFTPSensor</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="o"><span class="pre">*</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">path</span></span></em>, <em class="sig-param"><span class="n">< [...]
-<dd><p>Bases: <a class="reference external" href="/docs/apache-airflow/stable/_api/airflow/sensors/base/index.html#airflow.sensors.base.BaseSensorOperator" title="(in apache-airflow v2.1.4)"><code class="xref py py-obj docutils literal notranslate"><span class="pre">airflow.sensors.base.BaseSensorOperator</span></code></a></p>
+<dd><p>Bases: <a class="reference external" href="/docs/apache-airflow/stable/_api/airflow/sensors/base/index.html#airflow.sensors.base.BaseSensorOperator" title="(in apache-airflow v2.4.0.dev0)"><code class="xref py py-obj docutils literal notranslate"><span class="pre">airflow.sensors.base.BaseSensorOperator</span></code></a></p>
 <p>Waits for a file or directory to be present on SFTP.</p>
 <dl class="field-list simple">
 <dt class="field-odd">Parameters</dt>
 <dd class="field-odd"><ul class="simple">
-<li><p><strong>path</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a>) -- Remote file or directory path</p></li>
-<li><p><strong>file_pattern</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a>) -- The pattern that will be used to match the file (fnmatch format)</p></li>
-<li><p><strong>sftp_conn_id</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a>) -- The connection to run the sensor against</p></li>
-<li><p><strong>newer_than</strong> (<em>Optional</em><em>[</em><a class="reference external" href="https://docs.python.org/3/library/datetime.html#datetime.datetime" title="(in Python v3.10)"><em>datetime.datetime</em></a><em>]</em>) -- DateTime for which the file or file path should be newer than, comparison is inclusive</p></li>
+<li><p><strong>path</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a>) – Remote file or directory path</p></li>
+<li><p><strong>file_pattern</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a>) – The pattern that will be used to match the file (fnmatch format)</p></li>
+<li><p><strong>sftp_conn_id</strong> (<a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#str" title="(in Python v3.10)"><em>str</em></a>) – The connection to run the sensor against</p></li>
+<li><p><strong>newer_than</strong> (<em>Optional</em><em>[</em><a class="reference external" href="https://docs.python.org/3/library/datetime.html#datetime.datetime" title="(in Python v3.10)"><em>datetime.datetime</em></a><em>]</em>) – DateTime for which the file or file path should be newer than, comparison is inclusive</p></li>
 </ul>
 </dd>
 </dl>
@@ -886,6 +886,7 @@ override.</p>
         <script data-url_root="../../../../../../" id="documentation_options" src="../../../../../../_static/documentation_options.js"></script>
         <script src="../../../../../../_static/jquery.js"></script>
         <script src="../../../../../../_static/underscore.js"></script>
+        <script src="../../../../../../_static/_sphinx_javascript_frameworks_compat.js"></script>
         <script src="../../../../../../_static/doctools.js"></script>
         <script src="../../../../../../_static/clipboard.min.js"></script>
         <script src="../../../../../../_static/copybutton.js"></script>
diff --git a/docs/apache-airflow-providers-sftp/stable/_modules/airflow/providers/sftp/hooks/sftp.html b/docs/apache-airflow-providers-sftp/4.0.0/_modules/airflow/providers/sftp/hooks/sftp.html
similarity index 84%
copy from docs/apache-airflow-providers-sftp/stable/_modules/airflow/providers/sftp/hooks/sftp.html
copy to docs/apache-airflow-providers-sftp/4.0.0/_modules/airflow/providers/sftp/hooks/sftp.html
index a9eddbf614..6fb097797a 100644
--- a/docs/apache-airflow-providers-sftp/stable/_modules/airflow/providers/sftp/hooks/sftp.html
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_modules/airflow/providers/sftp/hooks/sftp.html
@@ -5,7 +5,7 @@
 <!DOCTYPE html>
 <!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
 <!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
-    <html xmlns="http://www.w3.org/1999/xhtml">
+    <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
 <head>
         <meta charset="utf-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1">
@@ -282,7 +282,7 @@
 <div id="docs-version-selector" class="docs-version-selector sidebar__version-selector">
     <a class="dropdown-toggle" href="#" id="versionDropdown" role="button" data-toggle="dropdown" aria-haspopup="true"
        aria-expanded="false">
-        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">3.0.0</span>
+        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">4.0.0</span>
     </a>
     <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
 
@@ -419,7 +419,7 @@
 <div id="docs-version-selector" class="docs-version-selector sidebar__version-selector">
     <a class="dropdown-toggle" href="#" id="versionDropdown" role="button" data-toggle="dropdown" aria-haspopup="true"
        aria-expanded="false">
-        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">3.0.0</span>
+        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">4.0.0</span>
     </a>
     <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
 
@@ -596,15 +596,15 @@
 <span class="c1"># under the License.</span>
 <span class="sd">&quot;&quot;&quot;This module contains SFTP hook.&quot;&quot;&quot;</span>
 <span class="kn">import</span> <span class="nn">datetime</span>
+<span class="kn">import</span> <span class="nn">os</span>
 <span class="kn">import</span> <span class="nn">stat</span>
 <span class="kn">import</span> <span class="nn">warnings</span>
 <span class="kn">from</span> <span class="nn">fnmatch</span> <span class="kn">import</span> <span class="n">fnmatch</span>
-<span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Any</span><span class="p">,</span> <span class="n">Dict</span><span class="p">,</span> <span class="n">List</span><span class="p">,</span> <span class="n">Optional</span><span class="p">,</span> <span class="n">Tuple</span>
+<span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Any</span><span class="p">,</span> <span class="n">Callable</span><span class="p">,</span> <span class="n">Dict</span><span class="p">,</span> <span class="n">List</span><span class="p">,</span> <span class="n">Optional</span><span class="p">,</span> <span class="n">Tuple</span><span class="p">,</span> <span class="n">Union</span>
 
-<span class="kn">import</span> <span class="nn">pysftp</span>
-<span class="kn">import</span> <span class="nn">tenacity</span>
-<span class="kn">from</span> <span class="nn">paramiko</span> <span class="kn">import</span> <span class="n">SSHException</span>
+<span class="kn">import</span> <span class="nn">paramiko</span>
 
+<span class="kn">from</span> <span class="nn">airflow.exceptions</span> <span class="kn">import</span> <span class="n">AirflowException</span>
 <span class="kn">from</span> <span class="nn">airflow.providers.ssh.hooks.ssh</span> <span class="kn">import</span> <span class="n">SSHHook</span>
 
 
@@ -628,11 +628,9 @@
 <span class="sd">    Errors that may occur throughout but should be handled downstream.</span>
 
 <span class="sd">    For consistency reasons with SSHHook, the preferred parameter is &quot;ssh_conn_id&quot;.</span>
-<span class="sd">    Please note that it is still possible to use the parameter &quot;ftp_conn_id&quot;</span>
-<span class="sd">    to initialize the hook, but it will be removed in future Airflow versions.</span>
 
 <span class="sd">    :param ssh_conn_id: The :ref:`sftp connection id&lt;howto/connection:sftp&gt;`</span>
-<span class="sd">    :param ftp_conn_id (Outdated): The :ref:`sftp connection id&lt;howto/connection:sftp&gt;`</span>
+<span class="sd">    :param ssh_hook: Optional SSH hook (included to support passing of an SSH hook to the SFTP operator)</span>
 <span class="sd">    &quot;&quot;&quot;</span>
 
 <div class="viewcode-block" id="SFTPHook.conn_name_attr"><a class="viewcode-back" href="../../../../../_api/airflow/providers/sftp/hooks/sftp/index.html#airflow.providers.sftp.hooks.sftp.SFTPHook.conn_name_attr">[docs]</a>    <span class="n">conn_name_attr</span> <span class="o">=</span> <span class="s1">&#39;ssh_conn_id&#39;</span></div>
@@ -652,9 +650,29 @@
     <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span>
         <span class="bp">self</span><span class="p">,</span>
         <span class="n">ssh_conn_id</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;sftp_default&#39;</span><span class="p">,</span>
+        <span class="n">ssh_hook</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">SSHHook</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
         <span class="o">*</span><span class="n">args</span><span class="p">,</span>
         <span class="o">**</span><span class="n">kwargs</span><span class="p">,</span>
     <span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">conn</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">paramiko</span><span class="o">.</span><span class="n">SFTPClient</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
+
+        <span class="c1"># TODO: remove support for ssh_hook when it is removed from SFTPOperator</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">ssh_hook</span> <span class="o">=</span> <span class="n">ssh_hook</span>
+
+        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">ssh_hook</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
+            <span class="n">warnings</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span>
+                <span class="s1">&#39;Parameter `ssh_hook` is deprecated and will be removed in a future version.&#39;</span><span class="p">,</span>
+                <span class="ne">DeprecationWarning</span><span class="p">,</span>
+                <span class="n">stacklevel</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span>
+            <span class="p">)</span>
+            <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">ssh_hook</span><span class="p">,</span> <span class="n">SSHHook</span><span class="p">):</span>
+                <span class="k">raise</span> <span class="n">AirflowException</span><span class="p">(</span>
+                    <span class="sa">f</span><span class="s1">&#39;ssh_hook must be an instance of SSHHook, but got </span><span class="si">{</span><span class="nb">type</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">ssh_hook</span><span class="p">)</span><span class="si">}</span><span class="s1">&#39;</span>
+                <span class="p">)</span>
+            <span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s1">&#39;ssh_hook is provided. It will be used to generate SFTP connection.&#39;</span><span class="p">)</span>
+            <span class="bp">self</span><span class="o">.</span><span class="n">ssh_conn_id</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">ssh_hook</span><span class="o">.</span><span class="n">ssh_conn_id</span>
+            <span class="k">return</span>
+
         <span class="n">ftp_conn_id</span> <span class="o">=</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s1">&#39;ftp_conn_id&#39;</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
         <span class="k">if</span> <span class="n">ftp_conn_id</span><span class="p">:</span>
             <span class="n">warnings</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span>
@@ -663,100 +681,33 @@
                 <span class="n">stacklevel</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span>
             <span class="p">)</span>
             <span class="n">ssh_conn_id</span> <span class="o">=</span> <span class="n">ftp_conn_id</span>
+
         <span class="n">kwargs</span><span class="p">[</span><span class="s1">&#39;ssh_conn_id&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">ssh_conn_id</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">ssh_conn_id</span> <span class="o">=</span> <span class="n">ssh_conn_id</span>
+
         <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
 
-        <span class="bp">self</span><span class="o">.</span><span class="n">conn</span> <span class="o">=</span> <span class="kc">None</span>
-        <span class="bp">self</span><span class="o">.</span><span class="n">private_key_pass</span> <span class="o">=</span> <span class="kc">None</span>
-        <span class="bp">self</span><span class="o">.</span><span class="n">ciphers</span> <span class="o">=</span> <span class="kc">None</span>
-
-        <span class="c1"># Fail for unverified hosts, unless this is explicitly allowed</span>
-        <span class="bp">self</span><span class="o">.</span><span class="n">no_host_key_check</span> <span class="o">=</span> <span class="kc">False</span>
-
-        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">ssh_conn_id</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
-            <span class="n">conn</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_connection</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">ssh_conn_id</span><span class="p">)</span>
-            <span class="k">if</span> <span class="n">conn</span><span class="o">.</span><span class="n">extra</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
-                <span class="n">extra_options</span> <span class="o">=</span> <span class="n">conn</span><span class="o">.</span><span class="n">extra_dejson</span>
-
-                <span class="c1"># For backward compatibility</span>
-                <span class="c1"># TODO: remove in the next major provider release.</span>
-
-                <span class="k">if</span> <span class="s1">&#39;private_key_pass&#39;</span> <span class="ow">in</span> <span class="n">extra_options</span><span class="p">:</span>
-                    <span class="n">warnings</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span>
-                        <span class="s1">&#39;Extra option `private_key_pass` is deprecated.&#39;</span>
-                        <span class="s1">&#39;Please use `private_key_passphrase` instead.&#39;</span>
-                        <span class="s1">&#39;`private_key_passphrase` will precede if both options are specified.&#39;</span>
-                        <span class="s1">&#39;The old option `private_key_pass` will be removed in a future release.&#39;</span><span class="p">,</span>
-                        <span class="ne">DeprecationWarning</span><span class="p">,</span>
-                        <span class="n">stacklevel</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span>
-                    <span class="p">)</span>
-                <span class="bp">self</span><span class="o">.</span><span class="n">private_key_pass</span> <span class="o">=</span> <span class="n">extra_options</span><span class="o">.</span><span class="n">get</span><span class="p">(</span>
-                    <span class="s1">&#39;private_key_passphrase&#39;</span><span class="p">,</span> <span class="n">extra_options</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;private_key_pass&#39;</span><span class="p">)</span>
-                <span class="p">)</span>
+<div class="viewcode-block" id="SFTPHook.get_conn"><a class="viewcode-back" href="../../../../../_api/airflow/providers/sftp/hooks/sftp/index.html#airflow.providers.sftp.hooks.sftp.SFTPHook.get_conn">[docs]</a>    <span class="k">def</span> <span class="nf">get_conn</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">paramiko</span><span class="o">.</span><span class="n">SFTPClient</span><span class="p">:</span>  [...]
+        <span class="sd">&quot;&quot;&quot;</span>
+<span class="sd">        Opens an SFTP connection to the remote host</span>
 
-                <span class="k">if</span> <span class="s1">&#39;ignore_hostkey_verification&#39;</span> <span class="ow">in</span> <span class="n">extra_options</span><span class="p">:</span>
-                    <span class="n">warnings</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span>
-                        <span class="s1">&#39;Extra option `ignore_hostkey_verification` is deprecated.&#39;</span>
-                        <span class="s1">&#39;Please use `no_host_key_check` instead.&#39;</span>
-                        <span class="s1">&#39;This option will be removed in a future release.&#39;</span><span class="p">,</span>
-                        <span class="ne">DeprecationWarning</span><span class="p">,</span>
-                        <span class="n">stacklevel</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span>
-                    <span class="p">)</span>
-                    <span class="bp">self</span><span class="o">.</span><span class="n">no_host_key_check</span> <span class="o">=</span> <span class="p">(</span>
-                        <span class="nb">str</span><span class="p">(</span><span class="n">extra_options</span><span class="p">[</span><span class="s1">&#39;ignore_hostkey_verification&#39;</span><span class="p">])</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="o">==</span> <span class="s1">&#39;true&#39;</span>
-                    <span class="p">)</span>
-
-                <span class="k">if</span> <span class="s1">&#39;no_host_key_check&#39;</span> <span class="ow">in</span> <span class="n">extra_options</span><span class="p">:</span>
-                    <span class="bp">self</span><span class="o">.</span><span class="n">no_host_key_check</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">extra_options</span><span class="p">[</span><span class="s1">&#39;no_host_key_check&#39;</span><span class="p">])</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="o">==</span> <span class="s1">&#39;true&#39;</span>
-
-                <span class="k">if</span> <span class="s1">&#39;ciphers&#39;</span> <span class="ow">in</span> <span class="n">extra_options</span><span class="p">:</span>
-                    <span class="bp">self</span><span class="o">.</span><span class="n">ciphers</span> <span class="o">=</span> <span class="n">extra_options</span><span class="p">[</span><span class="s1">&#39;ciphers&#39;</span><span class="p">]</span>
-
-    <span class="nd">@tenacity</span><span class="o">.</span><span class="n">retry</span><span class="p">(</span>
-        <span class="n">stop</span><span class="o">=</span><span class="n">tenacity</span><span class="o">.</span><span class="n">stop_after_delay</span><span class="p">(</span><span class="mi">10</span><span class="p">),</span>
-        <span class="n">wait</span><span class="o">=</span><span class="n">tenacity</span><span class="o">.</span><span class="n">wait_exponential</span><span class="p">(</span><span class="n">multiplier</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="nb">max</span><span class="o">=</span><span class="mi">10</span><span class="p">),</span>
-        <span class="n">retry</span><span class="o">=</span><span class="n">tenacity</span><span class="o">.</span><span class="n">retry_if_exception_type</span><span class="p">(</span><span class="n">SSHException</span><span class="p">),</span>
-        <span class="n">reraise</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
-<div class="viewcode-block" id="SFTPHook.get_conn"><a class="viewcode-back" href="../../../../../_api/airflow/providers/sftp/hooks/sftp/index.html#airflow.providers.sftp.hooks.sftp.SFTPHook.get_conn">[docs]</a>    <span class="p">)</span>
-    <span class="k">def</span> <span class="nf">get_conn</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">pysftp</span><span class="o">.</span><span class="n">Connection</span><span class="p">:</span>
-        <span class="sd">&quot;&quot;&quot;Returns an SFTP connection object&quot;&quot;&quot;</span>
+<span class="sd">        :rtype: paramiko.SFTPClient</span>
+<span class="sd">        &quot;&quot;&quot;</span>
         <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">conn</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
-            <span class="n">cnopts</span> <span class="o">=</span> <span class="n">pysftp</span><span class="o">.</span><span class="n">CnOpts</span><span class="p">()</span>
-            <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">no_host_key_check</span><span class="p">:</span>
-                <span class="n">cnopts</span><span class="o">.</span><span class="n">hostkeys</span> <span class="o">=</span> <span class="kc">None</span>
+            <span class="c1"># TODO: remove support for ssh_hook when it is removed from SFTPOperator</span>
+            <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">ssh_hook</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
+                <span class="bp">self</span><span class="o">.</span><span class="n">conn</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">ssh_hook</span><span class="o">.</span><span class="n">get_conn</span><span class="p">()</span><span class="o">.</span><span class="n">open_sftp</span><span class="p">()</span>
             <span class="k">else</span><span class="p">:</span>
-                <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">host_key</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
-                    <span class="n">cnopts</span><span class="o">.</span><span class="n">hostkeys</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">remote_host</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">host_key</span><span class="o">.</span><span class="n">get_name</span><span class="p">(),</span> <span class="bp">self</span><span clas [...]
-                <span class="k">else</span><span class="p">:</span>
-                    <span class="k">pass</span>  <span class="c1"># will fallback to system host keys if none explicitly specified in conn extra</span>
-
-            <span class="n">cnopts</span><span class="o">.</span><span class="n">compression</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">compress</span>
-            <span class="n">cnopts</span><span class="o">.</span><span class="n">ciphers</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">ciphers</span>
-            <span class="n">conn_params</span> <span class="o">=</span> <span class="p">{</span>
-                <span class="s1">&#39;host&#39;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">remote_host</span><span class="p">,</span>
-                <span class="s1">&#39;port&#39;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">port</span><span class="p">,</span>
-                <span class="s1">&#39;username&#39;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">username</span><span class="p">,</span>
-                <span class="s1">&#39;cnopts&#39;</span><span class="p">:</span> <span class="n">cnopts</span><span class="p">,</span>
-            <span class="p">}</span>
-            <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">password</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">password</span><span class="o">.</span><span class="n">strip</span><span class="p">():</span>
-                <span class="n">conn_params</span><span class="p">[</span><span class="s1">&#39;password&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">password</span>
-            <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">pkey</span><span class="p">:</span>
-                <span class="n">conn_params</span><span class="p">[</span><span class="s1">&#39;private_key&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">pkey</span>
-            <span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">key_file</span><span class="p">:</span>
-                <span class="n">conn_params</span><span class="p">[</span><span class="s1">&#39;private_key&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">key_file</span>
-            <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">private_key_pass</span><span class="p">:</span>
-                <span class="n">conn_params</span><span class="p">[</span><span class="s1">&#39;private_key_pass&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">private_key_pass</span>
-
-            <span class="bp">self</span><span class="o">.</span><span class="n">conn</span> <span class="o">=</span> <span class="n">pysftp</span><span class="o">.</span><span class="n">Connection</span><span class="p">(</span><span class="o">**</span><span class="n">conn_params</span><span class="p">)</span>
+                <span class="bp">self</span><span class="o">.</span><span class="n">conn</span> <span class="o">=</span> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="n">get_conn</span><span class="p">()</span><span class="o">.</span><span class="n">open_sftp</span><span class="p">()</span>
         <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">conn</span></div>
 
 <div class="viewcode-block" id="SFTPHook.close_conn"><a class="viewcode-back" href="../../../../../_api/airflow/providers/sftp/hooks/sftp/index.html#airflow.providers.sftp.hooks.sftp.SFTPHook.close_conn">[docs]</a>    <span class="k">def</span> <span class="nf">close_conn</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
-        <span class="sd">&quot;&quot;&quot;Closes the connection&quot;&quot;&quot;</span>
+        <span class="sd">&quot;&quot;&quot;Closes the SFTP connection&quot;&quot;&quot;</span>
         <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">conn</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
             <span class="bp">self</span><span class="o">.</span><span class="n">conn</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
             <span class="bp">self</span><span class="o">.</span><span class="n">conn</span> <span class="o">=</span> <span class="kc">None</span></div>
 
-<div class="viewcode-block" id="SFTPHook.describe_directory"><a class="viewcode-back" href="../../../../../_api/airflow/providers/sftp/hooks/sftp/index.html#airflow.providers.sftp.hooks.sftp.SFTPHook.describe_directory">[docs]</a>    <span class="k">def</span> <span class="nf">describe_directory</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">path</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span cl [...]
+<div class="viewcode-block" id="SFTPHook.describe_directory"><a class="viewcode-back" href="../../../../../_api/airflow/providers/sftp/hooks/sftp/index.html#airflow.providers.sftp.hooks.sftp.SFTPHook.describe_directory">[docs]</a>    <span class="k">def</span> <span class="nf">describe_directory</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">path</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span cl [...]
         <span class="sd">&quot;&quot;&quot;</span>
 <span class="sd">        Returns a dictionary of {filename: {attributes}} for all files</span>
 <span class="sd">        on the remote system (where the MLSD command is supported).</span>
@@ -764,13 +715,13 @@
 <span class="sd">        :param path: full path to the remote directory</span>
 <span class="sd">        &quot;&quot;&quot;</span>
         <span class="n">conn</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_conn</span><span class="p">()</span>
-        <span class="n">flist</span> <span class="o">=</span> <span class="n">conn</span><span class="o">.</span><span class="n">listdir_attr</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
+        <span class="n">flist</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">conn</span><span class="o">.</span><span class="n">listdir_attr</span><span class="p">(</span><span class="n">path</span><span class="p">),</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span><span class="o">.</span><span class="n">filename</span><span [...]
         <span class="n">files</span> <span class="o">=</span> <span class="p">{}</span>
         <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">flist</span><span class="p">:</span>
-            <span class="n">modify</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">fromtimestamp</span><span class="p">(</span><span class="n">f</span><span class="o">.</span><span class="n">st_mtime</span><span class="p">)</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">&#39;%Y%m</span><span class="si">%d</span><span class="s [...]
+            <span class="n">modify</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">fromtimestamp</span><span class="p">(</span><span class="n">f</span><span class="o">.</span><span class="n">st_mtime</span><span class="p">)</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">&#39;%Y%m</span><span class="si">%d</span><span class="s [...]
             <span class="n">files</span><span class="p">[</span><span class="n">f</span><span class="o">.</span><span class="n">filename</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span>
                 <span class="s1">&#39;size&#39;</span><span class="p">:</span> <span class="n">f</span><span class="o">.</span><span class="n">st_size</span><span class="p">,</span>
-                <span class="s1">&#39;type&#39;</span><span class="p">:</span> <span class="s1">&#39;dir&#39;</span> <span class="k">if</span> <span class="n">stat</span><span class="o">.</span><span class="n">S_ISDIR</span><span class="p">(</span><span class="n">f</span><span class="o">.</span><span class="n">st_mode</span><span class="p">)</span> <span class="k">else</span> <span class="s1">&#39;file&#39;</span><span class="p">,</span>
+                <span class="s1">&#39;type&#39;</span><span class="p">:</span> <span class="s1">&#39;dir&#39;</span> <span class="k">if</span> <span class="n">stat</span><span class="o">.</span><span class="n">S_ISDIR</span><span class="p">(</span><span class="n">f</span><span class="o">.</span><span class="n">st_mode</span><span class="p">)</span> <span class="k">else</span> <span class="s1">&#39;file&#39;</span><span class="p">,</span>  <span class="c1"># type: ignore</span>
                 <span class="s1">&#39;modify&#39;</span><span class="p">:</span> <span class="n">modify</span><span class="p">,</span>
             <span class="p">}</span>
         <span class="k">return</span> <span class="n">files</span></div>
@@ -782,9 +733,45 @@
 <span class="sd">        :param path: full path to the remote directory to list</span>
 <span class="sd">        &quot;&quot;&quot;</span>
         <span class="n">conn</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_conn</span><span class="p">()</span>
-        <span class="n">files</span> <span class="o">=</span> <span class="n">conn</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
+        <span class="n">files</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">conn</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">path</span><span class="p">))</span>
         <span class="k">return</span> <span class="n">files</span></div>
 
+<div class="viewcode-block" id="SFTPHook.mkdir"><a class="viewcode-back" href="../../../../../_api/airflow/providers/sftp/hooks/sftp/index.html#airflow.providers.sftp.hooks.sftp.SFTPHook.mkdir">[docs]</a>    <span class="k">def</span> <span class="nf">mkdir</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">path</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">mode</span><span class="p">:</s [...]
+        <span class="sd">&quot;&quot;&quot;</span>
+<span class="sd">        Creates a directory on the remote system.</span>
+
+<span class="sd">        :param path: full path to the remote directory to create</span>
+<span class="sd">        :param mode: permissions to set the directory with</span>
+<span class="sd">        &quot;&quot;&quot;</span>
+        <span class="n">conn</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_conn</span><span class="p">()</span>
+        <span class="n">conn</span><span class="o">.</span><span class="n">mkdir</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="n">mode</span><span class="o">=</span><span class="nb">int</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">mode</span><span class="p">),</span> <span class="mi">8</span><span class="p">))</span></div>
+
+<div class="viewcode-block" id="SFTPHook.isdir"><a class="viewcode-back" href="../../../../../_api/airflow/providers/sftp/hooks/sftp/index.html#airflow.providers.sftp.hooks.sftp.SFTPHook.isdir">[docs]</a>    <span class="k">def</span> <span class="nf">isdir</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">path</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">b [...]
+        <span class="sd">&quot;&quot;&quot;</span>
+<span class="sd">        Checks if the path provided is a directory or not.</span>
+
+<span class="sd">        :param path: full path to the remote directory to check</span>
+<span class="sd">        &quot;&quot;&quot;</span>
+        <span class="n">conn</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_conn</span><span class="p">()</span>
+        <span class="k">try</span><span class="p">:</span>
+            <span class="n">result</span> <span class="o">=</span> <span class="n">stat</span><span class="o">.</span><span class="n">S_ISDIR</span><span class="p">(</span><span class="n">conn</span><span class="o">.</span><span class="n">stat</span><span class="p">(</span><span class="n">path</span><span class="p">)</span><span class="o">.</span><span class="n">st_mode</span><span class="p">)</span>  <span class="c1"># type: ignore</span>
+        <span class="k">except</span> <span class="ne">OSError</span><span class="p">:</span>
+            <span class="n">result</span> <span class="o">=</span> <span class="kc">False</span>
+        <span class="k">return</span> <span class="n">result</span></div>
+
+<div class="viewcode-block" id="SFTPHook.isfile"><a class="viewcode-back" href="../../../../../_api/airflow/providers/sftp/hooks/sftp/index.html#airflow.providers.sftp.hooks.sftp.SFTPHook.isfile">[docs]</a>    <span class="k">def</span> <span class="nf">isfile</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">path</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb [...]
+        <span class="sd">&quot;&quot;&quot;</span>
+<span class="sd">        Checks if the path provided is a file or not.</span>
+
+<span class="sd">        :param path: full path to the remote file to check</span>
+<span class="sd">        &quot;&quot;&quot;</span>
+        <span class="n">conn</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_conn</span><span class="p">()</span>
+        <span class="k">try</span><span class="p">:</span>
+            <span class="n">result</span> <span class="o">=</span> <span class="n">stat</span><span class="o">.</span><span class="n">S_ISREG</span><span class="p">(</span><span class="n">conn</span><span class="o">.</span><span class="n">stat</span><span class="p">(</span><span class="n">path</span><span class="p">)</span><span class="o">.</span><span class="n">st_mode</span><span class="p">)</span>  <span class="c1"># type: ignore</span>
+        <span class="k">except</span> <span class="ne">OSError</span><span class="p">:</span>
+            <span class="n">result</span> <span class="o">=</span> <span class="kc">False</span>
+        <span class="k">return</span> <span class="n">result</span></div>
+
 <div class="viewcode-block" id="SFTPHook.create_directory"><a class="viewcode-back" href="../../../../../_api/airflow/providers/sftp/hooks/sftp/index.html#airflow.providers.sftp.hooks.sftp.SFTPHook.create_directory">[docs]</a>    <span class="k">def</span> <span class="nf">create_directory</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">path</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n [...]
         <span class="sd">&quot;&quot;&quot;</span>
 <span class="sd">        Creates a directory on the remote system.</span>
@@ -793,7 +780,18 @@
 <span class="sd">        :param mode: int representation of octal mode for directory</span>
 <span class="sd">        &quot;&quot;&quot;</span>
         <span class="n">conn</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_conn</span><span class="p">()</span>
-        <span class="n">conn</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="n">mode</span><span class="p">)</span></div>
+        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">path</span><span class="p">):</span>
+            <span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">&quot;</span><span class="si">%s</span><span class="s2"> already exists&quot;</span><span class="p">,</span> <span class="n">path</span><span class="p">)</span>
+            <span class="k">return</span>
+        <span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">isfile</span><span class="p">(</span><span class="n">path</span><span class="p">):</span>
+            <span class="k">raise</span> <span class="n">AirflowException</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="n">path</span><span class="si">}</span><span class="s2"> already exists and is a file&quot;</span><span class="p">)</span>
+        <span class="k">else</span><span class="p">:</span>
+            <span class="n">dirname</span><span class="p">,</span> <span class="n">basename</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
+            <span class="k">if</span> <span class="n">dirname</span> <span class="ow">and</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">dirname</span><span class="p">):</span>
+                <span class="bp">self</span><span class="o">.</span><span class="n">create_directory</span><span class="p">(</span><span class="n">dirname</span><span class="p">,</span> <span class="n">mode</span><span class="p">)</span>
+            <span class="k">if</span> <span class="n">basename</span><span class="p">:</span>
+                <span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">&quot;Creating </span><span class="si">%s</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">path</span><span class="p">)</span>
+                <span class="n">conn</span><span class="o">.</span><span class="n">mkdir</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="n">mode</span><span class="o">=</span><span class="n">mode</span><span class="p">)</span></div>
 
 <div class="viewcode-block" id="SFTPHook.delete_directory"><a class="viewcode-back" href="../../../../../_api/airflow/providers/sftp/hooks/sftp/index.html#airflow.providers.sftp.hooks.sftp.SFTPHook.delete_directory">[docs]</a>    <span class="k">def</span> <span class="nf">delete_directory</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">path</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o [...]
         <span class="sd">&quot;&quot;&quot;</span>
@@ -816,7 +814,7 @@
         <span class="n">conn</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_conn</span><span class="p">()</span>
         <span class="n">conn</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">remote_full_path</span><span class="p">,</span> <span class="n">local_full_path</span><span class="p">)</span></div>
 
-<div class="viewcode-block" id="SFTPHook.store_file"><a class="viewcode-back" href="../../../../../_api/airflow/providers/sftp/hooks/sftp/index.html#airflow.providers.sftp.hooks.sftp.SFTPHook.store_file">[docs]</a>    <span class="k">def</span> <span class="nf">store_file</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">remote_full_path</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">loca [...]
+<div class="viewcode-block" id="SFTPHook.store_file"><a class="viewcode-back" href="../../../../../_api/airflow/providers/sftp/hooks/sftp/index.html#airflow.providers.sftp.hooks.sftp.SFTPHook.store_file">[docs]</a>    <span class="k">def</span> <span class="nf">store_file</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">remote_full_path</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">loca [...]
         <span class="sd">&quot;&quot;&quot;</span>
 <span class="sd">        Transfers a local file to the remote location.</span>
 <span class="sd">        If local_full_path_or_buffer is a string path, the file will be read</span>
@@ -826,7 +824,7 @@
 <span class="sd">        :param local_full_path: full path to the local file</span>
 <span class="sd">        &quot;&quot;&quot;</span>
         <span class="n">conn</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_conn</span><span class="p">()</span>
-        <span class="n">conn</span><span class="o">.</span><span class="n">put</span><span class="p">(</span><span class="n">local_full_path</span><span class="p">,</span> <span class="n">remote_full_path</span><span class="p">)</span></div>
+        <span class="n">conn</span><span class="o">.</span><span class="n">put</span><span class="p">(</span><span class="n">local_full_path</span><span class="p">,</span> <span class="n">remote_full_path</span><span class="p">,</span> <span class="n">confirm</span><span class="o">=</span><span class="n">confirm</span><span class="p">)</span></div>
 
 <div class="viewcode-block" id="SFTPHook.delete_file"><a class="viewcode-back" href="../../../../../_api/airflow/providers/sftp/hooks/sftp/index.html#airflow.providers.sftp.hooks.sftp.SFTPHook.delete_file">[docs]</a>    <span class="k">def</span> <span class="nf">delete_file</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">path</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span>  [...]
         <span class="sd">&quot;&quot;&quot;</span>
@@ -845,7 +843,7 @@
 <span class="sd">        &quot;&quot;&quot;</span>
         <span class="n">conn</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_conn</span><span class="p">()</span>
         <span class="n">ftp_mdtm</span> <span class="o">=</span> <span class="n">conn</span><span class="o">.</span><span class="n">stat</span><span class="p">(</span><span class="n">path</span><span class="p">)</span><span class="o">.</span><span class="n">st_mtime</span>
-        <span class="k">return</span> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">fromtimestamp</span><span class="p">(</span><span class="n">ftp_mdtm</span><span class="p">)</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">&#39;%Y%m</span><span class="si">%d</span><span class="s1">%H%M%S&#39;</span><span class="p">)</span></div>
+        <span class="k">return</span> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">fromtimestamp</span><span class="p">(</span><span class="n">ftp_mdtm</span><span class="p">)</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">&#39;%Y%m</span><span class="si">%d</span><span class="s1">%H%M%S&#39;</span><span class="p">)</span>  <span class="c1"># type: ignor [...]
 
 <div class="viewcode-block" id="SFTPHook.path_exists"><a class="viewcode-back" href="../../../../../_api/airflow/providers/sftp/hooks/sftp/index.html#airflow.providers.sftp.hooks.sftp.SFTPHook.path_exists">[docs]</a>    <span class="k">def</span> <span class="nf">path_exists</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">path</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span>  [...]
         <span class="sd">&quot;&quot;&quot;</span>
@@ -854,7 +852,11 @@
 <span class="sd">        :param path: full path to the remote file or directory</span>
 <span class="sd">        &quot;&quot;&quot;</span>
         <span class="n">conn</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_conn</span><span class="p">()</span>
-        <span class="k">return</span> <span class="n">conn</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">path</span><span class="p">)</span></div>
+        <span class="k">try</span><span class="p">:</span>
+            <span class="n">conn</span><span class="o">.</span><span class="n">stat</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
+        <span class="k">except</span> <span class="ne">OSError</span><span class="p">:</span>
+            <span class="k">return</span> <span class="kc">False</span>
+        <span class="k">return</span> <span class="kc">True</span></div>
 
     <span class="nd">@staticmethod</span>
     <span class="k">def</span> <span class="nf">_is_path_match</span><span class="p">(</span><span class="n">path</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">prefix</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> <span class="n">delimiter</span><span class="p">:</span> [...]
@@ -872,6 +874,51 @@
             <span class="k">return</span> <span class="kc">False</span>
         <span class="k">return</span> <span class="kc">True</span>
 
+<div class="viewcode-block" id="SFTPHook.walktree"><a class="viewcode-back" href="../../../../../_api/airflow/providers/sftp/hooks/sftp/index.html#airflow.providers.sftp.hooks.sftp.SFTPHook.walktree">[docs]</a>    <span class="k">def</span> <span class="nf">walktree</span><span class="p">(</span>
+        <span class="bp">self</span><span class="p">,</span>
+        <span class="n">path</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span>
+        <span class="n">fcallback</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[[</span><span class="nb">str</span><span class="p">],</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Any</span><span class="p">]],</span>
+        <span class="n">dcallback</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[[</span><span class="nb">str</span><span class="p">],</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Any</span><span class="p">]],</span>
+        <span class="n">ucallback</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[[</span><span class="nb">str</span><span class="p">],</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Any</span><span class="p">]],</span>
+        <span class="n">recurse</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">True</span><span class="p">,</span>
+    <span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
+        <span class="sd">&quot;&quot;&quot;</span>
+<span class="sd">        Recursively descend, depth first, the directory tree rooted at</span>
+<span class="sd">        path, calling discreet callback functions for each regular file,</span>
+<span class="sd">        directory and unknown file type.</span>
+
+<span class="sd">        :param str path:</span>
+<span class="sd">            root of remote directory to descend, use &#39;.&#39; to start at</span>
+<span class="sd">            :attr:`.pwd`</span>
+<span class="sd">        :param callable fcallback:</span>
+<span class="sd">            callback function to invoke for a regular file.</span>
+<span class="sd">            (form: ``func(str)``)</span>
+<span class="sd">        :param callable dcallback:</span>
+<span class="sd">            callback function to invoke for a directory. (form: ``func(str)``)</span>
+<span class="sd">        :param callable ucallback:</span>
+<span class="sd">            callback function to invoke for an unknown file type.</span>
+<span class="sd">            (form: ``func(str)``)</span>
+<span class="sd">        :param bool recurse: *Default: True* - should it recurse</span>
+
+<span class="sd">        :returns: None</span>
+<span class="sd">        &quot;&quot;&quot;</span>
+        <span class="n">conn</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_conn</span><span class="p">()</span>
+        <span class="k">for</span> <span class="n">entry</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">list_directory</span><span class="p">(</span><span class="n">path</span><span class="p">):</span>
+            <span class="n">pathname</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="n">entry</span><span class="p">)</span>
+            <span class="n">mode</span> <span class="o">=</span> <span class="n">conn</span><span class="o">.</span><span class="n">stat</span><span class="p">(</span><span class="n">pathname</span><span class="p">)</span><span class="o">.</span><span class="n">st_mode</span>
+            <span class="k">if</span> <span class="n">stat</span><span class="o">.</span><span class="n">S_ISDIR</span><span class="p">(</span><span class="n">mode</span><span class="p">):</span>  <span class="c1"># type: ignore</span>
+                <span class="c1"># It&#39;s a directory, call the dcallback function</span>
+                <span class="n">dcallback</span><span class="p">(</span><span class="n">pathname</span><span class="p">)</span>
+                <span class="k">if</span> <span class="n">recurse</span><span class="p">:</span>
+                    <span class="c1"># now, recurse into it</span>
+                    <span class="bp">self</span><span class="o">.</span><span class="n">walktree</span><span class="p">(</span><span class="n">pathname</span><span class="p">,</span> <span class="n">fcallback</span><span class="p">,</span> <span class="n">dcallback</span><span class="p">,</span> <span class="n">ucallback</span><span class="p">)</span>
+            <span class="k">elif</span> <span class="n">stat</span><span class="o">.</span><span class="n">S_ISREG</span><span class="p">(</span><span class="n">mode</span><span class="p">):</span>  <span class="c1"># type: ignore</span>
+                <span class="c1"># It&#39;s a file, call the fcallback function</span>
+                <span class="n">fcallback</span><span class="p">(</span><span class="n">pathname</span><span class="p">)</span>
+            <span class="k">else</span><span class="p">:</span>
+                <span class="c1"># Unknown file type</span>
+                <span class="n">ucallback</span><span class="p">(</span><span class="n">pathname</span><span class="p">)</span></div>
+
 <div class="viewcode-block" id="SFTPHook.get_tree_map"><a class="viewcode-back" href="../../../../../_api/airflow/providers/sftp/hooks/sftp/index.html#airflow.providers.sftp.hooks.sftp.SFTPHook.get_tree_map">[docs]</a>    <span class="k">def</span> <span class="nf">get_tree_map</span><span class="p">(</span>
         <span class="bp">self</span><span class="p">,</span> <span class="n">path</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">prefix</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> <span class="n">delimiter</span><span class="p">:</span> <span class="n">Optional</span> [...]
     <span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Tuple</span><span class="p">[</span><span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">],</span> <span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">],</span> <span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">]]:</span>
@@ -885,14 +932,15 @@
 <span class="sd">        :return: tuple with list of files, dirs and unknown items</span>
 <span class="sd">        :rtype: Tuple[List[str], List[str], List[str]]</span>
 <span class="sd">        &quot;&quot;&quot;</span>
-        <span class="n">conn</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_conn</span><span class="p">()</span>
-        <span class="n">files</span><span class="p">,</span> <span class="n">dirs</span><span class="p">,</span> <span class="n">unknowns</span> <span class="o">=</span> <span class="p">[],</span> <span class="p">[],</span> <span class="p">[]</span>  <span class="c1"># type: List[str], List[str], List[str]</span>
+        <span class="n">files</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]</span>
+        <span class="n">dirs</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]</span>
+        <span class="n">unknowns</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]</span>
 
-        <span class="k">def</span> <span class="nf">append_matching_path_callback</span><span class="p">(</span><span class="n">list_</span><span class="p">):</span>
+        <span class="k">def</span> <span class="nf">append_matching_path_callback</span><span class="p">(</span><span class="n">list_</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="n">Callable</span><span class="p">:</span>
             <span class="k">return</span> <span class="k">lambda</span> <span class="n">item</span><span class="p">:</span> <span class="n">list_</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_is_path_match</span><span class="p">(</span><span class="n">item</span><span class="p">,</span> <span class="n">pref [...]
 
-        <span class="n">conn</span><span class="o">.</span><span class="n">walktree</span><span class="p">(</span>
-            <span class="n">remotepath</span><span class="o">=</span><span class="n">path</span><span class="p">,</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">walktree</span><span class="p">(</span>
+            <span class="n">path</span><span class="o">=</span><span class="n">path</span><span class="p">,</span>
             <span class="n">fcallback</span><span class="o">=</span><span class="n">append_matching_path_callback</span><span class="p">(</span><span class="n">files</span><span class="p">),</span>
             <span class="n">dcallback</span><span class="o">=</span><span class="n">append_matching_path_callback</span><span class="p">(</span><span class="n">dirs</span><span class="p">),</span>
             <span class="n">ucallback</span><span class="o">=</span><span class="n">append_matching_path_callback</span><span class="p">(</span><span class="n">unknowns</span><span class="p">),</span>
@@ -905,7 +953,7 @@
         <span class="sd">&quot;&quot;&quot;Test the SFTP connection by calling path with directory&quot;&quot;&quot;</span>
         <span class="k">try</span><span class="p">:</span>
             <span class="n">conn</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_conn</span><span class="p">()</span>
-            <span class="n">conn</span><span class="o">.</span><span class="n">pwd</span>
+            <span class="n">conn</span><span class="o">.</span><span class="n">normalize</span><span class="p">(</span><span class="s1">&#39;.&#39;</span><span class="p">)</span>
             <span class="k">return</span> <span class="kc">True</span><span class="p">,</span> <span class="s2">&quot;Connection successfully tested&quot;</span>
         <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
             <span class="k">return</span> <span class="kc">False</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">)</span></div>
@@ -1141,6 +1189,7 @@
         <script data-url_root="../../../../../" id="documentation_options" src="../../../../../_static/documentation_options.js"></script>
         <script src="../../../../../_static/jquery.js"></script>
         <script src="../../../../../_static/underscore.js"></script>
+        <script src="../../../../../_static/_sphinx_javascript_frameworks_compat.js"></script>
         <script src="../../../../../_static/doctools.js"></script>
         <script src="../../../../../_static/clipboard.min.js"></script>
         <script src="../../../../../_static/copybutton.js"></script>
diff --git a/docs/apache-airflow-providers-sftp/stable/_modules/airflow/providers/sftp/operators/sftp.html b/docs/apache-airflow-providers-sftp/4.0.0/_modules/airflow/providers/sftp/operators/sftp.html
similarity index 88%
copy from docs/apache-airflow-providers-sftp/stable/_modules/airflow/providers/sftp/operators/sftp.html
copy to docs/apache-airflow-providers-sftp/4.0.0/_modules/airflow/providers/sftp/operators/sftp.html
index 08ce91990d..5779b1a59b 100644
--- a/docs/apache-airflow-providers-sftp/stable/_modules/airflow/providers/sftp/operators/sftp.html
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_modules/airflow/providers/sftp/operators/sftp.html
@@ -5,7 +5,7 @@
 <!DOCTYPE html>
 <!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
 <!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
-    <html xmlns="http://www.w3.org/1999/xhtml">
+    <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
 <head>
         <meta charset="utf-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1">
@@ -282,7 +282,7 @@
 <div id="docs-version-selector" class="docs-version-selector sidebar__version-selector">
     <a class="dropdown-toggle" href="#" id="versionDropdown" role="button" data-toggle="dropdown" aria-haspopup="true"
        aria-expanded="false">
-        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">3.0.0</span>
+        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">4.0.0</span>
     </a>
     <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
 
@@ -419,7 +419,7 @@
 <div id="docs-version-selector" class="docs-version-selector sidebar__version-selector">
     <a class="dropdown-toggle" href="#" id="versionDropdown" role="button" data-toggle="dropdown" aria-haspopup="true"
        aria-expanded="false">
-        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">3.0.0</span>
+        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">4.0.0</span>
     </a>
     <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
 
@@ -596,16 +596,18 @@
 <span class="c1"># under the License.</span>
 <span class="sd">&quot;&quot;&quot;This module contains SFTP operator.&quot;&quot;&quot;</span>
 <span class="kn">import</span> <span class="nn">os</span>
+<span class="kn">import</span> <span class="nn">warnings</span>
 <span class="kn">from</span> <span class="nn">pathlib</span> <span class="kn">import</span> <span class="n">Path</span>
-<span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Any</span><span class="p">,</span> <span class="n">Sequence</span>
+<span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Any</span><span class="p">,</span> <span class="n">Optional</span><span class="p">,</span> <span class="n">Sequence</span>
 
 <span class="kn">from</span> <span class="nn">airflow.exceptions</span> <span class="kn">import</span> <span class="n">AirflowException</span>
 <span class="kn">from</span> <span class="nn">airflow.models</span> <span class="kn">import</span> <span class="n">BaseOperator</span>
+<span class="kn">from</span> <span class="nn">airflow.providers.sftp.hooks.sftp</span> <span class="kn">import</span> <span class="n">SFTPHook</span>
 <span class="kn">from</span> <span class="nn">airflow.providers.ssh.hooks.ssh</span> <span class="kn">import</span> <span class="n">SSHHook</span>
 
 
 <div class="viewcode-block" id="SFTPOperation"><a class="viewcode-back" href="../../../../../_api/airflow/providers/sftp/operators/sftp/index.html#airflow.providers.sftp.operators.sftp.SFTPOperation">[docs]</a><span class="k">class</span> <span class="nc">SFTPOperation</span><span class="p">:</span>
-    <span class="sd">&quot;&quot;&quot;Operation that can be used with SFTP/&quot;&quot;&quot;</span>
+    <span class="sd">&quot;&quot;&quot;Operation that can be used with SFTP&quot;&quot;&quot;</span>
 
 <div class="viewcode-block" id="SFTPOperation.PUT"><a class="viewcode-back" href="../../../../../_api/airflow/providers/sftp/operators/sftp/index.html#airflow.providers.sftp.operators.sftp.SFTPOperation.PUT">[docs]</a>    <span class="n">PUT</span> <span class="o">=</span> <span class="s1">&#39;put&#39;</span></div>
 <div class="viewcode-block" id="SFTPOperation.GET"><a class="viewcode-back" href="../../../../../_api/airflow/providers/sftp/operators/sftp/index.html#airflow.providers.sftp.operators.sftp.SFTPOperation.GET">[docs]</a>    <span class="n">GET</span> <span class="o">=</span> <span class="s1">&#39;get&#39;</span></div></div>
@@ -614,17 +616,19 @@
 <div class="viewcode-block" id="SFTPOperator"><a class="viewcode-back" href="../../../../../_api/airflow/providers/sftp/operators/sftp/index.html#airflow.providers.sftp.operators.sftp.SFTPOperator">[docs]</a><span class="k">class</span> <span class="nc">SFTPOperator</span><span class="p">(</span><span class="n">BaseOperator</span><span class="p">):</span>
     <span class="sd">&quot;&quot;&quot;</span>
 <span class="sd">    SFTPOperator for transferring files from remote host to local or vice a versa.</span>
-<span class="sd">    This operator uses ssh_hook to open sftp transport channel that serve as basis</span>
+<span class="sd">    This operator uses sftp_hook to open sftp transport channel that serve as basis</span>
 <span class="sd">    for file transfer.</span>
 
-<span class="sd">    :param ssh_hook: predefined ssh_hook to use for remote execution.</span>
-<span class="sd">        Either `ssh_hook` or `ssh_conn_id` needs to be provided.</span>
 <span class="sd">    :param ssh_conn_id: :ref:`ssh connection id&lt;howto/connection:ssh&gt;`</span>
 <span class="sd">        from airflow Connections. `ssh_conn_id` will be ignored if `ssh_hook`</span>
-<span class="sd">        is provided.</span>
+<span class="sd">        or `sftp_hook` is provided.</span>
+<span class="sd">    :param sftp_hook: predefined SFTPHook to use</span>
+<span class="sd">        Either `sftp_hook` or `ssh_conn_id` needs to be provided.</span>
+<span class="sd">    :param ssh_hook: Deprecated - predefined SSHHook to use for remote execution</span>
+<span class="sd">        Use `sftp_hook` instead.</span>
 <span class="sd">    :param remote_host: remote host to connect (templated)</span>
 <span class="sd">        Nullable. If provided, it will replace the `remote_host` which was</span>
-<span class="sd">        defined in `ssh_hook` or predefined in the connection of `ssh_conn_id`.</span>
+<span class="sd">        defined in `sftp_hook`/`ssh_hook` or predefined in the connection of `ssh_conn_id`.</span>
 <span class="sd">    :param local_filepath: local file path to get or put. (templated)</span>
 <span class="sd">    :param remote_filepath: remote file path to get or put. (templated)</span>
 <span class="sd">    :param operation: specify operation &#39;get&#39; or &#39;put&#39;, defaults to put</span>
@@ -654,18 +658,20 @@
     <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span>
         <span class="bp">self</span><span class="p">,</span>
         <span class="o">*</span><span class="p">,</span>
-        <span class="n">ssh_hook</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
-        <span class="n">ssh_conn_id</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
-        <span class="n">remote_host</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
-        <span class="n">local_filepath</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
-        <span class="n">remote_filepath</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
-        <span class="n">operation</span><span class="o">=</span><span class="n">SFTPOperation</span><span class="o">.</span><span class="n">PUT</span><span class="p">,</span>
-        <span class="n">confirm</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
-        <span class="n">create_intermediate_dirs</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
+        <span class="n">ssh_hook</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">SSHHook</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
+        <span class="n">sftp_hook</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">SFTPHook</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
+        <span class="n">ssh_conn_id</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
+        <span class="n">remote_host</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
+        <span class="n">local_filepath</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span>
+        <span class="n">remote_filepath</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span>
+        <span class="n">operation</span><span class="p">:</span> <span class="nb">str</span> <span class="o">=</span> <span class="n">SFTPOperation</span><span class="o">.</span><span class="n">PUT</span><span class="p">,</span>
+        <span class="n">confirm</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">True</span><span class="p">,</span>
+        <span class="n">create_intermediate_dirs</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span>
         <span class="o">**</span><span class="n">kwargs</span><span class="p">,</span>
     <span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
         <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
         <span class="bp">self</span><span class="o">.</span><span class="n">ssh_hook</span> <span class="o">=</span> <span class="n">ssh_hook</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">sftp_hook</span> <span class="o">=</span> <span class="n">sftp_hook</span>
         <span class="bp">self</span><span class="o">.</span><span class="n">ssh_conn_id</span> <span class="o">=</span> <span class="n">ssh_conn_id</span>
         <span class="bp">self</span><span class="o">.</span><span class="n">remote_host</span> <span class="o">=</span> <span class="n">remote_host</span>
         <span class="bp">self</span><span class="o">.</span><span class="n">local_filepath</span> <span class="o">=</span> <span class="n">local_filepath</span>
@@ -673,82 +679,75 @@
         <span class="bp">self</span><span class="o">.</span><span class="n">operation</span> <span class="o">=</span> <span class="n">operation</span>
         <span class="bp">self</span><span class="o">.</span><span class="n">confirm</span> <span class="o">=</span> <span class="n">confirm</span>
         <span class="bp">self</span><span class="o">.</span><span class="n">create_intermediate_dirs</span> <span class="o">=</span> <span class="n">create_intermediate_dirs</span>
+
         <span class="k">if</span> <span class="ow">not</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">operation</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="o">==</span> <span class="n">SFTPOperation</span><span class="o">.</span><span class="n">GET</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">operation</span><span class="o">.</s [...]
             <span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span>
                 <span class="sa">f</span><span class="s2">&quot;Unsupported operation value </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">operation</span><span class="si">}</span><span class="s2">, &quot;</span>
                 <span class="sa">f</span><span class="s2">&quot;expected </span><span class="si">{</span><span class="n">SFTPOperation</span><span class="o">.</span><span class="n">GET</span><span class="si">}</span><span class="s2"> or </span><span class="si">{</span><span class="n">SFTPOperation</span><span class="o">.</span><span class="n">PUT</span><span class="si">}</span><span class="s2">.&quot;</span>
             <span class="p">)</span>
 
-<div class="viewcode-block" id="SFTPOperator.execute"><a class="viewcode-back" href="../../../../../_api/airflow/providers/sftp/operators/sftp/index.html#airflow.providers.sftp.operators.sftp.SFTPOperator.execute">[docs]</a>    <span class="k">def</span> <span class="nf">execute</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">context</span><span class="p">:</span> <span class="n">Any</span><span class="p">)</span> <span class="o">-&gt;</ [...]
+        <span class="c1"># TODO: remove support for ssh_hook in next major provider version in hook and operator</span>
+        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">ssh_hook</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">sftp_hook</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
+            <span class="k">raise</span> <span class="n">AirflowException</span><span class="p">(</span>
+                <span class="s1">&#39;Both `ssh_hook` and `sftp_hook` are defined. Please use only one of them.&#39;</span>
+            <span class="p">)</span>
+
+        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">ssh_hook</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
+            <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">ssh_hook</span><span class="p">,</span> <span class="n">SSHHook</span><span class="p">):</span>
+                <span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s1">&#39;ssh_hook is invalid. Trying ssh_conn_id to create SFTPHook.&#39;</span><span class="p">)</span>
+                <span class="bp">self</span><span class="o">.</span><span class="n">sftp_hook</span> <span class="o">=</span> <span class="n">SFTPHook</span><span class="p">(</span><span class="n">ssh_conn_id</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">ssh_conn_id</span><span class="p">)</span>
+            <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">sftp_hook</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
+                <span class="n">warnings</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span>
+                    <span class="s1">&#39;Parameter `ssh_hook` is deprecated&#39;</span>
+                    <span class="s1">&#39;Please use `sftp_hook` instead.&#39;</span>
+                    <span class="s1">&#39;The old parameter `ssh_hook` will be removed in a future version.&#39;</span><span class="p">,</span>
+                    <span class="ne">DeprecationWarning</span><span class="p">,</span>
+                    <span class="n">stacklevel</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span>
+                <span class="p">)</span>
+                <span class="bp">self</span><span class="o">.</span><span class="n">sftp_hook</span> <span class="o">=</span> <span class="n">SFTPHook</span><span class="p">(</span><span class="n">ssh_hook</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">ssh_hook</span><span class="p">)</span>
+
+<div class="viewcode-block" id="SFTPOperator.execute"><a class="viewcode-back" href="../../../../../_api/airflow/providers/sftp/operators/sftp/index.html#airflow.providers.sftp.operators.sftp.SFTPOperator.execute">[docs]</a>    <span class="k">def</span> <span class="nf">execute</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">context</span><span class="p">:</span> <span class="n">Any</span><span class="p">)</span> <span class="o">-&gt;</ [...]
         <span class="n">file_msg</span> <span class="o">=</span> <span class="kc">None</span>
         <span class="k">try</span><span class="p">:</span>
             <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">ssh_conn_id</span><span class="p">:</span>
-                <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">ssh_hook</span> <span class="ow">and</span> <span class="nb">isinstance</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">ssh_hook</span><span class="p">,</span> <span class="n">SSHHook</span><span class="p">):</span>
-                    <span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">&quot;ssh_conn_id is ignored when ssh_hook is provided.&quot;</span><span class="p">)</span>
+                <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">sftp_hook</span> <span class="ow">and</span> <span class="nb">isinstance</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">sftp_hook</span><span class="p">,</span> <span class="n">SFTPHook</span><span class="p">):</span>
+                    <span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">&quot;ssh_conn_id is ignored when sftp_hook/ssh_hook is provided.&quot;</span><span class="p">)</span>
                 <span class="k">else</span><span class="p">:</span>
                     <span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">info</span><span class="p">(</span>
-                        <span class="s2">&quot;ssh_hook is not provided or invalid. Trying ssh_conn_id to create SSHHook.&quot;</span>
+                        <span class="s1">&#39;sftp_hook/ssh_hook not provided or invalid. Trying ssh_conn_id to create SFTPHook.&#39;</span>
                     <span class="p">)</span>
-                    <span class="bp">self</span><span class="o">.</span><span class="n">ssh_hook</span> <span class="o">=</span> <span class="n">SSHHook</span><span class="p">(</span><span class="n">ssh_conn_id</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">ssh_conn_id</span><span class="p">)</span>
+                    <span class="bp">self</span><span class="o">.</span><span class="n">sftp_hook</span> <span class="o">=</span> <span class="n">SFTPHook</span><span class="p">(</span><span class="n">ssh_conn_id</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">ssh_conn_id</span><span class="p">)</span>
 
-            <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">ssh_hook</span><span class="p">:</span>
-                <span class="k">raise</span> <span class="n">AirflowException</span><span class="p">(</span><span class="s2">&quot;Cannot operate without ssh_hook or ssh_conn_id.&quot;</span><span class="p">)</span>
+            <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">sftp_hook</span><span class="p">:</span>
+                <span class="k">raise</span> <span class="n">AirflowException</span><span class="p">(</span><span class="s2">&quot;Cannot operate without sftp_hook or ssh_conn_id.&quot;</span><span class="p">)</span>
 
             <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">remote_host</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
                 <span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">info</span><span class="p">(</span>
                     <span class="s2">&quot;remote_host is provided explicitly. &quot;</span>
                     <span class="s2">&quot;It will replace the remote_host which was defined &quot;</span>
-                    <span class="s2">&quot;in ssh_hook or predefined in connection of ssh_conn_id.&quot;</span>
+                    <span class="s2">&quot;in sftp_hook or predefined in connection of ssh_conn_id.&quot;</span>
                 <span class="p">)</span>
-                <span class="bp">self</span><span class="o">.</span><span class="n">ssh_hook</span><span class="o">.</span><span class="n">remote_host</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">remote_host</span>
-
-            <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">ssh_hook</span><span class="o">.</span><span class="n">get_conn</span><span class="p">()</span> <span class="k">as</span> <span class="n">ssh_client</span><span class="p">:</span>
-                <span class="n">sftp_client</span> <span class="o">=</span> <span class="n">ssh_client</span><span class="o">.</span><span class="n">open_sftp</span><span class="p">()</span>
-                <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">operation</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="o">==</span> <span class="n">SFTPOperation</span><span class="o">.</span><span class="n">GET</span><span class="p">:</span>
-                    <span class="n">local_folder</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">local_filepath</span><span class="p">)</span>
-                    <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">create_intermediate_dirs</span><span class="p">:</span>
-                        <span class="n">Path</span><span class="p">(</span><span class="n">local_folder</span><span class="p">)</span><span class="o">.</span><span class="n">mkdir</span><span class="p">(</span><span class="n">parents</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">exist_ok</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
-                    <span class="n">file_msg</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&quot;from </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">remote_filepath</span><span class="si">}</span><span class="s2"> to </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">local_filepath</span><span class="si">}</span><span class="s2">&quot;</span>
-                    <span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">&quot;Starting to transfer </span><span class="si">%s</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">file_msg</span><span class="p">)</span>
-                    <span class="n">sftp_client</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">remote_filepath</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">local_filepath</span><span class="p">)</span>
-                <span class="k">else</span><span class="p">:</span>
-                    <span class="n">remote_folder</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">remote_filepath</span><span class="p">)</span>
-                    <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">create_intermediate_dirs</span><span class="p">:</span>
-                        <span class="n">_make_intermediate_dirs</span><span class="p">(</span>
-                            <span class="n">sftp_client</span><span class="o">=</span><span class="n">sftp_client</span><span class="p">,</span>
-                            <span class="n">remote_directory</span><span class="o">=</span><span class="n">remote_folder</span><span class="p">,</span>
-                        <span class="p">)</span>
-                    <span class="n">file_msg</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&quot;from </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">local_filepath</span><span class="si">}</span><span class="s2"> to </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">remote_filepath</span><span class="si">}</span><span class="s2">&quot;</span>
-                    <span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">&quot;Starting to transfer file </span><span class="si">%s</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">file_msg</span><span class="p">)</span>
-                    <span class="n">sftp_client</span><span class="o">.</span><span class="n">put</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">local_filepath</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">remote_filepath</span><span class="p">,</span> <span class="n">confirm</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">confirm</span [...]
+                <span class="bp">self</span><span class="o">.</span><span class="n">sftp_hook</span><span class="o">.</span><span class="n">remote_host</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">remote_host</span>
+
+            <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">operation</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="o">==</span> <span class="n">SFTPOperation</span><span class="o">.</span><span class="n">GET</span><span class="p">:</span>
+                <span class="n">local_folder</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">local_filepath</span><span class="p">)</span>
+                <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">create_intermediate_dirs</span><span class="p">:</span>
+                    <span class="n">Path</span><span class="p">(</span><span class="n">local_folder</span><span class="p">)</span><span class="o">.</span><span class="n">mkdir</span><span class="p">(</span><span class="n">parents</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">exist_ok</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
+                <span class="n">file_msg</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&quot;from </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">remote_filepath</span><span class="si">}</span><span class="s2"> to </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">local_filepath</span><span class="si">}</span><span class="s2">&quot;</span>
+                <span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">&quot;Starting to transfer </span><span class="si">%s</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">file_msg</span><span class="p">)</span>
+                <span class="bp">self</span><span class="o">.</span><span class="n">sftp_hook</span><span class="o">.</span><span class="n">retrieve_file</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">remote_filepath</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">local_filepath</span><span class="p">)</span>
+            <span class="k">else</span><span class="p">:</span>
+                <span class="n">remote_folder</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">remote_filepath</span><span class="p">)</span>
+                <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">create_intermediate_dirs</span><span class="p">:</span>
+                    <span class="bp">self</span><span class="o">.</span><span class="n">sftp_hook</span><span class="o">.</span><span class="n">create_directory</span><span class="p">(</span><span class="n">remote_folder</span><span class="p">)</span>
+                <span class="n">file_msg</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&quot;from </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">local_filepath</span><span class="si">}</span><span class="s2"> to </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">remote_filepath</span><span class="si">}</span><span class="s2">&quot;</span>
+                <span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">&quot;Starting to transfer file </span><span class="si">%s</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">file_msg</span><span class="p">)</span>
+                <span class="bp">self</span><span class="o">.</span><span class="n">sftp_hook</span><span class="o">.</span><span class="n">store_file</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">remote_filepath</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">local_filepath</span><span class="p">,</span> <span class="n">confirm</span><span class="o">=</span><span class="bp">self</span> [...]
 
         <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
             <span class="k">raise</span> <span class="n">AirflowException</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Error while transferring </span><span class="si">{</span><span class="n">file_msg</span><span class="si">}</span><span class="s2">, error: </span><span class="si">{</span><span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="si">}</span><span class="s2">&quot;</span><span class="p" [...]
 
         <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">local_filepath</span></div></div>
-
-
-<span class="k">def</span> <span class="nf">_make_intermediate_dirs</span><span class="p">(</span><span class="n">sftp_client</span><span class="p">,</span> <span class="n">remote_directory</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
-    <span class="sd">&quot;&quot;&quot;</span>
-<span class="sd">    Create all the intermediate directories in a remote host</span>
-
-<span class="sd">    :param sftp_client: A Paramiko SFTP client.</span>
-<span class="sd">    :param remote_directory: Absolute Path of the directory containing the file</span>
-<span class="sd">    :return:</span>
-<span class="sd">    &quot;&quot;&quot;</span>
-    <span class="k">if</span> <span class="n">remote_directory</span> <span class="o">==</span> <span class="s1">&#39;/&#39;</span><span class="p">:</span>
-        <span class="n">sftp_client</span><span class="o">.</span><span class="n">chdir</span><span class="p">(</span><span class="s1">&#39;/&#39;</span><span class="p">)</span>
-        <span class="k">return</span>
-    <span class="k">if</span> <span class="n">remote_directory</span> <span class="o">==</span> <span class="s1">&#39;&#39;</span><span class="p">:</span>
-        <span class="k">return</span>
-    <span class="k">try</span><span class="p">:</span>
-        <span class="n">sftp_client</span><span class="o">.</span><span class="n">chdir</span><span class="p">(</span><span class="n">remote_directory</span><span class="p">)</span>
-    <span class="k">except</span> <span class="ne">OSError</span><span class="p">:</span>
-        <span class="n">dirname</span><span class="p">,</span> <span class="n">basename</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">remote_directory</span><span class="o">.</span><span class="n">rstrip</span><span class="p">(</span><span class="s1">&#39;/&#39;</span><span class="p">))</span>
-        <span class="n">_make_intermediate_dirs</span><span class="p">(</span><span class="n">sftp_client</span><span class="p">,</span> <span class="n">dirname</span><span class="p">)</span>
-        <span class="n">sftp_client</span><span class="o">.</span><span class="n">mkdir</span><span class="p">(</span><span class="n">basename</span><span class="p">)</span>
-        <span class="n">sftp_client</span><span class="o">.</span><span class="n">chdir</span><span class="p">(</span><span class="n">basename</span><span class="p">)</span>
-        <span class="k">return</span>
 </pre></div>
 
     <div class="pager" role="navigation" aria-label="related navigation"><button class="btn-hollow btn-blue bodytext__medium--cerulean-blue" disabled>Previous</button><button class="btn-hollow btn-blue bodytext__medium--cerulean-blue" disabled>Next</button>
@@ -963,6 +962,7 @@
         <script data-url_root="../../../../../" id="documentation_options" src="../../../../../_static/documentation_options.js"></script>
         <script src="../../../../../_static/jquery.js"></script>
         <script src="../../../../../_static/underscore.js"></script>
+        <script src="../../../../../_static/_sphinx_javascript_frameworks_compat.js"></script>
         <script src="../../../../../_static/doctools.js"></script>
         <script src="../../../../../_static/clipboard.min.js"></script>
         <script src="../../../../../_static/copybutton.js"></script>
diff --git a/docs/apache-airflow-providers-sftp/stable/_modules/airflow/providers/sftp/sensors/sftp.html b/docs/apache-airflow-providers-sftp/4.0.0/_modules/airflow/providers/sftp/sensors/sftp.html
similarity index 98%
copy from docs/apache-airflow-providers-sftp/stable/_modules/airflow/providers/sftp/sensors/sftp.html
copy to docs/apache-airflow-providers-sftp/4.0.0/_modules/airflow/providers/sftp/sensors/sftp.html
index a725d71a80..0f558d3900 100644
--- a/docs/apache-airflow-providers-sftp/stable/_modules/airflow/providers/sftp/sensors/sftp.html
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_modules/airflow/providers/sftp/sensors/sftp.html
@@ -5,7 +5,7 @@
 <!DOCTYPE html>
 <!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
 <!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
-    <html xmlns="http://www.w3.org/1999/xhtml">
+    <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
 <head>
         <meta charset="utf-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1">
@@ -282,7 +282,7 @@
 <div id="docs-version-selector" class="docs-version-selector sidebar__version-selector">
     <a class="dropdown-toggle" href="#" id="versionDropdown" role="button" data-toggle="dropdown" aria-haspopup="true"
        aria-expanded="false">
-        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">3.0.0</span>
+        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">4.0.0</span>
     </a>
     <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
 
@@ -419,7 +419,7 @@
 <div id="docs-version-selector" class="docs-version-selector sidebar__version-selector">
     <a class="dropdown-toggle" href="#" id="versionDropdown" role="button" data-toggle="dropdown" aria-haspopup="true"
        aria-expanded="false">
-        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">3.0.0</span>
+        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">4.0.0</span>
     </a>
     <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
 
@@ -638,22 +638,23 @@
         <span class="bp">self</span><span class="o">.</span><span class="n">hook</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">SFTPHook</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
         <span class="bp">self</span><span class="o">.</span><span class="n">sftp_conn_id</span> <span class="o">=</span> <span class="n">sftp_conn_id</span>
         <span class="bp">self</span><span class="o">.</span><span class="n">newer_than</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">datetime</span><span class="p">]</span> <span class="o">=</span> <span class="n">newer_than</span>
-        <span class="bp">self</span><span class="o">.</span><span class="n">actual_file_to_check</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">path</span>
 
 <div class="viewcode-block" id="SFTPSensor.poke"><a class="viewcode-back" href="../../../../../_api/airflow/providers/sftp/sensors/sftp/index.html#airflow.providers.sftp.sensors.sftp.SFTPSensor.poke">[docs]</a>    <span class="k">def</span> <span class="nf">poke</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">context</span><span class="p">:</span> <span class="s1">&#39;Context&#39;</span><span class="p">)</span> <span class="o">-&gt;</sp [...]
         <span class="bp">self</span><span class="o">.</span><span class="n">hook</span> <span class="o">=</span> <span class="n">SFTPHook</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">sftp_conn_id</span><span class="p">)</span>
-        <span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Poking for </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">path</span><span class="si">}</span><span class="s2">, with pattern </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">file [...]
+        <span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">&quot;Poking for </span><span class="si">%s</span><span class="s2">, with pattern </span><span class="si">%s</span><span class="s2">&quot;</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">path</span><span class="p">,</span> <span class="bp">self</span><span class= [...]
 
         <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">file_pattern</span><span class="p">:</span>
             <span class="n">file_from_pattern</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">hook</span><span class="o">.</span><span class="n">get_file_by_pattern</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">path</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">file_pattern</span><span class="p">)</span>
             <span class="k">if</span> <span class="n">file_from_pattern</span><span class="p">:</span>
-                <span class="bp">self</span><span class="o">.</span><span class="n">actual_file_to_check</span> <span class="o">=</span> <span class="n">file_from_pattern</span>
+                <span class="n">actual_file_to_check</span> <span class="o">=</span> <span class="n">file_from_pattern</span>
             <span class="k">else</span><span class="p">:</span>
                 <span class="k">return</span> <span class="kc">False</span>
+        <span class="k">else</span><span class="p">:</span>
+            <span class="n">actual_file_to_check</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">path</span>
 
         <span class="k">try</span><span class="p">:</span>
-            <span class="n">mod_time</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">hook</span><span class="o">.</span><span class="n">get_mod_time</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">actual_file_to_check</span><span class="p">)</span>
-            <span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s1">&#39;Found File </span><span class="si">%s</span><span class="s1"> last modified: </span><span class="si">%s</span><span class="s1">&#39;</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">actual_file_to_check</ [...]
+            <span class="n">mod_time</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">hook</span><span class="o">.</span><span class="n">get_mod_time</span><span class="p">(</span><span class="n">actual_file_to_check</span><span class="p">)</span>
+            <span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s1">&#39;Found File </span><span class="si">%s</span><span class="s1"> last modified: </span><span class="si">%s</span><span class="s1">&#39;</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="n">actual_file_to_check</span><span class="p">),</span> <span class="nb">str< [...]
         <span class="k">except</span> <span class="ne">OSError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
             <span class="k">if</span> <span class="n">e</span><span class="o">.</span><span class="n">errno</span> <span class="o">!=</span> <span class="n">SFTP_NO_SUCH_FILE</span><span class="p">:</span>
                 <span class="k">raise</span> <span class="n">e</span>
@@ -879,6 +880,7 @@
         <script data-url_root="../../../../../" id="documentation_options" src="../../../../../_static/documentation_options.js"></script>
         <script src="../../../../../_static/jquery.js"></script>
         <script src="../../../../../_static/underscore.js"></script>
+        <script src="../../../../../_static/_sphinx_javascript_frameworks_compat.js"></script>
         <script src="../../../../../_static/doctools.js"></script>
         <script src="../../../../../_static/clipboard.min.js"></script>
         <script src="../../../../../_static/copybutton.js"></script>
diff --git a/docs/apache-airflow-providers-sftp/stable/_modules/index.html b/docs/apache-airflow-providers-sftp/4.0.0/_modules/index.html
similarity index 99%
copy from docs/apache-airflow-providers-sftp/stable/_modules/index.html
copy to docs/apache-airflow-providers-sftp/4.0.0/_modules/index.html
index c41180f46e..1b2ee4860f 100644
--- a/docs/apache-airflow-providers-sftp/stable/_modules/index.html
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_modules/index.html
@@ -5,7 +5,7 @@
 <!DOCTYPE html>
 <!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
 <!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
-    <html xmlns="http://www.w3.org/1999/xhtml">
+    <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
 <head>
         <meta charset="utf-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1">
@@ -282,7 +282,7 @@
 <div id="docs-version-selector" class="docs-version-selector sidebar__version-selector">
     <a class="dropdown-toggle" href="#" id="versionDropdown" role="button" data-toggle="dropdown" aria-haspopup="true"
        aria-expanded="false">
-        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">3.0.0</span>
+        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">4.0.0</span>
     </a>
     <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
 
@@ -419,7 +419,7 @@
 <div id="docs-version-selector" class="docs-version-selector sidebar__version-selector">
     <a class="dropdown-toggle" href="#" id="versionDropdown" role="button" data-toggle="dropdown" aria-haspopup="true"
        aria-expanded="false">
-        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">3.0.0</span>
+        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">4.0.0</span>
     </a>
     <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
 
@@ -792,6 +792,7 @@
         <script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
         <script src="../_static/jquery.js"></script>
         <script src="../_static/underscore.js"></script>
+        <script src="../_static/_sphinx_javascript_frameworks_compat.js"></script>
         <script src="../_static/doctools.js"></script>
         <script src="../_static/clipboard.min.js"></script>
         <script src="../_static/copybutton.js"></script>
diff --git a/docs/apache-airflow-providers-sftp/4.0.0/_sources/_api/airflow/providers/sftp/hooks/index.rst.txt b/docs/apache-airflow-providers-sftp/4.0.0/_sources/_api/airflow/providers/sftp/hooks/index.rst.txt
new file mode 100644
index 0000000000..14e0a11f07
--- /dev/null
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_sources/_api/airflow/providers/sftp/hooks/index.rst.txt
@@ -0,0 +1,15 @@
+:py:mod:`airflow.providers.sftp.hooks`
+======================================
+
+.. py:module:: airflow.providers.sftp.hooks
+
+
+Submodules
+----------
+.. toctree::
+   :titlesonly:
+   :maxdepth: 1
+
+   sftp/index.rst
+
+
diff --git a/docs/apache-airflow-providers-sftp/stable/_sources/_api/airflow/providers/sftp/hooks/sftp/index.rst.txt b/docs/apache-airflow-providers-sftp/4.0.0/_sources/_api/airflow/providers/sftp/hooks/sftp/index.rst.txt
similarity index 72%
copy from docs/apache-airflow-providers-sftp/stable/_sources/_api/airflow/providers/sftp/hooks/sftp/index.rst.txt
copy to docs/apache-airflow-providers-sftp/4.0.0/_sources/_api/airflow/providers/sftp/hooks/sftp/index.rst.txt
index 3a076ab96c..94c97cd69d 100644
--- a/docs/apache-airflow-providers-sftp/stable/_sources/_api/airflow/providers/sftp/hooks/sftp/index.rst.txt
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_sources/_api/airflow/providers/sftp/hooks/sftp/index.rst.txt
@@ -22,7 +22,7 @@ Classes
 
 
 
-.. py:class:: SFTPHook(ssh_conn_id = 'sftp_default', *args, **kwargs)
+.. py:class:: SFTPHook(ssh_conn_id = 'sftp_default', ssh_hook = None, *args, **kwargs)
 
    Bases: :py:obj:`airflow.providers.ssh.hooks.ssh.SSHHook`
 
@@ -44,11 +44,9 @@ Classes
    Errors that may occur throughout but should be handled downstream.
 
    For consistency reasons with SSHHook, the preferred parameter is "ssh_conn_id".
-   Please note that it is still possible to use the parameter "ftp_conn_id"
-   to initialize the hook, but it will be removed in future Airflow versions.
 
    :param ssh_conn_id: The :ref:`sftp connection id<howto/connection:sftp>`
-   :param ftp_conn_id (Outdated): The :ref:`sftp connection id<howto/connection:sftp>`
+   :param ssh_hook: Optional SSH hook (included to support passing of an SSH hook to the SFTP operator)
 
    .. py:attribute:: conn_name_attr
       :annotation: = ssh_conn_id
@@ -78,12 +76,14 @@ Classes
 
    .. py:method:: get_conn(self)
 
-      Returns an SFTP connection object
+      Opens an SFTP connection to the remote host
+
+      :rtype: paramiko.SFTPClient
 
 
    .. py:method:: close_conn(self)
 
-      Closes the connection
+      Closes the SFTP connection
 
 
    .. py:method:: describe_directory(self, path)
@@ -101,6 +101,28 @@ Classes
       :param path: full path to the remote directory to list
 
 
+   .. py:method:: mkdir(self, path, mode = 777)
+
+      Creates a directory on the remote system.
+
+      :param path: full path to the remote directory to create
+      :param mode: permissions to set the directory with
+
+
+   .. py:method:: isdir(self, path)
+
+      Checks if the path provided is a directory or not.
+
+      :param path: full path to the remote directory to check
+
+
+   .. py:method:: isfile(self, path)
+
+      Checks if the path provided is a file or not.
+
+      :param path: full path to the remote file to check
+
+
    .. py:method:: create_directory(self, path, mode = 777)
 
       Creates a directory on the remote system.
@@ -126,7 +148,7 @@ Classes
       :param local_full_path: full path to the local file
 
 
-   .. py:method:: store_file(self, remote_full_path, local_full_path)
+   .. py:method:: store_file(self, remote_full_path, local_full_path, confirm = True)
 
       Transfers a local file to the remote location.
       If local_full_path_or_buffer is a string path, the file will be read
@@ -157,6 +179,28 @@ Classes
       :param path: full path to the remote file or directory
 
 
+   .. py:method:: walktree(self, path, fcallback, dcallback, ucallback, recurse = True)
+
+      Recursively descend, depth first, the directory tree rooted at
+      path, calling discreet callback functions for each regular file,
+      directory and unknown file type.
+
+      :param str path:
+          root of remote directory to descend, use '.' to start at
+          :attr:`.pwd`
+      :param callable fcallback:
+          callback function to invoke for a regular file.
+          (form: ``func(str)``)
+      :param callable dcallback:
+          callback function to invoke for a directory. (form: ``func(str)``)
+      :param callable ucallback:
+          callback function to invoke for an unknown file type.
+          (form: ``func(str)``)
+      :param bool recurse: *Default: True* - should it recurse
+
+      :returns: None
+
+
    .. py:method:: get_tree_map(self, path, prefix = None, delimiter = None)
 
       Return tuple with recursive lists of files, directories and unknown paths from given path.
diff --git a/docs/apache-airflow-providers-sftp/4.0.0/_sources/_api/airflow/providers/sftp/index.rst.txt b/docs/apache-airflow-providers-sftp/4.0.0/_sources/_api/airflow/providers/sftp/index.rst.txt
new file mode 100644
index 0000000000..93f6f3fe80
--- /dev/null
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_sources/_api/airflow/providers/sftp/index.rst.txt
@@ -0,0 +1,17 @@
+:py:mod:`airflow.providers.sftp`
+================================
+
+.. py:module:: airflow.providers.sftp
+
+
+Subpackages
+-----------
+.. toctree::
+   :titlesonly:
+   :maxdepth: 3
+
+   hooks/index.rst
+   operators/index.rst
+   sensors/index.rst
+
+
diff --git a/docs/apache-airflow-providers-sftp/4.0.0/_sources/_api/airflow/providers/sftp/operators/index.rst.txt b/docs/apache-airflow-providers-sftp/4.0.0/_sources/_api/airflow/providers/sftp/operators/index.rst.txt
new file mode 100644
index 0000000000..7a940ddcdf
--- /dev/null
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_sources/_api/airflow/providers/sftp/operators/index.rst.txt
@@ -0,0 +1,15 @@
+:py:mod:`airflow.providers.sftp.operators`
+==========================================
+
+.. py:module:: airflow.providers.sftp.operators
+
+
+Submodules
+----------
+.. toctree::
+   :titlesonly:
+   :maxdepth: 1
+
+   sftp/index.rst
+
+
diff --git a/docs/apache-airflow-providers-sftp/stable/_sources/_api/airflow/providers/sftp/operators/sftp/index.rst.txt b/docs/apache-airflow-providers-sftp/4.0.0/_sources/_api/airflow/providers/sftp/operators/sftp/index.rst.txt
similarity index 77%
copy from docs/apache-airflow-providers-sftp/stable/_sources/_api/airflow/providers/sftp/operators/sftp/index.rst.txt
copy to docs/apache-airflow-providers-sftp/4.0.0/_sources/_api/airflow/providers/sftp/operators/sftp/index.rst.txt
index a0fee5d159..4589c6f1bc 100644
--- a/docs/apache-airflow-providers-sftp/stable/_sources/_api/airflow/providers/sftp/operators/sftp/index.rst.txt
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_sources/_api/airflow/providers/sftp/operators/sftp/index.rst.txt
@@ -25,7 +25,7 @@ Classes
 
 .. py:class:: SFTPOperation
 
-   Operation that can be used with SFTP/
+   Operation that can be used with SFTP
 
    .. py:attribute:: PUT
       :annotation: = put
@@ -38,22 +38,24 @@ Classes
       
 
 
-.. py:class:: SFTPOperator(*, ssh_hook=None, ssh_conn_id=None, remote_host=None, local_filepath=None, remote_filepath=None, operation=SFTPOperation.PUT, confirm=True, create_intermediate_dirs=False, **kwargs)
+.. py:class:: SFTPOperator(*, ssh_hook = None, sftp_hook = None, ssh_conn_id = None, remote_host = None, local_filepath, remote_filepath, operation = SFTPOperation.PUT, confirm = True, create_intermediate_dirs = False, **kwargs)
 
    Bases: :py:obj:`airflow.models.BaseOperator`
 
    SFTPOperator for transferring files from remote host to local or vice a versa.
-   This operator uses ssh_hook to open sftp transport channel that serve as basis
+   This operator uses sftp_hook to open sftp transport channel that serve as basis
    for file transfer.
 
-   :param ssh_hook: predefined ssh_hook to use for remote execution.
-       Either `ssh_hook` or `ssh_conn_id` needs to be provided.
    :param ssh_conn_id: :ref:`ssh connection id<howto/connection:ssh>`
        from airflow Connections. `ssh_conn_id` will be ignored if `ssh_hook`
-       is provided.
+       or `sftp_hook` is provided.
+   :param sftp_hook: predefined SFTPHook to use
+       Either `sftp_hook` or `ssh_conn_id` needs to be provided.
+   :param ssh_hook: Deprecated - predefined SSHHook to use for remote execution
+       Use `sftp_hook` instead.
    :param remote_host: remote host to connect (templated)
        Nullable. If provided, it will replace the `remote_host` which was
-       defined in `ssh_hook` or predefined in the connection of `ssh_conn_id`.
+       defined in `sftp_hook`/`ssh_hook` or predefined in the connection of `ssh_conn_id`.
    :param local_filepath: local file path to get or put. (templated)
    :param remote_filepath: remote file path to get or put. (templated)
    :param operation: specify operation 'get' or 'put', defaults to put
diff --git a/docs/apache-airflow-providers-sftp/4.0.0/_sources/_api/airflow/providers/sftp/sensors/index.rst.txt b/docs/apache-airflow-providers-sftp/4.0.0/_sources/_api/airflow/providers/sftp/sensors/index.rst.txt
new file mode 100644
index 0000000000..c130339768
--- /dev/null
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_sources/_api/airflow/providers/sftp/sensors/index.rst.txt
@@ -0,0 +1,15 @@
+:py:mod:`airflow.providers.sftp.sensors`
+========================================
+
+.. py:module:: airflow.providers.sftp.sensors
+
+
+Submodules
+----------
+.. toctree::
+   :titlesonly:
+   :maxdepth: 1
+
+   sftp/index.rst
+
+
diff --git a/docs/apache-airflow-providers-sftp/4.0.0/_sources/_api/airflow/providers/sftp/sensors/sftp/index.rst.txt b/docs/apache-airflow-providers-sftp/4.0.0/_sources/_api/airflow/providers/sftp/sensors/sftp/index.rst.txt
new file mode 100644
index 0000000000..1c53d8ce52
--- /dev/null
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_sources/_api/airflow/providers/sftp/sensors/sftp/index.rst.txt
@@ -0,0 +1,47 @@
+:py:mod:`airflow.providers.sftp.sensors.sftp`
+=============================================
+
+.. py:module:: airflow.providers.sftp.sensors.sftp
+
+.. autoapi-nested-parse::
+
+   This module contains SFTP sensor.
+
+
+
+Module Contents
+---------------
+
+Classes
+~~~~~~~
+
+.. autoapisummary::
+
+   airflow.providers.sftp.sensors.sftp.SFTPSensor
+
+
+
+
+.. py:class:: SFTPSensor(*, path, file_pattern = '', newer_than = None, sftp_conn_id = 'sftp_default', **kwargs)
+
+   Bases: :py:obj:`airflow.sensors.base.BaseSensorOperator`
+
+   Waits for a file or directory to be present on SFTP.
+
+   :param path: Remote file or directory path
+   :param file_pattern: The pattern that will be used to match the file (fnmatch format)
+   :param sftp_conn_id: The connection to run the sensor against
+   :param newer_than: DateTime for which the file or file path should be newer than, comparison is inclusive
+
+   .. py:attribute:: template_fields
+      :annotation: :Sequence[str] = ['path', 'newer_than']
+
+      
+
+   .. py:method:: poke(self, context)
+
+      Function that the sensors defined while deriving this class should
+      override.
+
+
+
diff --git a/docs/apache-airflow-providers-sftp/stable/_sources/commits.rst.txt b/docs/apache-airflow-providers-sftp/4.0.0/_sources/commits.rst.txt
similarity index 93%
copy from docs/apache-airflow-providers-sftp/stable/_sources/commits.rst.txt
copy to docs/apache-airflow-providers-sftp/4.0.0/_sources/commits.rst.txt
index d103ef1220..ba189ef1dd 100644
--- a/docs/apache-airflow-providers-sftp/stable/_sources/commits.rst.txt
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_sources/commits.rst.txt
@@ -28,14 +28,31 @@ For high-level changelog, see :doc:`package information including changelog <ind
 
 
 
+4.0.0
+.....
+
+Latest change: 2022-07-13
+
+=================================================================================================  ===========  ===========================================================================
+Commit                                                                                             Committed    Subject
+=================================================================================================  ===========  ===========================================================================
+`d2459a241b <https://github.com/apache/airflow/commit/d2459a241b54d596ebdb9d81637400279fff4f2d>`_  2022-07-13   ``Add documentation for July 2022 Provider's release (#25030)``
+`acaa0635c8 <https://github.com/apache/airflow/commit/acaa0635c8477c98ab78da9f6d86e6f1bad2737d>`_  2022-07-08   ``Automatically detect if non-lazy logging interpolation is used (#24910)``
+`0de31bd73a <https://github.com/apache/airflow/commit/0de31bd73a8f41dded2907f0dee59dfa6c1ed7a1>`_  2022-06-29   ``Move provider dependencies to inside provider folders (#24672)``
+`510a6bab45 <https://github.com/apache/airflow/commit/510a6bab4595cce8bd5b1447db957309d70f35d9>`_  2022-06-28   ``Remove 'hook-class-names' from provider.yaml (#24702)``
+`f3aacebe50 <https://github.com/apache/airflow/commit/f3aacebe502c4ea5dc2b7d29373539296fa037eb>`_  2022-06-20   ``Convert sftp hook to use paramiko instead of pysftp (#24512)``
+`ad297c9177 <https://github.com/apache/airflow/commit/ad297c91777277e2b76dd7b7f0e3e3fc5c32e07c>`_  2022-06-17   ``Update 'actual_file_to_check' with rendered 'path' (#24451)``
+=================================================================================================  ===========  ===========================================================================
+
 3.0.0
 .....
 
-Latest change: 2022-06-07
+Latest change: 2022-06-09
 
 =================================================================================================  ===========  ==================================================================================
 Commit                                                                                             Committed    Subject
 =================================================================================================  ===========  ==================================================================================
+`dcdcf3a2b8 <https://github.com/apache/airflow/commit/dcdcf3a2b8054fa727efb4cd79d38d2c9c7e1bd5>`_  2022-06-09   ``Update release notes for RC2 release of Providers for May 2022 (#24307)``
 `717a7588bc <https://github.com/apache/airflow/commit/717a7588bc8170363fea5cb75f17efcf68689619>`_  2022-06-07   ``Update package description to remove double min-airflow specification (#24292)``
 `aeabe994b3 <https://github.com/apache/airflow/commit/aeabe994b3381d082f75678a159ddbb3cbf6f4d3>`_  2022-06-07   ``Prepare docs for May 2022 provider's release (#24231)``
 `e656e1de55 <https://github.com/apache/airflow/commit/e656e1de55094e8369cab80b9b1669b1d1225f54>`_  2022-06-06   ``Adding fnmatch type regex to SFTPSensor (#24084)``
diff --git a/docs/apache-airflow-providers-sftp/stable/_sources/connections/sftp.rst.txt b/docs/apache-airflow-providers-sftp/4.0.0/_sources/connections/sftp.rst.txt
similarity index 57%
copy from docs/apache-airflow-providers-sftp/stable/_sources/connections/sftp.rst.txt
copy to docs/apache-airflow-providers-sftp/4.0.0/_sources/connections/sftp.rst.txt
index 58133bb25f..6cc3cb47fb 100644
--- a/docs/apache-airflow-providers-sftp/stable/_sources/connections/sftp.rst.txt
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_sources/connections/sftp.rst.txt
@@ -29,10 +29,8 @@ Authenticating to SFTP
 
 There are two ways to connect to SFTP using Airflow.
 
-1. Use `host key
-   <https://pysftp.readthedocs.io/en/release_0.2.9/pysftp.html#pysftp.CnOpts>`_
-   i.e. host key entered in extras value ``host_key``.
-2. Use ``private_key`` or ``key_file``, along with the optional ``private_key_pass``
+1. Use ``login`` and ``password``.
+2. Use ``private_key`` or ``key_file``, along with the optional ``private_key_passphrase``
 
 Only one authorization method can be used at a time. If you need to manage multiple credentials or keys then you should
 configure multiple connections.
@@ -61,19 +59,20 @@ Extra (optional)
     Specify the extra parameters (as json dictionary) that can be used in sftp connection.
     The following parameters are all optional:
 
-    * ``private_key_pass``: Specify the password to use, if private_key is encrypted.
-    * ``no_host_key_check``: Set to false to restrict connecting to hosts with either no entries in ~/.ssh/known_hosts
-      (Hosts file) or not present in the host_key extra. This provides maximum protection against trojan horse attacks,
-      but can be troublesome when the /etc/ssh/ssh_known_hosts file is poorly maintained or connections to new hosts are
-      frequently made. This option forces the user to manually add all new hosts. Default is true, ssh will automatically
-      add new host keys to the user known hosts files.
-    * ``host_key``: The base64 encoded ssh-rsa public key of the host, as you would find in the known_hosts file.
-      Specifying this, along with no_host_key_check=False allows you to only make the connection if the public key of
-      the endpoint matches this value.
-    * ``private_key`` Specify the content of the private key, the path to the private key file(str) or paramiko.AgentKey
     * ``key_file`` - Full Path of the private SSH Key file that will be used to connect to the remote_host.
-
-Example β€œextras” field using ``host_key``:
+    * ``private_key`` - Content of the private key used to connect to the remote_host.
+    * ``private_key_passphrase`` - Content of the private key passphrase used to decrypt the private key.
+    * ``conn_timeout`` - An optional timeout (in seconds) for the TCP connect. Default is ``10``.
+    * ``timeout`` - Deprecated - use conn_timeout instead.
+    * ``compress`` - ``true`` to ask the remote client/server to compress traffic; ``false`` to refuse compression. Default is ``true``.
+    * ``no_host_key_check`` - Set to ``false`` to restrict connecting to hosts with no entries in ``~/.ssh/known_hosts`` (Hosts file). This provides maximum protection against trojan horse attacks, but can be troublesome when the ``/etc/ssh/ssh_known_hosts`` file is poorly maintained or connections to new hosts are frequently made. This option forces the user to manually add all new hosts. Default is ``true``, ssh will automatically add new host keys to the user known hosts files.
+    * ``allow_host_key_change`` - Set to ``true`` if you want to allow connecting to hosts that has host key changed or when you get 'REMOTE HOST IDENTIFICATION HAS CHANGED' error.  This won't protect against Man-In-The-Middle attacks. Other possible solution is to remove the host entry from ``~/.ssh/known_hosts`` file. Default is ``false``.
+    * ``look_for_keys`` - Set to ``false`` if you want to disable searching for discoverable private key files in ``~/.ssh/``
+    * ``host_key`` - The base64 encoded ssh-rsa public key of the host or "ssh-<key type> <key data>" (as you would find in the ``known_hosts`` file). Specifying this allows making the connection if and only if the public key of the endpoint matches this value.
+    * ``disabled_algorithms`` - A dictionary mapping algorithm type to an iterable of algorithm identifiers, which will be disabled for the lifetime of the transport.
+    * ``ciphers`` - A list of ciphers to use in order of preference.
+
+Example "extras" field using ``host_key``:
 
 .. code-block:: json
 
@@ -83,7 +82,7 @@ Example β€œextras” field using ``host_key``:
        "host_key": "AAAHD...YDWwq=="
     }
 
-Example β€œextras” field using ``key_file`` or ``private_key``:
+Example "extras" field using ``key_file`` or ``private_key``:
 
 .. code-block:: json
 
diff --git a/docs/apache-airflow-providers-sftp/stable/_sources/index.rst.txt b/docs/apache-airflow-providers-sftp/4.0.0/_sources/index.rst.txt
similarity index 85%
copy from docs/apache-airflow-providers-sftp/stable/_sources/index.rst.txt
copy to docs/apache-airflow-providers-sftp/4.0.0/_sources/index.rst.txt
index 4ea251eb75..da3b7dcf81 100644
--- a/docs/apache-airflow-providers-sftp/stable/_sources/index.rst.txt
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_sources/index.rst.txt
@@ -52,7 +52,7 @@ Package apache-airflow-providers-sftp
 `SSH File Transfer Protocol (SFTP) <https://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/>`__
 
 
-Release: 3.0.0
+Release: 4.0.0
 
 Provider package
 ----------------
@@ -75,9 +75,6 @@ PIP package                       Version required
 ================================  ==================
 ``apache-airflow``                ``>=2.2.0``
 ``apache-airflow-providers-ssh``  ``>=2.1.0``
-``paramiko``                      ``>=2.6.0``
-``pysftp``                        ``>=0.2.9``
-``sshtunnel``                     ``>=0.3.2``
 ================================  ==================
 
 Cross provider package dependencies
@@ -105,7 +102,7 @@ Downloading official packages
 You can download officially released packages and verify their checksums and signatures from the
 `Official Apache Download site <https://downloads.apache.org/airflow/providers/>`_
 
-* `The apache-airflow-providers-sftp 3.0.0 sdist package <https://downloads.apache.org/airflow/providers/apache-airflow-providers-sftp-3.0.0.tar.gz>`_ (`asc <https://downloads.apache.org/airflow/providers/apache-airflow-providers-sftp-3.0.0.tar.gz.asc>`__, `sha512 <https://downloads.apache.org/airflow/providers/apache-airflow-providers-sftp-3.0.0.tar.gz.sha512>`__)
-* `The apache-airflow-providers-sftp 3.0.0 wheel package <https://downloads.apache.org/airflow/providers/apache_airflow_providers_sftp-3.0.0-py3-none-any.whl>`_ (`asc <https://downloads.apache.org/airflow/providers/apache_airflow_providers_sftp-3.0.0-py3-none-any.whl.asc>`__, `sha512 <https://downloads.apache.org/airflow/providers/apache_airflow_providers_sftp-3.0.0-py3-none-any.whl.sha512>`__)
+* `The apache-airflow-providers-sftp 4.0.0 sdist package <https://downloads.apache.org/airflow/providers/apache-airflow-providers-sftp-4.0.0.tar.gz>`_ (`asc <https://downloads.apache.org/airflow/providers/apache-airflow-providers-sftp-4.0.0.tar.gz.asc>`__, `sha512 <https://downloads.apache.org/airflow/providers/apache-airflow-providers-sftp-4.0.0.tar.gz.sha512>`__)
+* `The apache-airflow-providers-sftp 4.0.0 wheel package <https://downloads.apache.org/airflow/providers/apache_airflow_providers_sftp-4.0.0-py3-none-any.whl>`_ (`asc <https://downloads.apache.org/airflow/providers/apache_airflow_providers_sftp-4.0.0-py3-none-any.whl.asc>`__, `sha512 <https://downloads.apache.org/airflow/providers/apache_airflow_providers_sftp-4.0.0-py3-none-any.whl.sha512>`__)
 
 .. include:: ../../airflow/providers/sftp/CHANGELOG.rst
diff --git a/docs/apache-airflow-providers-sftp/4.0.0/_sources/installing-providers-from-sources.rst.txt b/docs/apache-airflow-providers-sftp/4.0.0/_sources/installing-providers-from-sources.rst.txt
new file mode 100644
index 0000000000..1c90205d15
--- /dev/null
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_sources/installing-providers-from-sources.rst.txt
@@ -0,0 +1,18 @@
+ .. 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.
+
+.. include:: ../installing-providers-from-sources.rst
diff --git a/docs/apache-airflow-providers-sftp/4.0.0/_static/_gen/css/main-custom.min.css b/docs/apache-airflow-providers-sftp/4.0.0/_static/_gen/css/main-custom.min.css
new file mode 100644
index 0000000000..46f1de5932
--- /dev/null
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_static/_gen/css/main-custom.min.css
@@ -0,0 +1 @@
+@charset "UTF-8";@import "https://fonts.googleapis.com/css?family=Rubik:500&display=swap";@import "https://fonts.googleapis.com/css?family=Roboto:400,400i,500,700&display=swap";@import "https://fonts.googleapis.com/css?family=Roboto+Mono:400,700&display=swap";.header__large--cerulean-blue{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#017cee}.header__large--shamrock{font-family:rubik,sans-serif;font-weight:500;font-size:72px;line-height:1.17;color:#00 [...]
\ No newline at end of file
diff --git a/docs/apache-airflow-providers-sftp/4.0.0/_static/_gen/css/main.min.css b/docs/apache-airflow-providers-sftp/4.0.0/_static/_gen/css/main.min.css
new file mode 100644
index 0000000000..603f3cb39f
--- /dev/null
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_static/_gen/css/main.min.css
@@ -0,0 +1,7 @@
+@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,700,700i";@fa-font-path:"../webfonts";/*!* Bootstrap v4.1.3 (https://getbootstrap.com/)
+* Copyright 2011-2018 The Bootstrap Authors
+* Copyright 2011-2018 Twitter, Inc.
+* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)*/:root{--blue: #72A1E5;--indigo: #6610f2;--purple: #6f42c1;--pink: #e83e8c;--red: #dc3545;--orange: #BA5A31;--yellow: #ffc107;--green: #28a745;--teal: #20c997;--cyan: #17a2b8;--white: #fff;--gray: #888;--gray-dark: #333;--primary: #30638E;--secondary: #FFA630;--success: #3772FF;--info: #C0E0DE;--warning: #ED6A5A;--danger: #ED6A5A;--light: #D3F3EE;--dark: #403F4C;--breakpoint-xs: 0;--breakpoint-sm: 576px;--breakp [...]
+* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)*/.fa,.fas,.far,.fal,.fad,.fab{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-.0667em}.fa-xs{font-size:.75em}.fa-sm{font-size:.875em}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font [...]
+* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)*/@font-face{font-family:'font awesome 5 free';font-style:normal;font-weight:900;font-display:auto;src:url(../webfonts/fa-solid-900.eot);src:url(../webfonts/fa-solid-900.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.woff) format("woff"),url(../webfonts/fa-solid-900.ttf) format("truetype"),url(../webfonts/fa-so [...]
+* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)*/@font-face{font-family:'font awesome 5 brands';font-style:normal;font-weight:400;font-display:auto;src:url(../webfonts/fa-brands-400.eot);src:url(../webfonts/fa-brands-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.woff) format("woff"),url(../webfonts/fa-brands-400.ttf) format("truetype"),url(../webfont [...]
\ No newline at end of file
diff --git a/docs/apache-airflow-providers-sftp/4.0.0/_static/_gen/js/docs.js b/docs/apache-airflow-providers-sftp/4.0.0/_static/_gen/js/docs.js
new file mode 100644
index 0000000000..90898d86d5
--- /dev/null
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_static/_gen/js/docs.js
@@ -0,0 +1 @@
+!function(r){var n={};function o(t){if(n[t])return n[t].exports;var e=n[t]={i:t,l:!1,exports:{}};return r[t].call(e.exports,e,e.exports,o),e.l=!0,e.exports}o.m=r,o.c=n,o.d=function(t,e,r){o.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:r})},o.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},o.t=function(e,t){if(1&t&&(e=o(e)),8&t)return e;if(4&t&&"object"==typ [...]
\ No newline at end of file
diff --git a/docs/apache-airflow-providers-sftp/4.0.0/_static/_sphinx_javascript_frameworks_compat.js b/docs/apache-airflow-providers-sftp/4.0.0/_static/_sphinx_javascript_frameworks_compat.js
new file mode 100644
index 0000000000..8549469dc2
--- /dev/null
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_static/_sphinx_javascript_frameworks_compat.js
@@ -0,0 +1,134 @@
+/*
+ * _sphinx_javascript_frameworks_compat.js
+ * ~~~~~~~~~~
+ *
+ * Compatability shim for jQuery and underscores.js.
+ *
+ * WILL BE REMOVED IN Sphinx 6.0
+ * xref RemovedInSphinx60Warning
+ *
+ */
+
+/**
+ * select a different prefix for underscore
+ */
+$u = _.noConflict();
+
+
+/**
+ * small helper function to urldecode strings
+ *
+ * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL
+ */
+jQuery.urldecode = function(x) {
+    if (!x) {
+        return x
+    }
+    return decodeURIComponent(x.replace(/\+/g, ' '));
+};
+
+/**
+ * small helper function to urlencode strings
+ */
+jQuery.urlencode = encodeURIComponent;
+
+/**
+ * This function returns the parsed url parameters of the
+ * current request. Multiple values per key are supported,
+ * it will always return arrays of strings for the value parts.
+ */
+jQuery.getQueryParameters = function(s) {
+    if (typeof s === 'undefined')
+        s = document.location.search;
+    var parts = s.substr(s.indexOf('?') + 1).split('&');
+    var result = {};
+    for (var i = 0; i < parts.length; i++) {
+        var tmp = parts[i].split('=', 2);
+        var key = jQuery.urldecode(tmp[0]);
+        var value = jQuery.urldecode(tmp[1]);
+        if (key in result)
+            result[key].push(value);
+        else
+            result[key] = [value];
+    }
+    return result;
+};
+
+/**
+ * highlight a given string on a jquery object by wrapping it in
+ * span elements with the given class name.
+ */
+jQuery.fn.highlightText = function(text, className) {
+    function highlight(node, addItems) {
+        if (node.nodeType === 3) {
+            var val = node.nodeValue;
+            var pos = val.toLowerCase().indexOf(text);
+            if (pos >= 0 &&
+                !jQuery(node.parentNode).hasClass(className) &&
+                !jQuery(node.parentNode).hasClass("nohighlight")) {
+                var span;
+                var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg");
+                if (isInSVG) {
+                    span = document.createElementNS("http://www.w3.org/2000/svg", "tspan");
+                } else {
+                    span = document.createElement("span");
+                    span.className = className;
+                }
+                span.appendChild(document.createTextNode(val.substr(pos, text.length)));
+                node.parentNode.insertBefore(span, node.parentNode.insertBefore(
+                    document.createTextNode(val.substr(pos + text.length)),
+                    node.nextSibling));
+                node.nodeValue = val.substr(0, pos);
+                if (isInSVG) {
+                    var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
+                    var bbox = node.parentElement.getBBox();
+                    rect.x.baseVal.value = bbox.x;
+                    rect.y.baseVal.value = bbox.y;
+                    rect.width.baseVal.value = bbox.width;
+                    rect.height.baseVal.value = bbox.height;
+                    rect.setAttribute('class', className);
+                    addItems.push({
+                        "parent": node.parentNode,
+                        "target": rect});
+                }
+            }
+        }
+        else if (!jQuery(node).is("button, select, textarea")) {
+            jQuery.each(node.childNodes, function() {
+                highlight(this, addItems);
+            });
+        }
+    }
+    var addItems = [];
+    var result = this.each(function() {
+        highlight(this, addItems);
+    });
+    for (var i = 0; i < addItems.length; ++i) {
+        jQuery(addItems[i].parent).before(addItems[i].target);
+    }
+    return result;
+};
+
+/*
+ * backward compatibility for jQuery.browser
+ * This will be supported until firefox bug is fixed.
+ */
+if (!jQuery.browser) {
+    jQuery.uaMatch = function(ua) {
+        ua = ua.toLowerCase();
+
+        var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
+            /(webkit)[ \/]([\w.]+)/.exec(ua) ||
+            /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
+            /(msie) ([\w.]+)/.exec(ua) ||
+            ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
+            [];
+
+        return {
+            browser: match[ 1 ] || "",
+            version: match[ 2 ] || "0"
+        };
+    };
+    jQuery.browser = {};
+    jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true;
+}
diff --git a/docs/apache-airflow-providers-sftp/stable/_static/basic.css b/docs/apache-airflow-providers-sftp/4.0.0/_static/basic.css
similarity index 96%
copy from docs/apache-airflow-providers-sftp/stable/_static/basic.css
copy to docs/apache-airflow-providers-sftp/4.0.0/_static/basic.css
index bf18350b65..7d5974c322 100644
--- a/docs/apache-airflow-providers-sftp/stable/_static/basic.css
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_static/basic.css
@@ -222,7 +222,7 @@ table.modindextable td {
 /* -- general body styles --------------------------------------------------- */
 
 div.body {
-    min-width: 450px;
+    min-width: 360px;
     max-width: 800px;
 }
 
@@ -236,7 +236,6 @@ div.body p, div.body dd, div.body li, div.body blockquote {
 a.headerlink {
     visibility: hidden;
 }
-
 a.brackets:before,
 span.brackets > a:before{
     content: "[";
@@ -247,6 +246,7 @@ span.brackets > a:after {
     content: "]";
 }
 
+
 h1:hover > a.headerlink,
 h2:hover > a.headerlink,
 h3:hover > a.headerlink,
@@ -334,13 +334,11 @@ aside.sidebar {
 p.sidebar-title {
     font-weight: bold;
 }
-
 div.admonition, div.topic, blockquote {
     clear: left;
 }
 
 /* -- topics ---------------------------------------------------------------- */
-
 div.topic {
     border: 1px solid #ccc;
     padding: 7px;
@@ -428,10 +426,6 @@ table.docutils td, table.docutils th {
     border-bottom: 1px solid #aaa;
 }
 
-table.footnote td, table.footnote th {
-    border: 0 !important;
-}
-
 th {
     text-align: left;
     padding-right: 5px;
@@ -615,6 +609,7 @@ ul.simple p {
     margin-bottom: 0;
 }
 
+/* Docutils 0.17 and older (footnotes & citations) */
 dl.footnote > dt,
 dl.citation > dt {
     float: left;
@@ -632,6 +627,33 @@ dl.citation > dd:after {
     clear: both;
 }
 
+/* Docutils 0.18+ (footnotes & citations) */
+aside.footnote > span,
+div.citation > span {
+    float: left;
+}
+aside.footnote > span:last-of-type,
+div.citation > span:last-of-type {
+  padding-right: 0.5em;
+}
+aside.footnote > p {
+  margin-left: 2em;
+}
+div.citation > p {
+  margin-left: 4em;
+}
+aside.footnote > p:last-of-type,
+div.citation > p:last-of-type {
+    margin-bottom: 0em;
+}
+aside.footnote > p:last-of-type:after,
+div.citation > p:last-of-type:after {
+    content: "";
+    clear: both;
+}
+
+/* Footnotes & citations ends */
+
 dl.field-list {
     display: grid;
     grid-template-columns: fit-content(30%) auto;
diff --git a/docs/apache-airflow-providers-sftp/4.0.0/_static/check-solid.svg b/docs/apache-airflow-providers-sftp/4.0.0/_static/check-solid.svg
new file mode 100644
index 0000000000..92fad4b5c0
--- /dev/null
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_static/check-solid.svg
@@ -0,0 +1,4 @@
+<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-check" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#22863a" fill="none" stroke-linecap="round" stroke-linejoin="round">
+  <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
+  <path d="M5 12l5 5l10 -10" />
+</svg>
diff --git a/docs/apache-airflow-providers-sftp/4.0.0/_static/clipboard.min.js b/docs/apache-airflow-providers-sftp/4.0.0/_static/clipboard.min.js
new file mode 100644
index 0000000000..54b3c46381
--- /dev/null
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_static/clipboard.min.js
@@ -0,0 +1,7 @@
+/*!
+ * clipboard.js v2.0.8
+ * https://clipboardjs.com/
+ *
+ * Licensed MIT Β© Zeno Rocha
+ */
+!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return n={686:function(t,e,n){"use strict";n.d(e,{default:function(){return o}});var e=n(279),i=n.n(e),e=n(370),u=n.n(e),e=n(817),c=n.n(e);function a(t){try{return document.execCommand(t)}catch(t){return}}var f=function(t){t=c()(t);return a("cut"),t};var l=function(t){var  [...]
\ No newline at end of file
diff --git a/docs/apache-airflow-providers-sftp/4.0.0/_static/copy-button.svg b/docs/apache-airflow-providers-sftp/4.0.0/_static/copy-button.svg
new file mode 100644
index 0000000000..9c074dae52
--- /dev/null
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_static/copy-button.svg
@@ -0,0 +1,5 @@
+<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-copy" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#000000" fill="none" stroke-linecap="round" stroke-linejoin="round">
+  <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
+  <rect x="8" y="8" width="12" height="12" rx="2" />
+  <path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2" />
+</svg>
diff --git a/docs/apache-airflow-providers-sftp/4.0.0/_static/copybutton.css b/docs/apache-airflow-providers-sftp/4.0.0/_static/copybutton.css
new file mode 100644
index 0000000000..40eafe5fc2
--- /dev/null
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_static/copybutton.css
@@ -0,0 +1,93 @@
+/* Copy buttons */
+button.copybtn {
+    position: absolute;
+    display: flex;
+    top: .3em;
+    right: .3em;
+    width: 1.7em;
+    height: 1.7em;
+	opacity: 0;
+    transition: opacity 0.3s, border .3s, background-color .3s;
+    user-select: none;
+    padding: 0;
+    border: none;
+    outline: none;
+    border-radius: 0.4em;
+    /* The colors that GitHub uses */
+    border: #1b1f2426 1px solid;
+    background-color: #f6f8fa;
+    color: #57606a;
+}
+
+button.copybtn.success {
+    border-color: #22863a;
+    color: #22863a;
+}
+
+button.copybtn svg {
+    stroke: currentColor;
+    width: 1.5em;
+    height: 1.5em;
+    padding: 0.1em;
+}
+
+div.highlight  {
+    position: relative;
+}
+
+.highlight:hover button.copybtn {
+	opacity: 1;
+}
+
+.highlight button.copybtn:hover {
+    background-color: rgb(235, 235, 235);
+}
+
+.highlight button.copybtn:active {
+    background-color: rgb(187, 187, 187);
+}
+
+/**
+ * A minimal CSS-only tooltip copied from:
+ *   https://codepen.io/mildrenben/pen/rVBrpK
+ *
+ * To use, write HTML like the following:
+ *
+ * <p class="o-tooltip--left" data-tooltip="Hey">Short</p>
+ */
+ .o-tooltip--left {
+  position: relative;
+ }
+
+ .o-tooltip--left:after {
+    opacity: 0;
+    visibility: hidden;
+    position: absolute;
+    content: attr(data-tooltip);
+    padding: .2em;
+    font-size: .8em;
+    left: -.2em;
+    background: grey;
+    color: white;
+    white-space: nowrap;
+    z-index: 2;
+    border-radius: 2px;
+    transform: translateX(-102%) translateY(0);
+    transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1);
+}
+
+.o-tooltip--left:hover:after {
+    display: block;
+    opacity: 1;
+    visibility: visible;
+    transform: translateX(-100%) translateY(0);
+    transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1);
+    transition-delay: .5s;
+}
+
+/* By default the copy button shouldn't show up when printing a page */
+@media print {
+    button.copybtn {
+        display: none;
+    }
+}
diff --git a/docs/apache-airflow-providers-sftp/4.0.0/_static/copybutton.js b/docs/apache-airflow-providers-sftp/4.0.0/_static/copybutton.js
new file mode 100644
index 0000000000..40ac331086
--- /dev/null
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_static/copybutton.js
@@ -0,0 +1,220 @@
+// Localization support
+const messages = {
+  'en': {
+    'copy': 'Copy',
+    'copy_to_clipboard': 'Copy to clipboard',
+    'copy_success': 'Copied!',
+    'copy_failure': 'Failed to copy',
+  },
+  'es' : {
+    'copy': 'Copiar',
+    'copy_to_clipboard': 'Copiar al portapapeles',
+    'copy_success': 'Β‘Copiado!',
+    'copy_failure': 'Error al copiar',
+  },
+  'de' : {
+    'copy': 'Kopieren',
+    'copy_to_clipboard': 'In die Zwischenablage kopieren',
+    'copy_success': 'Kopiert!',
+    'copy_failure': 'Fehler beim Kopieren',
+  },
+  'fr' : {
+    'copy': 'Copier',
+    'copy_to_clipboard': 'CopiΓ© dans le presse-papier',
+    'copy_success': 'CopiΓ© !',
+    'copy_failure': 'Γ‰chec de la copie',
+  },
+  'ru': {
+    'copy': 'Π‘ΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ',
+    'copy_to_clipboard': 'Π‘ΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π² Π±ΡƒΡ„Π΅Ρ€',
+    'copy_success': 'Π‘ΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Π½ΠΎ!',
+    'copy_failure': 'НС ΡƒΠ΄Π°Π»ΠΎΡΡŒ ΡΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ',
+  },
+  'zh-CN': {
+    'copy': '倍刢',
+    'copy_to_clipboard': '倍刢到ε‰ͺ贴板',
+    'copy_success': '倍刢成功!',
+    'copy_failure': '倍刢倱θ΄₯',
+  },
+  'it' : {
+    'copy': 'Copiare',
+    'copy_to_clipboard': 'Copiato negli appunti',
+    'copy_success': 'Copiato!',
+    'copy_failure': 'Errore durante la copia',
+  }
+}
+
+let locale = 'en'
+if( document.documentElement.lang !== undefined
+    && messages[document.documentElement.lang] !== undefined ) {
+  locale = document.documentElement.lang
+}
+
+let doc_url_root = DOCUMENTATION_OPTIONS.URL_ROOT;
+if (doc_url_root == '#') {
+    doc_url_root = '';
+}
+
+/**
+ * SVG files for our copy buttons
+ */
+let iconCheck = `<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-check" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" stroke="#22863a" fill="none" stroke-linecap="round" stroke-linejoin="round">
+  <title>${messages[locale]['copy_success']}</title>
+  <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
+  <path d="M5 12l5 5l10 -10" />
+</svg>`
+
+// If the user specified their own SVG use that, otherwise use the default
+let iconCopy = ``;
+if (!iconCopy) {
+  iconCopy = `<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-copy" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#000000" fill="none" stroke-linecap="round" stroke-linejoin="round">
+  <title>${messages[locale]['copy_to_clipboard']}</title>
+  <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
+  <rect x="8" y="8" width="12" height="12" rx="2" />
+  <path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2" />
+</svg>`
+}
+
+/**
+ * Set up copy/paste for code blocks
+ */
+
+const runWhenDOMLoaded = cb => {
+  if (document.readyState != 'loading') {
+    cb()
+  } else if (document.addEventListener) {
+    document.addEventListener('DOMContentLoaded', cb)
+  } else {
+    document.attachEvent('onreadystatechange', function() {
+      if (document.readyState == 'complete') cb()
+    })
+  }
+}
+
+const codeCellId = index => `codecell${index}`
+
+// Clears selected text since ClipboardJS will select the text when copying
+const clearSelection = () => {
+  if (window.getSelection) {
+    window.getSelection().removeAllRanges()
+  } else if (document.selection) {
+    document.selection.empty()
+  }
+}
+
+// Changes tooltip text for two seconds, then changes it back
+const temporarilyChangeTooltip = (el, oldText, newText) => {
+  el.setAttribute('data-tooltip', newText)
+  el.classList.add('success')
+  setTimeout(() => el.setAttribute('data-tooltip', oldText), 2000)
+  setTimeout(() => el.classList.remove('success'), 2000)
+}
+
+// Changes the copy button icon for two seconds, then changes it back
+const temporarilyChangeIcon = (el) => {
+  el.innerHTML = iconCheck;
+  setTimeout(() => {el.innerHTML = iconCopy}, 2000)
+}
+
+const addCopyButtonToCodeCells = () => {
+  // If ClipboardJS hasn't loaded, wait a bit and try again. This
+  // happens because we load ClipboardJS asynchronously.
+  if (window.ClipboardJS === undefined) {
+    setTimeout(addCopyButtonToCodeCells, 250)
+    return
+  }
+
+  // Add copybuttons to all of our code cells
+  const codeCells = document.querySelectorAll('div.highlight pre')
+  codeCells.forEach((codeCell, index) => {
+    const id = codeCellId(index)
+    codeCell.setAttribute('id', id)
+
+    const clipboardButton = id =>
+    `<button class="copybtn o-tooltip--left" data-tooltip="${messages[locale]['copy']}" data-clipboard-target="#${id}">
+      ${iconCopy}
+    </button>`
+    codeCell.insertAdjacentHTML('afterend', clipboardButton(id))
+  })
+
+function escapeRegExp(string) {
+    return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
+}
+
+// Callback when a copy button is clicked. Will be passed the node that was clicked
+// should then grab the text and replace pieces of text that shouldn't be used in output
+function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") {
+
+    var regexp;
+    var match;
+
+    // Do we check for line continuation characters and "HERE-documents"?
+    var useLineCont = !!lineContinuationChar
+    var useHereDoc = !!hereDocDelim
+
+    // create regexp to capture prompt and remaining line
+    if (isRegexp) {
+        regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)')
+    } else {
+        regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)')
+    }
+
+    const outputLines = [];
+    var promptFound = false;
+    var gotLineCont = false;
+    var gotHereDoc = false;
+    const lineGotPrompt = [];
+    for (const line of textContent.split('\n')) {
+        match = line.match(regexp)
+        if (match || gotLineCont || gotHereDoc) {
+            promptFound = regexp.test(line)
+            lineGotPrompt.push(promptFound)
+            if (removePrompts && promptFound) {
+                outputLines.push(match[2])
+            } else {
+                outputLines.push(line)
+            }
+            gotLineCont = line.endsWith(lineContinuationChar) & useLineCont
+            if (line.includes(hereDocDelim) & useHereDoc)
+                gotHereDoc = !gotHereDoc
+        } else if (!onlyCopyPromptLines) {
+            outputLines.push(line)
+        } else if (copyEmptyLines && line.trim() === '') {
+            outputLines.push(line)
+        }
+    }
+
+    // If no lines with the prompt were found then just use original lines
+    if (lineGotPrompt.some(v => v === true)) {
+        textContent = outputLines.join('\n');
+    }
+
+    // Remove a trailing newline to avoid auto-running when pasting
+    if (textContent.endsWith("\n")) {
+        textContent = textContent.slice(0, -1)
+    }
+    return textContent
+}
+
+
+var copyTargetText = (trigger) => {
+  var target = document.querySelector(trigger.attributes['data-clipboard-target'].value);
+  return formatCopyText(target.innerText, '', false, true, true, true, '', '')
+}
+
+  // Initialize with a callback so we can modify the text before copy
+  const clipboard = new ClipboardJS('.copybtn', {text: copyTargetText})
+
+  // Update UI with error/success messages
+  clipboard.on('success', event => {
+    clearSelection()
+    temporarilyChangeTooltip(event.trigger, messages[locale]['copy'], messages[locale]['copy_success'])
+    temporarilyChangeIcon(event.trigger)
+  })
+
+  clipboard.on('error', event => {
+    temporarilyChangeTooltip(event.trigger, messages[locale]['copy'], messages[locale]['copy_failure'])
+  })
+}
+
+runWhenDOMLoaded(addCopyButtonToCodeCells)
\ No newline at end of file
diff --git a/docs/apache-airflow-providers-sftp/4.0.0/_static/copybutton_funcs.js b/docs/apache-airflow-providers-sftp/4.0.0/_static/copybutton_funcs.js
new file mode 100644
index 0000000000..b9168c5565
--- /dev/null
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_static/copybutton_funcs.js
@@ -0,0 +1,58 @@
+function escapeRegExp(string) {
+    return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
+}
+
+// Callback when a copy button is clicked. Will be passed the node that was clicked
+// should then grab the text and replace pieces of text that shouldn't be used in output
+export function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") {
+
+    var regexp;
+    var match;
+
+    // Do we check for line continuation characters and "HERE-documents"?
+    var useLineCont = !!lineContinuationChar
+    var useHereDoc = !!hereDocDelim
+
+    // create regexp to capture prompt and remaining line
+    if (isRegexp) {
+        regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)')
+    } else {
+        regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)')
+    }
+
+    const outputLines = [];
+    var promptFound = false;
+    var gotLineCont = false;
+    var gotHereDoc = false;
+    const lineGotPrompt = [];
+    for (const line of textContent.split('\n')) {
+        match = line.match(regexp)
+        if (match || gotLineCont || gotHereDoc) {
+            promptFound = regexp.test(line)
+            lineGotPrompt.push(promptFound)
+            if (removePrompts && promptFound) {
+                outputLines.push(match[2])
+            } else {
+                outputLines.push(line)
+            }
+            gotLineCont = line.endsWith(lineContinuationChar) & useLineCont
+            if (line.includes(hereDocDelim) & useHereDoc)
+                gotHereDoc = !gotHereDoc
+        } else if (!onlyCopyPromptLines) {
+            outputLines.push(line)
+        } else if (copyEmptyLines && line.trim() === '') {
+            outputLines.push(line)
+        }
+    }
+
+    // If no lines with the prompt were found then just use original lines
+    if (lineGotPrompt.some(v => v === true)) {
+        textContent = outputLines.join('\n');
+    }
+
+    // Remove a trailing newline to avoid auto-running when pasting
+    if (textContent.endsWith("\n")) {
+        textContent = textContent.slice(0, -1)
+    }
+    return textContent
+}
diff --git a/docs/apache-airflow-providers-sftp/4.0.0/_static/doctools.js b/docs/apache-airflow-providers-sftp/4.0.0/_static/doctools.js
new file mode 100644
index 0000000000..c3db08d1c3
--- /dev/null
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_static/doctools.js
@@ -0,0 +1,264 @@
+/*
+ * doctools.js
+ * ~~~~~~~~~~~
+ *
+ * Base JavaScript utilities for all Sphinx HTML documentation.
+ *
+ * :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+"use strict";
+
+const _ready = (callback) => {
+  if (document.readyState !== "loading") {
+    callback();
+  } else {
+    document.addEventListener("DOMContentLoaded", callback);
+  }
+};
+
+/**
+ * highlight a given string on a node by wrapping it in
+ * span elements with the given class name.
+ */
+const _highlight = (node, addItems, text, className) => {
+  if (node.nodeType === Node.TEXT_NODE) {
+    const val = node.nodeValue;
+    const parent = node.parentNode;
+    const pos = val.toLowerCase().indexOf(text);
+    if (
+      pos >= 0 &&
+      !parent.classList.contains(className) &&
+      !parent.classList.contains("nohighlight")
+    ) {
+      let span;
+
+      const closestNode = parent.closest("body, svg, foreignObject");
+      const isInSVG = closestNode && closestNode.matches("svg");
+      if (isInSVG) {
+        span = document.createElementNS("http://www.w3.org/2000/svg", "tspan");
+      } else {
+        span = document.createElement("span");
+        span.classList.add(className);
+      }
+
+      span.appendChild(document.createTextNode(val.substr(pos, text.length)));
+      parent.insertBefore(
+        span,
+        parent.insertBefore(
+          document.createTextNode(val.substr(pos + text.length)),
+          node.nextSibling
+        )
+      );
+      node.nodeValue = val.substr(0, pos);
+
+      if (isInSVG) {
+        const rect = document.createElementNS(
+          "http://www.w3.org/2000/svg",
+          "rect"
+        );
+        const bbox = parent.getBBox();
+        rect.x.baseVal.value = bbox.x;
+        rect.y.baseVal.value = bbox.y;
+        rect.width.baseVal.value = bbox.width;
+        rect.height.baseVal.value = bbox.height;
+        rect.setAttribute("class", className);
+        addItems.push({ parent: parent, target: rect });
+      }
+    }
+  } else if (node.matches && !node.matches("button, select, textarea")) {
+    node.childNodes.forEach((el) => _highlight(el, addItems, text, className));
+  }
+};
+const _highlightText = (thisNode, text, className) => {
+  let addItems = [];
+  _highlight(thisNode, addItems, text, className);
+  addItems.forEach((obj) =>
+    obj.parent.insertAdjacentElement("beforebegin", obj.target)
+  );
+};
+
+/**
+ * Small JavaScript module for the documentation.
+ */
+const Documentation = {
+  init: () => {
+    Documentation.highlightSearchWords();
+    Documentation.initDomainIndexTable();
+    Documentation.initOnKeyListeners();
+  },
+
+  /**
+   * i18n support
+   */
+  TRANSLATIONS: {},
+  PLURAL_EXPR: (n) => (n === 1 ? 0 : 1),
+  LOCALE: "unknown",
+
+  // gettext and ngettext don't access this so that the functions
+  // can safely bound to a different name (_ = Documentation.gettext)
+  gettext: (string) => {
+    const translated = Documentation.TRANSLATIONS[string];
+    switch (typeof translated) {
+      case "undefined":
+        return string; // no translation
+      case "string":
+        return translated; // translation exists
+      default:
+        return translated[0]; // (singular, plural) translation tuple exists
+    }
+  },
+
+  ngettext: (singular, plural, n) => {
+    const translated = Documentation.TRANSLATIONS[singular];
+    if (typeof translated !== "undefined")
+      return translated[Documentation.PLURAL_EXPR(n)];
+    return n === 1 ? singular : plural;
+  },
+
+  addTranslations: (catalog) => {
+    Object.assign(Documentation.TRANSLATIONS, catalog.messages);
+    Documentation.PLURAL_EXPR = new Function(
+      "n",
+      `return (${catalog.plural_expr})`
+    );
+    Documentation.LOCALE = catalog.locale;
+  },
+
+  /**
+   * highlight the search words provided in the url in the text
+   */
+  highlightSearchWords: () => {
+    const highlight =
+      new URLSearchParams(window.location.search).get("highlight") || "";
+    const terms = highlight.toLowerCase().split(/\s+/).filter(x => x);
+    if (terms.length === 0) return; // nothing to do
+
+    // There should never be more than one element matching "div.body"
+    const divBody = document.querySelectorAll("div.body");
+    const body = divBody.length ? divBody[0] : document.querySelector("body");
+    window.setTimeout(() => {
+      terms.forEach((term) => _highlightText(body, term, "highlighted"));
+    }, 10);
+
+    const searchBox = document.getElementById("searchbox");
+    if (searchBox === null) return;
+    searchBox.appendChild(
+      document
+        .createRange()
+        .createContextualFragment(
+          '<p class="highlight-link">' +
+            '<a href="javascript:Documentation.hideSearchWords()">' +
+            Documentation.gettext("Hide Search Matches") +
+            "</a></p>"
+        )
+    );
+  },
+
+  /**
+   * helper function to hide the search marks again
+   */
+  hideSearchWords: () => {
+    document
+      .querySelectorAll("#searchbox .highlight-link")
+      .forEach((el) => el.remove());
+    document
+      .querySelectorAll("span.highlighted")
+      .forEach((el) => el.classList.remove("highlighted"));
+    const url = new URL(window.location);
+    url.searchParams.delete("highlight");
+    window.history.replaceState({}, "", url);
+  },
+
+  /**
+   * helper function to focus on search bar
+   */
+  focusSearchBar: () => {
+    document.querySelectorAll("input[name=q]")[0]?.focus();
+  },
+
+  /**
+   * Initialise the domain index toggle buttons
+   */
+  initDomainIndexTable: () => {
+    const toggler = (el) => {
+      const idNumber = el.id.substr(7);
+      const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`);
+      if (el.src.substr(-9) === "minus.png") {
+        el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`;
+        toggledRows.forEach((el) => (el.style.display = "none"));
+      } else {
+        el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`;
+        toggledRows.forEach((el) => (el.style.display = ""));
+      }
+    };
+
+    const togglerElements = document.querySelectorAll("img.toggler");
+    togglerElements.forEach((el) =>
+      el.addEventListener("click", (event) => toggler(event.currentTarget))
+    );
+    togglerElements.forEach((el) => (el.style.display = ""));
+    if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler);
+  },
+
+  initOnKeyListeners: () => {
+    // only install a listener if it is really needed
+    if (
+      !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS &&
+      !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS
+    )
+      return;
+
+    const blacklistedElements = new Set([
+      "TEXTAREA",
+      "INPUT",
+      "SELECT",
+      "BUTTON",
+    ]);
+    document.addEventListener("keydown", (event) => {
+      if (blacklistedElements.has(document.activeElement.tagName)) return; // bail for input elements
+      if (event.altKey || event.ctrlKey || event.metaKey) return; // bail with special keys
+
+      if (!event.shiftKey) {
+        switch (event.key) {
+          case "ArrowLeft":
+            if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break;
+
+            const prevLink = document.querySelector('link[rel="prev"]');
+            if (prevLink && prevLink.href) {
+              window.location.href = prevLink.href;
+              event.preventDefault();
+            }
+            break;
+          case "ArrowRight":
+            if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break;
+
+            const nextLink = document.querySelector('link[rel="next"]');
+            if (nextLink && nextLink.href) {
+              window.location.href = nextLink.href;
+              event.preventDefault();
+            }
+            break;
+          case "Escape":
+            if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break;
+            Documentation.hideSearchWords();
+            event.preventDefault();
+        }
+      }
+
+      // some keyboard layouts may need Shift to get /
+      switch (event.key) {
+        case "/":
+          if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break;
+          Documentation.focusSearchBar();
+          event.preventDefault();
+      }
+    });
+  },
+};
+
+// quick alias for translations
+const _ = Documentation.gettext;
+
+_ready(Documentation.init);
diff --git a/docs/apache-airflow-providers-tabular/stable/_static/documentation_options.js b/docs/apache-airflow-providers-sftp/4.0.0/_static/documentation_options.js
similarity index 94%
copy from docs/apache-airflow-providers-tabular/stable/_static/documentation_options.js
copy to docs/apache-airflow-providers-sftp/4.0.0/_static/documentation_options.js
index 95926d9eea..52c7f1f5a7 100644
--- a/docs/apache-airflow-providers-tabular/stable/_static/documentation_options.js
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_static/documentation_options.js
@@ -1,6 +1,6 @@
 var DOCUMENTATION_OPTIONS = {
     URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
-    VERSION: '1.0.0',
+    VERSION: '4.0.0',
     LANGUAGE: 'en',
     COLLAPSE_INDEX: false,
     BUILDER: 'html',
diff --git a/docs/apache-airflow-providers-sftp/4.0.0/_static/file.png b/docs/apache-airflow-providers-sftp/4.0.0/_static/file.png
new file mode 100644
index 0000000000..a858a410e4
Binary files /dev/null and b/docs/apache-airflow-providers-sftp/4.0.0/_static/file.png differ
diff --git a/docs/apache-airflow-providers-sftp/4.0.0/_static/graphviz.css b/docs/apache-airflow-providers-sftp/4.0.0/_static/graphviz.css
new file mode 100644
index 0000000000..19e7afd385
--- /dev/null
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_static/graphviz.css
@@ -0,0 +1,19 @@
+/*
+ * graphviz.css
+ * ~~~~~~~~~~~~
+ *
+ * Sphinx stylesheet -- graphviz extension.
+ *
+ * :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+img.graphviz {
+    border: 0;
+    max-width: 100%;
+}
+
+object.graphviz {
+    max-width: 100%;
+}
diff --git a/docs/apache-airflow-providers-sftp/stable/_static/jquery-3.5.1.js b/docs/apache-airflow-providers-sftp/4.0.0/_static/jquery-3.6.0.js
similarity index 98%
copy from docs/apache-airflow-providers-sftp/stable/_static/jquery-3.5.1.js
copy to docs/apache-airflow-providers-sftp/4.0.0/_static/jquery-3.6.0.js
index 50937333b9..fc6c299b73 100644
--- a/docs/apache-airflow-providers-sftp/stable/_static/jquery-3.5.1.js
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_static/jquery-3.6.0.js
@@ -1,15 +1,15 @@
 /*!
- * jQuery JavaScript Library v3.5.1
+ * jQuery JavaScript Library v3.6.0
  * https://jquery.com/
  *
  * Includes Sizzle.js
  * https://sizzlejs.com/
  *
- * Copyright JS Foundation and other contributors
+ * Copyright OpenJS Foundation and other contributors
  * Released under the MIT license
  * https://jquery.org/license
  *
- * Date: 2020-05-04T22:49Z
+ * Date: 2021-03-02T17:08Z
  */
 ( function( global, factory ) {
 
@@ -76,12 +76,16 @@ var support = {};
 
 var isFunction = function isFunction( obj ) {
 
-      // Support: Chrome <=57, Firefox <=52
-      // In some browsers, typeof returns "function" for HTML <object> elements
-      // (i.e., `typeof document.createElement( "object" ) === "function"`).
-      // We don't want to classify *any* DOM node as a function.
-      return typeof obj === "function" && typeof obj.nodeType !== "number";
-  };
+		// Support: Chrome <=57, Firefox <=52
+		// In some browsers, typeof returns "function" for HTML <object> elements
+		// (i.e., `typeof document.createElement( "object" ) === "function"`).
+		// We don't want to classify *any* DOM node as a function.
+		// Support: QtWeb <=3.8.5, WebKit <=534.34, wkhtmltopdf tool <=0.12.5
+		// Plus for old WebKit, typeof returns "function" for HTML collections
+		// (e.g., `typeof document.getElementsByTagName("div") === "function"`). (gh-4756)
+		return typeof obj === "function" && typeof obj.nodeType !== "number" &&
+			typeof obj.item !== "function";
+	};
 
 
 var isWindow = function isWindow( obj ) {
@@ -147,7 +151,7 @@ function toType( obj ) {
 
 
 var
-	version = "3.5.1",
+	version = "3.6.0",
 
 	// Define a local copy of jQuery
 	jQuery = function( selector, context ) {
@@ -401,7 +405,7 @@ jQuery.extend( {
 			if ( isArrayLike( Object( arr ) ) ) {
 				jQuery.merge( ret,
 					typeof arr === "string" ?
-					[ arr ] : arr
+						[ arr ] : arr
 				);
 			} else {
 				push.call( ret, arr );
@@ -496,9 +500,9 @@ if ( typeof Symbol === "function" ) {
 
 // Populate the class2type map
 jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
-function( _i, name ) {
-	class2type[ "[object " + name + "]" ] = name.toLowerCase();
-} );
+	function( _i, name ) {
+		class2type[ "[object " + name + "]" ] = name.toLowerCase();
+	} );
 
 function isArrayLike( obj ) {
 
@@ -518,14 +522,14 @@ function isArrayLike( obj ) {
 }
 var Sizzle =
 /*!
- * Sizzle CSS Selector Engine v2.3.5
+ * Sizzle CSS Selector Engine v2.3.6
  * https://sizzlejs.com/
  *
  * Copyright JS Foundation and other contributors
  * Released under the MIT license
  * https://js.foundation/
  *
- * Date: 2020-03-14
+ * Date: 2021-02-16
  */
 ( function( window ) {
 var i,
@@ -1108,8 +1112,8 @@ support = Sizzle.support = {};
  * @returns {Boolean} True iff elem is a non-HTML XML node
  */
 isXML = Sizzle.isXML = function( elem ) {
-	var namespace = elem.namespaceURI,
-		docElem = ( elem.ownerDocument || elem ).documentElement;
+	var namespace = elem && elem.namespaceURI,
+		docElem = elem && ( elem.ownerDocument || elem ).documentElement;
 
 	// Support: IE <=8
 	// Assume HTML when documentElement doesn't yet exist, such as inside loading iframes
@@ -3024,9 +3028,9 @@ var rneedsContext = jQuery.expr.match.needsContext;
 
 function nodeName( elem, name ) {
 
-  return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
+	return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
 
-};
+}
 var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i );
 
 
@@ -3997,8 +4001,8 @@ jQuery.extend( {
 			resolveContexts = Array( i ),
 			resolveValues = slice.call( arguments ),
 
-			// the master Deferred
-			master = jQuery.Deferred(),
+			// the primary Deferred
+			primary = jQuery.Deferred(),
 
 			// subordinate callback factory
 			updateFunc = function( i ) {
@@ -4006,30 +4010,30 @@ jQuery.extend( {
 					resolveContexts[ i ] = this;
 					resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
 					if ( !( --remaining ) ) {
-						master.resolveWith( resolveContexts, resolveValues );
+						primary.resolveWith( resolveContexts, resolveValues );
 					}
 				};
 			};
 
 		// Single- and empty arguments are adopted like Promise.resolve
 		if ( remaining <= 1 ) {
-			adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject,
+			adoptValue( singleValue, primary.done( updateFunc( i ) ).resolve, primary.reject,
 				!remaining );
 
 			// Use .then() to unwrap secondary thenables (cf. gh-3000)
-			if ( master.state() === "pending" ||
+			if ( primary.state() === "pending" ||
 				isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) {
 
-				return master.then();
+				return primary.then();
 			}
 		}
 
 		// Multiple arguments are aggregated like Promise.all array elements
 		while ( i-- ) {
-			adoptValue( resolveValues[ i ], updateFunc( i ), master.reject );
+			adoptValue( resolveValues[ i ], updateFunc( i ), primary.reject );
 		}
 
-		return master.promise();
+		return primary.promise();
 	}
 } );
 
@@ -4180,8 +4184,8 @@ var access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
 			for ( ; i < len; i++ ) {
 				fn(
 					elems[ i ], key, raw ?
-					value :
-					value.call( elems[ i ], i, fn( elems[ i ], key ) )
+						value :
+						value.call( elems[ i ], i, fn( elems[ i ], key ) )
 				);
 			}
 		}
@@ -5089,10 +5093,7 @@ function buildFragment( elems, context, scripts, selection, ignored ) {
 }
 
 
-var
-	rkeyEvent = /^key/,
-	rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/,
-	rtypenamespace = /^([^.]*)(?:\.(.+)|)/;
+var rtypenamespace = /^([^.]*)(?:\.(.+)|)/;
 
 function returnTrue() {
 	return true;
@@ -5387,8 +5388,8 @@ jQuery.event = {
 			event = jQuery.event.fix( nativeEvent ),
 
 			handlers = (
-					dataPriv.get( this, "events" ) || Object.create( null )
-				)[ event.type ] || [],
+				dataPriv.get( this, "events" ) || Object.create( null )
+			)[ event.type ] || [],
 			special = jQuery.event.special[ event.type ] || {};
 
 		// Use the fix-ed jQuery.Event rather than the (read-only) native event
@@ -5512,12 +5513,12 @@ jQuery.event = {
 			get: isFunction( hook ) ?
 				function() {
 					if ( this.originalEvent ) {
-							return hook( this.originalEvent );
+						return hook( this.originalEvent );
 					}
 				} :
 				function() {
 					if ( this.originalEvent ) {
-							return this.originalEvent[ name ];
+						return this.originalEvent[ name ];
 					}
 				},
 
@@ -5656,7 +5657,13 @@ function leverageNative( el, type, expectSync ) {
 						// Cancel the outer synthetic event
 						event.stopImmediatePropagation();
 						event.preventDefault();
-						return result.value;
+
+						// Support: Chrome 86+
+						// In Chrome, if an element having a focusout handler is blurred by
+						// clicking outside of it, it invokes the handler synchronously. If
+						// that handler calls `.remove()` on the element, the data is cleared,
+						// leaving `result` undefined. We need to guard against this.
+						return result && result.value;
 					}
 
 				// If this is an inner synthetic event for an event with a bubbling surrogate
@@ -5821,34 +5828,7 @@ jQuery.each( {
 	targetTouches: true,
 	toElement: true,
 	touches: true,
-
-	which: function( event ) {
-		var button = event.button;
-
-		// Add which for key events
-		if ( event.which == null && rkeyEvent.test( event.type ) ) {
-			return event.charCode != null ? event.charCode : event.keyCode;
-		}
-
-		// Add which for click: 1 === left; 2 === middle; 3 === right
-		if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) {
-			if ( button & 1 ) {
-				return 1;
-			}
-
-			if ( button & 2 ) {
-				return 3;
-			}
-
-			if ( button & 4 ) {
-				return 2;
-			}
-
-			return 0;
-		}
-
-		return event.which;
-	}
+	which: true
 }, jQuery.event.addProp );
 
 jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) {
@@ -5874,6 +5854,12 @@ jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateTyp
 			return true;
 		},
 
+		// Suppress native focus or blur as it's already being fired
+		// in leverageNative.
+		_default: function() {
+			return true;
+		},
+
 		delegateType: delegateType
 	};
 } );
@@ -6541,6 +6527,10 @@ var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" );
 		// set in CSS while `offset*` properties report correct values.
 		// Behavior in IE 9 is more subtle than in newer versions & it passes
 		// some versions of this test; make sure not to make it pass there!
+		//
+		// Support: Firefox 70+
+		// Only Firefox includes border widths
+		// in computed dimensions. (gh-4529)
 		reliableTrDimensions: function() {
 			var table, tr, trChild, trStyle;
 			if ( reliableTrDimensionsVal == null ) {
@@ -6548,17 +6538,32 @@ var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" );
 				tr = document.createElement( "tr" );
 				trChild = document.createElement( "div" );
 
-				table.style.cssText = "position:absolute;left:-11111px";
+				table.style.cssText = "position:absolute;left:-11111px;border-collapse:separate";
+				tr.style.cssText = "border:1px solid";
+
+				// Support: Chrome 86+
+				// Height set through cssText does not get applied.
+				// Computed height then comes back as 0.
 				tr.style.height = "1px";
 				trChild.style.height = "9px";
 
+				// Support: Android 8 Chrome 86+
+				// In our bodyBackground.html iframe,
+				// display for all div elements is set to "inline",
+				// which causes a problem only in Android 8 Chrome 86.
+				// Ensuring the div is display: block
+				// gets around this issue.
+				trChild.style.display = "block";
+
 				documentElement
 					.appendChild( table )
 					.appendChild( tr )
 					.appendChild( trChild );
 
 				trStyle = window.getComputedStyle( tr );
-				reliableTrDimensionsVal = parseInt( trStyle.height ) > 3;
+				reliableTrDimensionsVal = ( parseInt( trStyle.height, 10 ) +
+					parseInt( trStyle.borderTopWidth, 10 ) +
+					parseInt( trStyle.borderBottomWidth, 10 ) ) === tr.offsetHeight;
 
 				documentElement.removeChild( table );
 			}
@@ -7022,10 +7027,10 @@ jQuery.each( [ "height", "width" ], function( _i, dimension ) {
 					// Running getBoundingClientRect on a disconnected node
 					// in IE throws an error.
 					( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ?
-						swap( elem, cssShow, function() {
-							return getWidthOrHeight( elem, dimension, extra );
-						} ) :
-						getWidthOrHeight( elem, dimension, extra );
+					swap( elem, cssShow, function() {
+						return getWidthOrHeight( elem, dimension, extra );
+					} ) :
+					getWidthOrHeight( elem, dimension, extra );
 			}
 		},
 
@@ -7084,7 +7089,7 @@ jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft,
 					swap( elem, { marginLeft: 0 }, function() {
 						return elem.getBoundingClientRect().left;
 					} )
-				) + "px";
+			) + "px";
 		}
 	}
 );
@@ -7223,7 +7228,7 @@ Tween.propHooks = {
 			if ( jQuery.fx.step[ tween.prop ] ) {
 				jQuery.fx.step[ tween.prop ]( tween );
 			} else if ( tween.elem.nodeType === 1 && (
-					jQuery.cssHooks[ tween.prop ] ||
+				jQuery.cssHooks[ tween.prop ] ||
 					tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) {
 				jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
 			} else {
@@ -7468,7 +7473,7 @@ function defaultPrefilter( elem, props, opts ) {
 
 			anim.done( function() {
 
-			/* eslint-enable no-loop-func */
+				/* eslint-enable no-loop-func */
 
 				// The final step of a "hide" animation is actually hiding the element
 				if ( !hidden ) {
@@ -7588,7 +7593,7 @@ function Animation( elem, properties, options ) {
 			tweens: [],
 			createTween: function( prop, end ) {
 				var tween = jQuery.Tween( elem, animation.opts, prop, end,
-						animation.opts.specialEasing[ prop ] || animation.opts.easing );
+					animation.opts.specialEasing[ prop ] || animation.opts.easing );
 				animation.tweens.push( tween );
 				return tween;
 			},
@@ -7761,7 +7766,8 @@ jQuery.fn.extend( {
 					anim.stop( true );
 				}
 			};
-			doAnimation.finish = doAnimation;
+
+		doAnimation.finish = doAnimation;
 
 		return empty || optall.queue === false ?
 			this.each( doAnimation ) :
@@ -8401,8 +8407,8 @@ jQuery.fn.extend( {
 				if ( this.setAttribute ) {
 					this.setAttribute( "class",
 						className || value === false ?
-						"" :
-						dataPriv.get( this, "__className__" ) || ""
+							"" :
+							dataPriv.get( this, "__className__" ) || ""
 					);
 				}
 			}
@@ -8417,7 +8423,7 @@ jQuery.fn.extend( {
 		while ( ( elem = this[ i++ ] ) ) {
 			if ( elem.nodeType === 1 &&
 				( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) {
-					return true;
+				return true;
 			}
 		}
 
@@ -8707,9 +8713,7 @@ jQuery.extend( jQuery.event, {
 				special.bindType || type;
 
 			// jQuery handler
-			handle = (
-					dataPriv.get( cur, "events" ) || Object.create( null )
-				)[ event.type ] &&
+			handle = ( dataPriv.get( cur, "events" ) || Object.create( null ) )[ event.type ] &&
 				dataPriv.get( cur, "handle" );
 			if ( handle ) {
 				handle.apply( cur, data );
@@ -8856,7 +8860,7 @@ var rquery = ( /\?/ );
 
 // Cross-browser xml parsing
 jQuery.parseXML = function( data ) {
-	var xml;
+	var xml, parserErrorElem;
 	if ( !data || typeof data !== "string" ) {
 		return null;
 	}
@@ -8865,12 +8869,17 @@ jQuery.parseXML = function( data ) {
 	// IE throws on parseFromString with invalid input.
 	try {
 		xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" );
-	} catch ( e ) {
-		xml = undefined;
-	}
+	} catch ( e ) {}
 
-	if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) {
-		jQuery.error( "Invalid XML: " + data );
+	parserErrorElem = xml && xml.getElementsByTagName( "parsererror" )[ 0 ];
+	if ( !xml || parserErrorElem ) {
+		jQuery.error( "Invalid XML: " + (
+			parserErrorElem ?
+				jQuery.map( parserErrorElem.childNodes, function( el ) {
+					return el.textContent;
+				} ).join( "\n" ) :
+				data
+		) );
 	}
 	return xml;
 };
@@ -8971,16 +8980,14 @@ jQuery.fn.extend( {
 			// Can add propHook for "elements" to filter or add form elements
 			var elements = jQuery.prop( this, "elements" );
 			return elements ? jQuery.makeArray( elements ) : this;
-		} )
-		.filter( function() {
+		} ).filter( function() {
 			var type = this.type;
 
 			// Use .is( ":disabled" ) so that fieldset[disabled] works
 			return this.name && !jQuery( this ).is( ":disabled" ) &&
 				rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
 				( this.checked || !rcheckableType.test( type ) );
-		} )
-		.map( function( _i, elem ) {
+		} ).map( function( _i, elem ) {
 			var val = jQuery( this ).val();
 
 			if ( val == null ) {
@@ -9033,7 +9040,8 @@ var
 
 	// Anchor tag for parsing the document origin
 	originAnchor = document.createElement( "a" );
-	originAnchor.href = location.href;
+
+originAnchor.href = location.href;
 
 // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
 function addToPrefiltersOrTransports( structure ) {
@@ -9414,8 +9422,8 @@ jQuery.extend( {
 			// Context for global events is callbackContext if it is a DOM node or jQuery collection
 			globalEventContext = s.context &&
 				( callbackContext.nodeType || callbackContext.jquery ) ?
-					jQuery( callbackContext ) :
-					jQuery.event,
+				jQuery( callbackContext ) :
+				jQuery.event,
 
 			// Deferreds
 			deferred = jQuery.Deferred(),
@@ -9727,8 +9735,10 @@ jQuery.extend( {
 				response = ajaxHandleResponses( s, jqXHR, responses );
 			}
 
-			// Use a noop converter for missing script
-			if ( !isSuccess && jQuery.inArray( "script", s.dataTypes ) > -1 ) {
+			// Use a noop converter for missing script but not if jsonp
+			if ( !isSuccess &&
+				jQuery.inArray( "script", s.dataTypes ) > -1 &&
+				jQuery.inArray( "json", s.dataTypes ) < 0 ) {
 				s.converters[ "text script" ] = function() {};
 			}
 
@@ -10466,12 +10476,6 @@ jQuery.offset = {
 			options.using.call( elem, props );
 
 		} else {
-			if ( typeof props.top === "number" ) {
-				props.top += "px";
-			}
-			if ( typeof props.left === "number" ) {
-				props.left += "px";
-			}
 			curElem.css( props );
 		}
 	}
@@ -10640,8 +10644,11 @@ jQuery.each( [ "top", "left" ], function( _i, prop ) {
 
 // Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
 jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
-	jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name },
-		function( defaultExtra, funcName ) {
+	jQuery.each( {
+		padding: "inner" + name,
+		content: type,
+		"": "outer" + name
+	}, function( defaultExtra, funcName ) {
 
 		// Margin is only for outerHeight, outerWidth
 		jQuery.fn[ funcName ] = function( margin, value ) {
@@ -10726,7 +10733,8 @@ jQuery.fn.extend( {
 	}
 } );
 
-jQuery.each( ( "blur focus focusin focusout resize scroll click dblclick " +
+jQuery.each(
+	( "blur focus focusin focusout resize scroll click dblclick " +
 	"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
 	"change select submit keydown keypress keyup contextmenu" ).split( " " ),
 	function( _i, name ) {
@@ -10737,7 +10745,8 @@ jQuery.each( ( "blur focus focusin focusout resize scroll click dblclick " +
 				this.on( name, null, data, fn ) :
 				this.trigger( name );
 		};
-	} );
+	}
+);
 
 
 
diff --git a/docs/apache-airflow-providers-sftp/4.0.0/_static/jquery.js b/docs/apache-airflow-providers-sftp/4.0.0/_static/jquery.js
new file mode 100644
index 0000000000..c4c6022f29
--- /dev/null
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_static/jquery.js
@@ -0,0 +1,2 @@
+/*! jQuery v3.6.0 | (c) OpenJS Foundation and other contributors | jquery.org/license */
+!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l= [...]
diff --git a/docs/apache-airflow-providers-sftp/4.0.0/_static/language_data.js b/docs/apache-airflow-providers-sftp/4.0.0/_static/language_data.js
new file mode 100644
index 0000000000..2e22b06ab1
--- /dev/null
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_static/language_data.js
@@ -0,0 +1,199 @@
+/*
+ * language_data.js
+ * ~~~~~~~~~~~~~~~~
+ *
+ * This script contains the language-specific data used by searchtools.js,
+ * namely the list of stopwords, stemmer, scorer and splitter.
+ *
+ * :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+var stopwords = ["a", "and", "are", "as", "at", "be", "but", "by", "for", "if", "in", "into", "is", "it", "near", "no", "not", "of", "on", "or", "such", "that", "the", "their", "then", "there", "these", "they", "this", "to", "was", "will", "with"];
+
+
+/* Non-minified version is copied as a separate JS file, is available */
+
+/**
+ * Porter Stemmer
+ */
+var Stemmer = function() {
+
+  var step2list = {
+    ational: 'ate',
+    tional: 'tion',
+    enci: 'ence',
+    anci: 'ance',
+    izer: 'ize',
+    bli: 'ble',
+    alli: 'al',
+    entli: 'ent',
+    eli: 'e',
+    ousli: 'ous',
+    ization: 'ize',
+    ation: 'ate',
+    ator: 'ate',
+    alism: 'al',
+    iveness: 'ive',
+    fulness: 'ful',
+    ousness: 'ous',
+    aliti: 'al',
+    iviti: 'ive',
+    biliti: 'ble',
+    logi: 'log'
+  };
+
+  var step3list = {
+    icate: 'ic',
+    ative: '',
+    alize: 'al',
+    iciti: 'ic',
+    ical: 'ic',
+    ful: '',
+    ness: ''
+  };
+
+  var c = "[^aeiou]";          // consonant
+  var v = "[aeiouy]";          // vowel
+  var C = c + "[^aeiouy]*";    // consonant sequence
+  var V = v + "[aeiou]*";      // vowel sequence
+
+  var mgr0 = "^(" + C + ")?" + V + C;                      // [C]VC... is m>0
+  var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$";    // [C]VC[V] is m=1
+  var mgr1 = "^(" + C + ")?" + V + C + V + C;              // [C]VCVC... is m>1
+  var s_v   = "^(" + C + ")?" + v;                         // vowel in stem
+
+  this.stemWord = function (w) {
+    var stem;
+    var suffix;
+    var firstch;
+    var origword = w;
+
+    if (w.length < 3)
+      return w;
+
+    var re;
+    var re2;
+    var re3;
+    var re4;
+
+    firstch = w.substr(0,1);
+    if (firstch == "y")
+      w = firstch.toUpperCase() + w.substr(1);
+
+    // Step 1a
+    re = /^(.+?)(ss|i)es$/;
+    re2 = /^(.+?)([^s])s$/;
+
+    if (re.test(w))
+      w = w.replace(re,"$1$2");
+    else if (re2.test(w))
+      w = w.replace(re2,"$1$2");
+
+    // Step 1b
+    re = /^(.+?)eed$/;
+    re2 = /^(.+?)(ed|ing)$/;
+    if (re.test(w)) {
+      var fp = re.exec(w);
+      re = new RegExp(mgr0);
+      if (re.test(fp[1])) {
+        re = /.$/;
+        w = w.replace(re,"");
+      }
+    }
+    else if (re2.test(w)) {
+      var fp = re2.exec(w);
+      stem = fp[1];
+      re2 = new RegExp(s_v);
+      if (re2.test(stem)) {
+        w = stem;
+        re2 = /(at|bl|iz)$/;
+        re3 = new RegExp("([^aeiouylsz])\\1$");
+        re4 = new RegExp("^" + C + v + "[^aeiouwxy]$");
+        if (re2.test(w))
+          w = w + "e";
+        else if (re3.test(w)) {
+          re = /.$/;
+          w = w.replace(re,"");
+        }
+        else if (re4.test(w))
+          w = w + "e";
+      }
+    }
+
+    // Step 1c
+    re = /^(.+?)y$/;
+    if (re.test(w)) {
+      var fp = re.exec(w);
+      stem = fp[1];
+      re = new RegExp(s_v);
+      if (re.test(stem))
+        w = stem + "i";
+    }
+
+    // Step 2
+    re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;
+    if (re.test(w)) {
+      var fp = re.exec(w);
+      stem = fp[1];
+      suffix = fp[2];
+      re = new RegExp(mgr0);
+      if (re.test(stem))
+        w = stem + step2list[suffix];
+    }
+
+    // Step 3
+    re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;
+    if (re.test(w)) {
+      var fp = re.exec(w);
+      stem = fp[1];
+      suffix = fp[2];
+      re = new RegExp(mgr0);
+      if (re.test(stem))
+        w = stem + step3list[suffix];
+    }
+
+    // Step 4
+    re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;
+    re2 = /^(.+?)(s|t)(ion)$/;
+    if (re.test(w)) {
+      var fp = re.exec(w);
+      stem = fp[1];
+      re = new RegExp(mgr1);
+      if (re.test(stem))
+        w = stem;
+    }
+    else if (re2.test(w)) {
+      var fp = re2.exec(w);
+      stem = fp[1] + fp[2];
+      re2 = new RegExp(mgr1);
+      if (re2.test(stem))
+        w = stem;
+    }
+
+    // Step 5
+    re = /^(.+?)e$/;
+    if (re.test(w)) {
+      var fp = re.exec(w);
+      stem = fp[1];
+      re = new RegExp(mgr1);
+      re2 = new RegExp(meq1);
+      re3 = new RegExp("^" + C + v + "[^aeiouwxy]$");
+      if (re.test(stem) || (re2.test(stem) && !(re3.test(stem))))
+        w = stem;
+    }
+    re = /ll$/;
+    re2 = new RegExp(mgr1);
+    if (re.test(w) && re2.test(w)) {
+      re = /.$/;
+      w = w.replace(re,"");
+    }
+
+    // and turn initial Y back to y
+    if (firstch == "y")
+      w = firstch.toLowerCase() + w.substr(1);
+    return w;
+  }
+}
+
diff --git a/docs/apache-airflow-providers-sftp/4.0.0/_static/minus.png b/docs/apache-airflow-providers-sftp/4.0.0/_static/minus.png
new file mode 100644
index 0000000000..d96755fdaf
Binary files /dev/null and b/docs/apache-airflow-providers-sftp/4.0.0/_static/minus.png differ
diff --git a/docs/apache-airflow-providers-sftp/4.0.0/_static/pin_32.png b/docs/apache-airflow-providers-sftp/4.0.0/_static/pin_32.png
new file mode 100644
index 0000000000..244ffc5bab
Binary files /dev/null and b/docs/apache-airflow-providers-sftp/4.0.0/_static/pin_32.png differ
diff --git a/docs/apache-airflow-providers-sftp/4.0.0/_static/plus.png b/docs/apache-airflow-providers-sftp/4.0.0/_static/plus.png
new file mode 100644
index 0000000000..7107cec93a
Binary files /dev/null and b/docs/apache-airflow-providers-sftp/4.0.0/_static/plus.png differ
diff --git a/docs/apache-airflow-providers-sftp/4.0.0/_static/pygments.css b/docs/apache-airflow-providers-sftp/4.0.0/_static/pygments.css
new file mode 100644
index 0000000000..08bec689d3
--- /dev/null
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_static/pygments.css
@@ -0,0 +1,74 @@
+pre { line-height: 125%; }
+td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
+span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
+td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
+span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
+.highlight .hll { background-color: #ffffcc }
+.highlight { background: #f8f8f8; }
+.highlight .c { color: #3D7B7B; font-style: italic } /* Comment */
+.highlight .err { border: 1px solid #FF0000 } /* Error */
+.highlight .k { color: #008000; font-weight: bold } /* Keyword */
+.highlight .o { color: #666666 } /* Operator */
+.highlight .ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */
+.highlight .cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */
+.highlight .cp { color: #9C6500 } /* Comment.Preproc */
+.highlight .cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */
+.highlight .c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */
+.highlight .cs { color: #3D7B7B; font-style: italic } /* Comment.Special */
+.highlight .gd { color: #A00000 } /* Generic.Deleted */
+.highlight .ge { font-style: italic } /* Generic.Emph */
+.highlight .gr { color: #E40000 } /* Generic.Error */
+.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
+.highlight .gi { color: #008400 } /* Generic.Inserted */
+.highlight .go { color: #717171 } /* Generic.Output */
+.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
+.highlight .gs { font-weight: bold } /* Generic.Strong */
+.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
+.highlight .gt { color: #0044DD } /* Generic.Traceback */
+.highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
+.highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
+.highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
+.highlight .kp { color: #008000 } /* Keyword.Pseudo */
+.highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
+.highlight .kt { color: #B00040 } /* Keyword.Type */
+.highlight .m { color: #666666 } /* Literal.Number */
+.highlight .s { color: #BA2121 } /* Literal.String */
+.highlight .na { color: #687822 } /* Name.Attribute */
+.highlight .nb { color: #008000 } /* Name.Builtin */
+.highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */
+.highlight .no { color: #880000 } /* Name.Constant */
+.highlight .nd { color: #AA22FF } /* Name.Decorator */
+.highlight .ni { color: #717171; font-weight: bold } /* Name.Entity */
+.highlight .ne { color: #CB3F38; font-weight: bold } /* Name.Exception */
+.highlight .nf { color: #0000FF } /* Name.Function */
+.highlight .nl { color: #767600 } /* Name.Label */
+.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
+.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */
+.highlight .nv { color: #19177C } /* Name.Variable */
+.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
+.highlight .w { color: #bbbbbb } /* Text.Whitespace */
+.highlight .mb { color: #666666 } /* Literal.Number.Bin */
+.highlight .mf { color: #666666 } /* Literal.Number.Float */
+.highlight .mh { color: #666666 } /* Literal.Number.Hex */
+.highlight .mi { color: #666666 } /* Literal.Number.Integer */
+.highlight .mo { color: #666666 } /* Literal.Number.Oct */
+.highlight .sa { color: #BA2121 } /* Literal.String.Affix */
+.highlight .sb { color: #BA2121 } /* Literal.String.Backtick */
+.highlight .sc { color: #BA2121 } /* Literal.String.Char */
+.highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */
+.highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
+.highlight .s2 { color: #BA2121 } /* Literal.String.Double */
+.highlight .se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */
+.highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */
+.highlight .si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */
+.highlight .sx { color: #008000 } /* Literal.String.Other */
+.highlight .sr { color: #A45A77 } /* Literal.String.Regex */
+.highlight .s1 { color: #BA2121 } /* Literal.String.Single */
+.highlight .ss { color: #19177C } /* Literal.String.Symbol */
+.highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */
+.highlight .fm { color: #0000FF } /* Name.Function.Magic */
+.highlight .vc { color: #19177C } /* Name.Variable.Class */
+.highlight .vg { color: #19177C } /* Name.Variable.Global */
+.highlight .vi { color: #19177C } /* Name.Variable.Instance */
+.highlight .vm { color: #19177C } /* Name.Variable.Magic */
+.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */
\ No newline at end of file
diff --git a/docs/apache-airflow-providers-sftp/4.0.0/_static/searchtools.js b/docs/apache-airflow-providers-sftp/4.0.0/_static/searchtools.js
new file mode 100644
index 0000000000..ac4d5861f9
--- /dev/null
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_static/searchtools.js
@@ -0,0 +1,531 @@
+/*
+ * searchtools.js
+ * ~~~~~~~~~~~~~~~~
+ *
+ * Sphinx JavaScript utilities for the full-text search.
+ *
+ * :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+"use strict";
+
+/**
+ * Simple result scoring code.
+ */
+if (typeof Scorer === "undefined") {
+  var Scorer = {
+    // Implement the following function to further tweak the score for each result
+    // The function takes a result array [docname, title, anchor, descr, score, filename]
+    // and returns the new score.
+    /*
+    score: result => {
+      const [docname, title, anchor, descr, score, filename] = result
+      return score
+    },
+    */
+
+    // query matches the full name of an object
+    objNameMatch: 11,
+    // or matches in the last dotted part of the object name
+    objPartialMatch: 6,
+    // Additive scores depending on the priority of the object
+    objPrio: {
+      0: 15, // used to be importantResults
+      1: 5, // used to be objectResults
+      2: -5, // used to be unimportantResults
+    },
+    //  Used when the priority is not in the mapping.
+    objPrioDefault: 0,
+
+    // query found in title
+    title: 15,
+    partialTitle: 7,
+    // query found in terms
+    term: 5,
+    partialTerm: 2,
+  };
+}
+
+const _removeChildren = (element) => {
+  while (element && element.lastChild) element.removeChild(element.lastChild);
+};
+
+/**
+ * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping
+ */
+const _escapeRegExp = (string) =>
+  string.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string
+
+const _displayItem = (item, highlightTerms, searchTerms) => {
+  const docBuilder = DOCUMENTATION_OPTIONS.BUILDER;
+  const docUrlRoot = DOCUMENTATION_OPTIONS.URL_ROOT;
+  const docFileSuffix = DOCUMENTATION_OPTIONS.FILE_SUFFIX;
+  const docLinkSuffix = DOCUMENTATION_OPTIONS.LINK_SUFFIX;
+  const showSearchSummary = DOCUMENTATION_OPTIONS.SHOW_SEARCH_SUMMARY;
+
+  const [docName, title, anchor, descr] = item;
+
+  let listItem = document.createElement("li");
+  let requestUrl;
+  let linkUrl;
+  if (docBuilder === "dirhtml") {
+    // dirhtml builder
+    let dirname = docName + "/";
+    if (dirname.match(/\/index\/$/))
+      dirname = dirname.substring(0, dirname.length - 6);
+    else if (dirname === "index/") dirname = "";
+    requestUrl = docUrlRoot + dirname;
+    linkUrl = requestUrl;
+  } else {
+    // normal html builders
+    requestUrl = docUrlRoot + docName + docFileSuffix;
+    linkUrl = docName + docLinkSuffix;
+  }
+  const params = new URLSearchParams();
+  params.set("highlight", [...highlightTerms].join(" "));
+  let linkEl = listItem.appendChild(document.createElement("a"));
+  linkEl.href = linkUrl + "?" + params.toString() + anchor;
+  linkEl.innerHTML = title;
+  if (descr)
+    listItem.appendChild(document.createElement("span")).innerText =
+      " (" + descr + ")";
+  else if (showSearchSummary)
+    fetch(requestUrl)
+      .then((responseData) => responseData.text())
+      .then((data) => {
+        if (data)
+          listItem.appendChild(
+            Search.makeSearchSummary(data, searchTerms, highlightTerms)
+          );
+      });
+  Search.output.appendChild(listItem);
+};
+const _finishSearch = (resultCount) => {
+  Search.stopPulse();
+  Search.title.innerText = _("Search Results");
+  if (!resultCount)
+    Search.status.innerText = Documentation.gettext(
+      "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories."
+    );
+  else
+    Search.status.innerText = _(
+      `Search finished, found ${resultCount} page(s) matching the search query.`
+    );
+};
+const _displayNextItem = (
+  results,
+  resultCount,
+  highlightTerms,
+  searchTerms
+) => {
+  // results left, load the summary and display it
+  // this is intended to be dynamic (don't sub resultsCount)
+  if (results.length) {
+    _displayItem(results.pop(), highlightTerms, searchTerms);
+    setTimeout(
+      () => _displayNextItem(results, resultCount, highlightTerms, searchTerms),
+      5
+    );
+  }
+  // search finished, update title and status message
+  else _finishSearch(resultCount);
+};
+
+/**
+ * Default splitQuery function. Can be overridden in ``sphinx.search`` with a
+ * custom function per language.
+ *
+ * The regular expression works by splitting the string on consecutive characters
+ * that are not Unicode letters, numbers, underscores, or emoji characters.
+ * This is the same as ``\W+`` in Python, preserving the surrogate pair area.
+ */
+if (typeof splitQuery === "undefined") {
+  var splitQuery = (query) => query
+      .split(/[^\p{Letter}\p{Number}_\p{Emoji_Presentation}]+/gu)
+      .filter(term => term)  // remove remaining empty strings
+}
+
+/**
+ * Search Module
+ */
+const Search = {
+  _index: null,
+  _queued_query: null,
+  _pulse_status: -1,
+
+  htmlToText: (htmlString) => {
+    const htmlElement = document
+      .createRange()
+      .createContextualFragment(htmlString);
+    _removeChildren(htmlElement.querySelectorAll(".headerlink"));
+    const docContent = htmlElement.querySelector('[role="main"]');
+    if (docContent !== undefined) return docContent.textContent;
+    console.warn(
+      "Content block not found. Sphinx search tries to obtain it via '[role=main]'. Could you check your theme or template."
+    );
+    return "";
+  },
+
+  init: () => {
+    const query = new URLSearchParams(window.location.search).get("q");
+    document
+      .querySelectorAll('input[name="q"]')
+      .forEach((el) => (el.value = query));
+    if (query) Search.performSearch(query);
+  },
+
+  loadIndex: (url) =>
+    (document.body.appendChild(document.createElement("script")).src = url),
+
+  setIndex: (index) => {
+    Search._index = index;
+    if (Search._queued_query !== null) {
+      const query = Search._queued_query;
+      Search._queued_query = null;
+      Search.query(query);
+    }
+  },
+
+  hasIndex: () => Search._index !== null,
+
+  deferQuery: (query) => (Search._queued_query = query),
+
+  stopPulse: () => (Search._pulse_status = -1),
+
+  startPulse: () => {
+    if (Search._pulse_status >= 0) return;
+
+    const pulse = () => {
+      Search._pulse_status = (Search._pulse_status + 1) % 4;
+      Search.dots.innerText = ".".repeat(Search._pulse_status);
+      if (Search._pulse_status >= 0) window.setTimeout(pulse, 500);
+    };
+    pulse();
+  },
+
+  /**
+   * perform a search for something (or wait until index is loaded)
+   */
+  performSearch: (query) => {
+    // create the required interface elements
+    const searchText = document.createElement("h2");
+    searchText.textContent = _("Searching");
+    const searchSummary = document.createElement("p");
+    searchSummary.classList.add("search-summary");
+    searchSummary.innerText = "";
+    const searchList = document.createElement("ul");
+    searchList.classList.add("search");
+
+    const out = document.getElementById("search-results");
+    Search.title = out.appendChild(searchText);
+    Search.dots = Search.title.appendChild(document.createElement("span"));
+    Search.status = out.appendChild(searchSummary);
+    Search.output = out.appendChild(searchList);
+
+    const searchProgress = document.getElementById("search-progress");
+    // Some themes don't use the search progress node
+    if (searchProgress) {
+      searchProgress.innerText = _("Preparing search...");
+    }
+    Search.startPulse();
+
+    // index already loaded, the browser was quick!
+    if (Search.hasIndex()) Search.query(query);
+    else Search.deferQuery(query);
+  },
+
+  /**
+   * execute search (requires search index to be loaded)
+   */
+  query: (query) => {
+    // stem the search terms and add them to the correct list
+    const stemmer = new Stemmer();
+    const searchTerms = new Set();
+    const excludedTerms = new Set();
+    const highlightTerms = new Set();
+    const objectTerms = new Set(splitQuery(query.toLowerCase().trim()));
+    splitQuery(query.trim()).forEach((queryTerm) => {
+      const queryTermLower = queryTerm.toLowerCase();
+
+      // maybe skip this "word"
+      // stopwords array is from language_data.js
+      if (
+        stopwords.indexOf(queryTermLower) !== -1 ||
+        queryTerm.match(/^\d+$/)
+      )
+        return;
+
+      // stem the word
+      let word = stemmer.stemWord(queryTermLower);
+      // select the correct list
+      if (word[0] === "-") excludedTerms.add(word.substr(1));
+      else {
+        searchTerms.add(word);
+        highlightTerms.add(queryTermLower);
+      }
+    });
+
+    // console.debug("SEARCH: searching for:");
+    // console.info("required: ", [...searchTerms]);
+    // console.info("excluded: ", [...excludedTerms]);
+
+    // array of [docname, title, anchor, descr, score, filename]
+    let results = [];
+    _removeChildren(document.getElementById("search-progress"));
+
+    // lookup as object
+    objectTerms.forEach((term) =>
+      results.push(...Search.performObjectSearch(term, objectTerms))
+    );
+
+    // lookup as search terms in fulltext
+    results.push(...Search.performTermsSearch(searchTerms, excludedTerms));
+
+    // let the scorer override scores with a custom scoring function
+    if (Scorer.score) results.forEach((item) => (item[4] = Scorer.score(item)));
+
+    // now sort the results by score (in opposite order of appearance, since the
+    // display function below uses pop() to retrieve items) and then
+    // alphabetically
+    results.sort((a, b) => {
+      const leftScore = a[4];
+      const rightScore = b[4];
+      if (leftScore === rightScore) {
+        // same score: sort alphabetically
+        const leftTitle = a[1].toLowerCase();
+        const rightTitle = b[1].toLowerCase();
+        if (leftTitle === rightTitle) return 0;
+        return leftTitle > rightTitle ? -1 : 1; // inverted is intentional
+      }
+      return leftScore > rightScore ? 1 : -1;
+    });
+
+    // remove duplicate search results
+    // note the reversing of results, so that in the case of duplicates, the highest-scoring entry is kept
+    let seen = new Set();
+    results = results.reverse().reduce((acc, result) => {
+      let resultStr = result.slice(0, 4).concat([result[5]]).map(v => String(v)).join(',');
+      if (!seen.has(resultStr)) {
+        acc.push(result);
+        seen.add(resultStr);
+      }
+      return acc;
+    }, []);
+
+    results = results.reverse();
+
+    // for debugging
+    //Search.lastresults = results.slice();  // a copy
+    // console.info("search results:", Search.lastresults);
+
+    // print the results
+    _displayNextItem(results, results.length, highlightTerms, searchTerms);
+  },
+
+  /**
+   * search for object names
+   */
+  performObjectSearch: (object, objectTerms) => {
+    const filenames = Search._index.filenames;
+    const docNames = Search._index.docnames;
+    const objects = Search._index.objects;
+    const objNames = Search._index.objnames;
+    const titles = Search._index.titles;
+
+    const results = [];
+
+    const objectSearchCallback = (prefix, match) => {
+      const name = match[4]
+      const fullname = (prefix ? prefix + "." : "") + name;
+      const fullnameLower = fullname.toLowerCase();
+      if (fullnameLower.indexOf(object) < 0) return;
+
+      let score = 0;
+      const parts = fullnameLower.split(".");
+
+      // check for different match types: exact matches of full name or
+      // "last name" (i.e. last dotted part)
+      if (fullnameLower === object || parts.slice(-1)[0] === object)
+        score += Scorer.objNameMatch;
+      else if (parts.slice(-1)[0].indexOf(object) > -1)
+        score += Scorer.objPartialMatch; // matches in last name
+
+      const objName = objNames[match[1]][2];
+      const title = titles[match[0]];
+
+      // If more than one term searched for, we require other words to be
+      // found in the name/title/description
+      const otherTerms = new Set(objectTerms);
+      otherTerms.delete(object);
+      if (otherTerms.size > 0) {
+        const haystack = `${prefix} ${name} ${objName} ${title}`.toLowerCase();
+        if (
+          [...otherTerms].some((otherTerm) => haystack.indexOf(otherTerm) < 0)
+        )
+          return;
+      }
+
+      let anchor = match[3];
+      if (anchor === "") anchor = fullname;
+      else if (anchor === "-") anchor = objNames[match[1]][1] + "-" + fullname;
+
+      const descr = objName + _(", in ") + title;
+
+      // add custom score for some objects according to scorer
+      if (Scorer.objPrio.hasOwnProperty(match[2]))
+        score += Scorer.objPrio[match[2]];
+      else score += Scorer.objPrioDefault;
+
+      results.push([
+        docNames[match[0]],
+        fullname,
+        "#" + anchor,
+        descr,
+        score,
+        filenames[match[0]],
+      ]);
+    };
+    Object.keys(objects).forEach((prefix) =>
+      objects[prefix].forEach((array) =>
+        objectSearchCallback(prefix, array)
+      )
+    );
+    return results;
+  },
+
+  /**
+   * search for full-text terms in the index
+   */
+  performTermsSearch: (searchTerms, excludedTerms) => {
+    // prepare search
+    const terms = Search._index.terms;
+    const titleTerms = Search._index.titleterms;
+    const docNames = Search._index.docnames;
+    const filenames = Search._index.filenames;
+    const titles = Search._index.titles;
+
+    const scoreMap = new Map();
+    const fileMap = new Map();
+
+    // perform the search on the required terms
+    searchTerms.forEach((word) => {
+      const files = [];
+      const arr = [
+        { files: terms[word], score: Scorer.term },
+        { files: titleTerms[word], score: Scorer.title },
+      ];
+      // add support for partial matches
+      if (word.length > 2) {
+        const escapedWord = _escapeRegExp(word);
+        Object.keys(terms).forEach((term) => {
+          if (term.match(escapedWord) && !terms[word])
+            arr.push({ files: terms[term], score: Scorer.partialTerm });
+        });
+        Object.keys(titleTerms).forEach((term) => {
+          if (term.match(escapedWord) && !titleTerms[word])
+            arr.push({ files: titleTerms[word], score: Scorer.partialTitle });
+        });
+      }
+
+      // no match but word was a required one
+      if (arr.every((record) => record.files === undefined)) return;
+
+      // found search word in contents
+      arr.forEach((record) => {
+        if (record.files === undefined) return;
+
+        let recordFiles = record.files;
+        if (recordFiles.length === undefined) recordFiles = [recordFiles];
+        files.push(...recordFiles);
+
+        // set score for the word in each file
+        recordFiles.forEach((file) => {
+          if (!scoreMap.has(file)) scoreMap.set(file, {});
+          scoreMap.get(file)[word] = record.score;
+        });
+      });
+
+      // create the mapping
+      files.forEach((file) => {
+        if (fileMap.has(file) && fileMap.get(file).indexOf(word) === -1)
+          fileMap.get(file).push(word);
+        else fileMap.set(file, [word]);
+      });
+    });
+
+    // now check if the files don't contain excluded terms
+    const results = [];
+    for (const [file, wordList] of fileMap) {
+      // check if all requirements are matched
+
+      // as search terms with length < 3 are discarded
+      const filteredTermCount = [...searchTerms].filter(
+        (term) => term.length > 2
+      ).length;
+      if (
+        wordList.length !== searchTerms.size &&
+        wordList.length !== filteredTermCount
+      )
+        continue;
+
+      // ensure that none of the excluded terms is in the search result
+      if (
+        [...excludedTerms].some(
+          (term) =>
+            terms[term] === file ||
+            titleTerms[term] === file ||
+            (terms[term] || []).includes(file) ||
+            (titleTerms[term] || []).includes(file)
+        )
+      )
+        break;
+
+      // select one (max) score for the file.
+      const score = Math.max(...wordList.map((w) => scoreMap.get(file)[w]));
+      // add result to the result list
+      results.push([
+        docNames[file],
+        titles[file],
+        "",
+        null,
+        score,
+        filenames[file],
+      ]);
+    }
+    return results;
+  },
+
+  /**
+   * helper function to return a node containing the
+   * search summary for a given text. keywords is a list
+   * of stemmed words, highlightWords is the list of normal, unstemmed
+   * words. the first one is used to find the occurrence, the
+   * latter for highlighting it.
+   */
+  makeSearchSummary: (htmlText, keywords, highlightWords) => {
+    const text = Search.htmlToText(htmlText).toLowerCase();
+    if (text === "") return null;
+
+    const actualStartPosition = [...keywords]
+      .map((k) => text.indexOf(k.toLowerCase()))
+      .filter((i) => i > -1)
+      .slice(-1)[0];
+    const startWithContext = Math.max(actualStartPosition - 120, 0);
+
+    const top = startWithContext === 0 ? "" : "...";
+    const tail = startWithContext + 240 < text.length ? "..." : "";
+
+    let summary = document.createElement("div");
+    summary.classList.add("context");
+    summary.innerText = top + text.substr(startWithContext, 240).trim() + tail;
+
+    highlightWords.forEach((highlightWord) =>
+      _highlightText(summary, highlightWord, "highlighted")
+    );
+
+    return summary;
+  },
+};
+
+_ready(Search.init);
diff --git a/docs/apache-airflow-providers-sftp/4.0.0/_static/underscore-1.13.1.js b/docs/apache-airflow-providers-sftp/4.0.0/_static/underscore-1.13.1.js
new file mode 100644
index 0000000000..ffd77af964
--- /dev/null
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_static/underscore-1.13.1.js
@@ -0,0 +1,2042 @@
+(function (global, factory) {
+  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+  typeof define === 'function' && define.amd ? define('underscore', factory) :
+  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, (function () {
+    var current = global._;
+    var exports = global._ = factory();
+    exports.noConflict = function () { global._ = current; return exports; };
+  }()));
+}(this, (function () {
+  //     Underscore.js 1.13.1
+  //     https://underscorejs.org
+  //     (c) 2009-2021 Jeremy Ashkenas, Julian Gonggrijp, and DocumentCloud and Investigative Reporters & Editors
+  //     Underscore may be freely distributed under the MIT license.
+
+  // Current version.
+  var VERSION = '1.13.1';
+
+  // Establish the root object, `window` (`self`) in the browser, `global`
+  // on the server, or `this` in some virtual machines. We use `self`
+  // instead of `window` for `WebWorker` support.
+  var root = typeof self == 'object' && self.self === self && self ||
+            typeof global == 'object' && global.global === global && global ||
+            Function('return this')() ||
+            {};
+
+  // Save bytes in the minified (but not gzipped) version:
+  var ArrayProto = Array.prototype, ObjProto = Object.prototype;
+  var SymbolProto = typeof Symbol !== 'undefined' ? Symbol.prototype : null;
+
+  // Create quick reference variables for speed access to core prototypes.
+  var push = ArrayProto.push,
+      slice = ArrayProto.slice,
+      toString = ObjProto.toString,
+      hasOwnProperty = ObjProto.hasOwnProperty;
+
+  // Modern feature detection.
+  var supportsArrayBuffer = typeof ArrayBuffer !== 'undefined',
+      supportsDataView = typeof DataView !== 'undefined';
+
+  // All **ECMAScript 5+** native function implementations that we hope to use
+  // are declared here.
+  var nativeIsArray = Array.isArray,
+      nativeKeys = Object.keys,
+      nativeCreate = Object.create,
+      nativeIsView = supportsArrayBuffer && ArrayBuffer.isView;
+
+  // Create references to these builtin functions because we override them.
+  var _isNaN = isNaN,
+      _isFinite = isFinite;
+
+  // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed.
+  var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString');
+  var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',
+    'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];
+
+  // The largest integer that can be represented exactly.
+  var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
+
+  // Some functions take a variable number of arguments, or a few expected
+  // arguments at the beginning and then a variable number of values to operate
+  // on. This helper accumulates all remaining arguments past the function’s
+  // argument length (or an explicit `startIndex`), into an array that becomes
+  // the last argument. Similar to ES6’s "rest parameter".
+  function restArguments(func, startIndex) {
+    startIndex = startIndex == null ? func.length - 1 : +startIndex;
+    return function() {
+      var length = Math.max(arguments.length - startIndex, 0),
+          rest = Array(length),
+          index = 0;
+      for (; index < length; index++) {
+        rest[index] = arguments[index + startIndex];
+      }
+      switch (startIndex) {
+        case 0: return func.call(this, rest);
+        case 1: return func.call(this, arguments[0], rest);
+        case 2: return func.call(this, arguments[0], arguments[1], rest);
+      }
+      var args = Array(startIndex + 1);
+      for (index = 0; index < startIndex; index++) {
+        args[index] = arguments[index];
+      }
+      args[startIndex] = rest;
+      return func.apply(this, args);
+    };
+  }
+
+  // Is a given variable an object?
+  function isObject(obj) {
+    var type = typeof obj;
+    return type === 'function' || type === 'object' && !!obj;
+  }
+
+  // Is a given value equal to null?
+  function isNull(obj) {
+    return obj === null;
+  }
+
+  // Is a given variable undefined?
+  function isUndefined(obj) {
+    return obj === void 0;
+  }
+
+  // Is a given value a boolean?
+  function isBoolean(obj) {
+    return obj === true || obj === false || toString.call(obj) === '[object Boolean]';
+  }
+
+  // Is a given value a DOM element?
+  function isElement(obj) {
+    return !!(obj && obj.nodeType === 1);
+  }
+
+  // Internal function for creating a `toString`-based type tester.
+  function tagTester(name) {
+    var tag = '[object ' + name + ']';
+    return function(obj) {
+      return toString.call(obj) === tag;
+    };
+  }
+
+  var isString = tagTester('String');
+
+  var isNumber = tagTester('Number');
+
+  var isDate = tagTester('Date');
+
+  var isRegExp = tagTester('RegExp');
+
+  var isError = tagTester('Error');
+
+  var isSymbol = tagTester('Symbol');
+
+  var isArrayBuffer = tagTester('ArrayBuffer');
+
+  var isFunction = tagTester('Function');
+
+  // Optimize `isFunction` if appropriate. Work around some `typeof` bugs in old
+  // v8, IE 11 (#1621), Safari 8 (#1929), and PhantomJS (#2236).
+  var nodelist = root.document && root.document.childNodes;
+  if (typeof /./ != 'function' && typeof Int8Array != 'object' && typeof nodelist != 'function') {
+    isFunction = function(obj) {
+      return typeof obj == 'function' || false;
+    };
+  }
+
+  var isFunction$1 = isFunction;
+
+  var hasObjectTag = tagTester('Object');
+
+  // In IE 10 - Edge 13, `DataView` has string tag `'[object Object]'`.
+  // In IE 11, the most common among them, this problem also applies to
+  // `Map`, `WeakMap` and `Set`.
+  var hasStringTagBug = (
+        supportsDataView && hasObjectTag(new DataView(new ArrayBuffer(8)))
+      ),
+      isIE11 = (typeof Map !== 'undefined' && hasObjectTag(new Map));
+
+  var isDataView = tagTester('DataView');
+
+  // In IE 10 - Edge 13, we need a different heuristic
+  // to determine whether an object is a `DataView`.
+  function ie10IsDataView(obj) {
+    return obj != null && isFunction$1(obj.getInt8) && isArrayBuffer(obj.buffer);
+  }
+
+  var isDataView$1 = (hasStringTagBug ? ie10IsDataView : isDataView);
+
+  // Is a given value an array?
+  // Delegates to ECMA5's native `Array.isArray`.
+  var isArray = nativeIsArray || tagTester('Array');
+
+  // Internal function to check whether `key` is an own property name of `obj`.
+  function has$1(obj, key) {
+    return obj != null && hasOwnProperty.call(obj, key);
+  }
+
+  var isArguments = tagTester('Arguments');
+
+  // Define a fallback version of the method in browsers (ahem, IE < 9), where
+  // there isn't any inspectable "Arguments" type.
+  (function() {
+    if (!isArguments(arguments)) {
+      isArguments = function(obj) {
+        return has$1(obj, 'callee');
+      };
+    }
+  }());
+
+  var isArguments$1 = isArguments;
+
+  // Is a given object a finite number?
+  function isFinite$1(obj) {
+    return !isSymbol(obj) && _isFinite(obj) && !isNaN(parseFloat(obj));
+  }
+
+  // Is the given value `NaN`?
+  function isNaN$1(obj) {
+    return isNumber(obj) && _isNaN(obj);
+  }
+
+  // Predicate-generating function. Often useful outside of Underscore.
+  function constant(value) {
+    return function() {
+      return value;
+    };
+  }
+
+  // Common internal logic for `isArrayLike` and `isBufferLike`.
+  function createSizePropertyCheck(getSizeProperty) {
+    return function(collection) {
+      var sizeProperty = getSizeProperty(collection);
+      return typeof sizeProperty == 'number' && sizeProperty >= 0 && sizeProperty <= MAX_ARRAY_INDEX;
+    }
+  }
+
+  // Internal helper to generate a function to obtain property `key` from `obj`.
+  function shallowProperty(key) {
+    return function(obj) {
+      return obj == null ? void 0 : obj[key];
+    };
+  }
+
+  // Internal helper to obtain the `byteLength` property of an object.
+  var getByteLength = shallowProperty('byteLength');
+
+  // Internal helper to determine whether we should spend extensive checks against
+  // `ArrayBuffer` et al.
+  var isBufferLike = createSizePropertyCheck(getByteLength);
+
+  // Is a given value a typed array?
+  var typedArrayPattern = /\[object ((I|Ui)nt(8|16|32)|Float(32|64)|Uint8Clamped|Big(I|Ui)nt64)Array\]/;
+  function isTypedArray(obj) {
+    // `ArrayBuffer.isView` is the most future-proof, so use it when available.
+    // Otherwise, fall back on the above regular expression.
+    return nativeIsView ? (nativeIsView(obj) && !isDataView$1(obj)) :
+                  isBufferLike(obj) && typedArrayPattern.test(toString.call(obj));
+  }
+
+  var isTypedArray$1 = supportsArrayBuffer ? isTypedArray : constant(false);
+
+  // Internal helper to obtain the `length` property of an object.
+  var getLength = shallowProperty('length');
+
+  // Internal helper to create a simple lookup structure.
+  // `collectNonEnumProps` used to depend on `_.contains`, but this led to
+  // circular imports. `emulatedSet` is a one-off solution that only works for
+  // arrays of strings.
+  function emulatedSet(keys) {
+    var hash = {};
+    for (var l = keys.length, i = 0; i < l; ++i) hash[keys[i]] = true;
+    return {
+      contains: function(key) { return hash[key]; },
+      push: function(key) {
+        hash[key] = true;
+        return keys.push(key);
+      }
+    };
+  }
+
+  // Internal helper. Checks `keys` for the presence of keys in IE < 9 that won't
+  // be iterated by `for key in ...` and thus missed. Extends `keys` in place if
+  // needed.
+  function collectNonEnumProps(obj, keys) {
+    keys = emulatedSet(keys);
+    var nonEnumIdx = nonEnumerableProps.length;
+    var constructor = obj.constructor;
+    var proto = isFunction$1(constructor) && constructor.prototype || ObjProto;
+
+    // Constructor is a special case.
+    var prop = 'constructor';
+    if (has$1(obj, prop) && !keys.contains(prop)) keys.push(prop);
+
+    while (nonEnumIdx--) {
+      prop = nonEnumerableProps[nonEnumIdx];
+      if (prop in obj && obj[prop] !== proto[prop] && !keys.contains(prop)) {
+        keys.push(prop);
+      }
+    }
+  }
+
+  // Retrieve the names of an object's own properties.
+  // Delegates to **ECMAScript 5**'s native `Object.keys`.
+  function keys(obj) {
+    if (!isObject(obj)) return [];
+    if (nativeKeys) return nativeKeys(obj);
+    var keys = [];
+    for (var key in obj) if (has$1(obj, key)) keys.push(key);
+    // Ahem, IE < 9.
+    if (hasEnumBug) collectNonEnumProps(obj, keys);
+    return keys;
+  }
+
+  // Is a given array, string, or object empty?
+  // An "empty" object has no enumerable own-properties.
+  function isEmpty(obj) {
+    if (obj == null) return true;
+    // Skip the more expensive `toString`-based type checks if `obj` has no
+    // `.length`.
+    var length = getLength(obj);
+    if (typeof length == 'number' && (
+      isArray(obj) || isString(obj) || isArguments$1(obj)
+    )) return length === 0;
+    return getLength(keys(obj)) === 0;
+  }
+
+  // Returns whether an object has a given set of `key:value` pairs.
+  function isMatch(object, attrs) {
+    var _keys = keys(attrs), length = _keys.length;
+    if (object == null) return !length;
+    var obj = Object(object);
+    for (var i = 0; i < length; i++) {
+      var key = _keys[i];
+      if (attrs[key] !== obj[key] || !(key in obj)) return false;
+    }
+    return true;
+  }
+
+  // If Underscore is called as a function, it returns a wrapped object that can
+  // be used OO-style. This wrapper holds altered versions of all functions added
+  // through `_.mixin`. Wrapped objects may be chained.
+  function _$1(obj) {
+    if (obj instanceof _$1) return obj;
+    if (!(this instanceof _$1)) return new _$1(obj);
+    this._wrapped = obj;
+  }
+
+  _$1.VERSION = VERSION;
+
+  // Extracts the result from a wrapped and chained object.
+  _$1.prototype.value = function() {
+    return this._wrapped;
+  };
+
+  // Provide unwrapping proxies for some methods used in engine operations
+  // such as arithmetic and JSON stringification.
+  _$1.prototype.valueOf = _$1.prototype.toJSON = _$1.prototype.value;
+
+  _$1.prototype.toString = function() {
+    return String(this._wrapped);
+  };
+
+  // Internal function to wrap or shallow-copy an ArrayBuffer,
+  // typed array or DataView to a new view, reusing the buffer.
+  function toBufferView(bufferSource) {
+    return new Uint8Array(
+      bufferSource.buffer || bufferSource,
+      bufferSource.byteOffset || 0,
+      getByteLength(bufferSource)
+    );
+  }
+
+  // We use this string twice, so give it a name for minification.
+  var tagDataView = '[object DataView]';
+
+  // Internal recursive comparison function for `_.isEqual`.
+  function eq(a, b, aStack, bStack) {
+    // Identical objects are equal. `0 === -0`, but they aren't identical.
+    // See the [Harmony `egal` proposal](https://wiki.ecmascript.org/doku.php?id=harmony:egal).
+    if (a === b) return a !== 0 || 1 / a === 1 / b;
+    // `null` or `undefined` only equal to itself (strict comparison).
+    if (a == null || b == null) return false;
+    // `NaN`s are equivalent, but non-reflexive.
+    if (a !== a) return b !== b;
+    // Exhaust primitive checks
+    var type = typeof a;
+    if (type !== 'function' && type !== 'object' && typeof b != 'object') return false;
+    return deepEq(a, b, aStack, bStack);
+  }
+
+  // Internal recursive comparison function for `_.isEqual`.
+  function deepEq(a, b, aStack, bStack) {
+    // Unwrap any wrapped objects.
+    if (a instanceof _$1) a = a._wrapped;
+    if (b instanceof _$1) b = b._wrapped;
+    // Compare `[[Class]]` names.
+    var className = toString.call(a);
+    if (className !== toString.call(b)) return false;
+    // Work around a bug in IE 10 - Edge 13.
+    if (hasStringTagBug && className == '[object Object]' && isDataView$1(a)) {
+      if (!isDataView$1(b)) return false;
+      className = tagDataView;
+    }
+    switch (className) {
+      // These types are compared by value.
+      case '[object RegExp]':
+        // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
+      case '[object String]':
+        // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
+        // equivalent to `new String("5")`.
+        return '' + a === '' + b;
+      case '[object Number]':
+        // `NaN`s are equivalent, but non-reflexive.
+        // Object(NaN) is equivalent to NaN.
+        if (+a !== +a) return +b !== +b;
+        // An `egal` comparison is performed for other numeric values.
+        return +a === 0 ? 1 / +a === 1 / b : +a === +b;
+      case '[object Date]':
+      case '[object Boolean]':
+        // Coerce dates and booleans to numeric primitive values. Dates are compared by their
+        // millisecond representations. Note that invalid dates with millisecond representations
+        // of `NaN` are not equivalent.
+        return +a === +b;
+      case '[object Symbol]':
+        return SymbolProto.valueOf.call(a) === SymbolProto.valueOf.call(b);
+      case '[object ArrayBuffer]':
+      case tagDataView:
+        // Coerce to typed array so we can fall through.
+        return deepEq(toBufferView(a), toBufferView(b), aStack, bStack);
+    }
+
+    var areArrays = className === '[object Array]';
+    if (!areArrays && isTypedArray$1(a)) {
+        var byteLength = getByteLength(a);
+        if (byteLength !== getByteLength(b)) return false;
+        if (a.buffer === b.buffer && a.byteOffset === b.byteOffset) return true;
+        areArrays = true;
+    }
+    if (!areArrays) {
+      if (typeof a != 'object' || typeof b != 'object') return false;
+
+      // Objects with different constructors are not equivalent, but `Object`s or `Array`s
+      // from different frames are.
+      var aCtor = a.constructor, bCtor = b.constructor;
+      if (aCtor !== bCtor && !(isFunction$1(aCtor) && aCtor instanceof aCtor &&
+                               isFunction$1(bCtor) && bCtor instanceof bCtor)
+                          && ('constructor' in a && 'constructor' in b)) {
+        return false;
+      }
+    }
+    // Assume equality for cyclic structures. The algorithm for detecting cyclic
+    // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
+
+    // Initializing stack of traversed objects.
+    // It's done here since we only need them for objects and arrays comparison.
+    aStack = aStack || [];
+    bStack = bStack || [];
+    var length = aStack.length;
+    while (length--) {
+      // Linear search. Performance is inversely proportional to the number of
+      // unique nested structures.
+      if (aStack[length] === a) return bStack[length] === b;
+    }
+
+    // Add the first object to the stack of traversed objects.
+    aStack.push(a);
+    bStack.push(b);
+
+    // Recursively compare objects and arrays.
+    if (areArrays) {
+      // Compare array lengths to determine if a deep comparison is necessary.
+      length = a.length;
+      if (length !== b.length) return false;
+      // Deep compare the contents, ignoring non-numeric properties.
+      while (length--) {
+        if (!eq(a[length], b[length], aStack, bStack)) return false;
+      }
+    } else {
+      // Deep compare objects.
+      var _keys = keys(a), key;
+      length = _keys.length;
+      // Ensure that both objects contain the same number of properties before comparing deep equality.
+      if (keys(b).length !== length) return false;
+      while (length--) {
+        // Deep compare each member
+        key = _keys[length];
+        if (!(has$1(b, key) && eq(a[key], b[key], aStack, bStack))) return false;
+      }
+    }
+    // Remove the first object from the stack of traversed objects.
+    aStack.pop();
+    bStack.pop();
+    return true;
+  }
+
+  // Perform a deep comparison to check if two objects are equal.
+  function isEqual(a, b) {
+    return eq(a, b);
+  }
+
+  // Retrieve all the enumerable property names of an object.
+  function allKeys(obj) {
+    if (!isObject(obj)) return [];
+    var keys = [];
+    for (var key in obj) keys.push(key);
+    // Ahem, IE < 9.
+    if (hasEnumBug) collectNonEnumProps(obj, keys);
+    return keys;
+  }
+
+  // Since the regular `Object.prototype.toString` type tests don't work for
+  // some types in IE 11, we use a fingerprinting heuristic instead, based
+  // on the methods. It's not great, but it's the best we got.
+  // The fingerprint method lists are defined below.
+  function ie11fingerprint(methods) {
+    var length = getLength(methods);
+    return function(obj) {
+      if (obj == null) return false;
+      // `Map`, `WeakMap` and `Set` have no enumerable keys.
+      var keys = allKeys(obj);
+      if (getLength(keys)) return false;
+      for (var i = 0; i < length; i++) {
+        if (!isFunction$1(obj[methods[i]])) return false;
+      }
+      // If we are testing against `WeakMap`, we need to ensure that
+      // `obj` doesn't have a `forEach` method in order to distinguish
+      // it from a regular `Map`.
+      return methods !== weakMapMethods || !isFunction$1(obj[forEachName]);
+    };
+  }
+
+  // In the interest of compact minification, we write
+  // each string in the fingerprints only once.
+  var forEachName = 'forEach',
+      hasName = 'has',
+      commonInit = ['clear', 'delete'],
+      mapTail = ['get', hasName, 'set'];
+
+  // `Map`, `WeakMap` and `Set` each have slightly different
+  // combinations of the above sublists.
+  var mapMethods = commonInit.concat(forEachName, mapTail),
+      weakMapMethods = commonInit.concat(mapTail),
+      setMethods = ['add'].concat(commonInit, forEachName, hasName);
+
+  var isMap = isIE11 ? ie11fingerprint(mapMethods) : tagTester('Map');
+
+  var isWeakMap = isIE11 ? ie11fingerprint(weakMapMethods) : tagTester('WeakMap');
+
+  var isSet = isIE11 ? ie11fingerprint(setMethods) : tagTester('Set');
+
+  var isWeakSet = tagTester('WeakSet');
+
+  // Retrieve the values of an object's properties.
+  function values(obj) {
+    var _keys = keys(obj);
+    var length = _keys.length;
+    var values = Array(length);
+    for (var i = 0; i < length; i++) {
+      values[i] = obj[_keys[i]];
+    }
+    return values;
+  }
+
+  // Convert an object into a list of `[key, value]` pairs.
+  // The opposite of `_.object` with one argument.
+  function pairs(obj) {
+    var _keys = keys(obj);
+    var length = _keys.length;
+    var pairs = Array(length);
+    for (var i = 0; i < length; i++) {
+      pairs[i] = [_keys[i], obj[_keys[i]]];
+    }
+    return pairs;
+  }
+
+  // Invert the keys and values of an object. The values must be serializable.
+  function invert(obj) {
+    var result = {};
+    var _keys = keys(obj);
+    for (var i = 0, length = _keys.length; i < length; i++) {
+      result[obj[_keys[i]]] = _keys[i];
+    }
+    return result;
+  }
+
+  // Return a sorted list of the function names available on the object.
+  function functions(obj) {
+    var names = [];
+    for (var key in obj) {
+      if (isFunction$1(obj[key])) names.push(key);
+    }
+    return names.sort();
+  }
+
+  // An internal function for creating assigner functions.
+  function createAssigner(keysFunc, defaults) {
+    return function(obj) {
+      var length = arguments.length;
+      if (defaults) obj = Object(obj);
+      if (length < 2 || obj == null) return obj;
+      for (var index = 1; index < length; index++) {
+        var source = arguments[index],
+            keys = keysFunc(source),
+            l = keys.length;
+        for (var i = 0; i < l; i++) {
+          var key = keys[i];
+          if (!defaults || obj[key] === void 0) obj[key] = source[key];
+        }
+      }
+      return obj;
+    };
+  }
+
+  // Extend a given object with all the properties in passed-in object(s).
+  var extend = createAssigner(allKeys);
+
+  // Assigns a given object with all the own properties in the passed-in
+  // object(s).
+  // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
+  var extendOwn = createAssigner(keys);
+
+  // Fill in a given object with default properties.
+  var defaults = createAssigner(allKeys, true);
+
+  // Create a naked function reference for surrogate-prototype-swapping.
+  function ctor() {
+    return function(){};
+  }
+
+  // An internal function for creating a new object that inherits from another.
+  function baseCreate(prototype) {
+    if (!isObject(prototype)) return {};
+    if (nativeCreate) return nativeCreate(prototype);
+    var Ctor = ctor();
+    Ctor.prototype = prototype;
+    var result = new Ctor;
+    Ctor.prototype = null;
+    return result;
+  }
+
+  // Creates an object that inherits from the given prototype object.
+  // If additional properties are provided then they will be added to the
+  // created object.
+  function create(prototype, props) {
+    var result = baseCreate(prototype);
+    if (props) extendOwn(result, props);
+    return result;
+  }
+
+  // Create a (shallow-cloned) duplicate of an object.
+  function clone(obj) {
+    if (!isObject(obj)) return obj;
+    return isArray(obj) ? obj.slice() : extend({}, obj);
+  }
+
+  // Invokes `interceptor` with the `obj` and then returns `obj`.
+  // The primary purpose of this method is to "tap into" a method chain, in
+  // order to perform operations on intermediate results within the chain.
+  function tap(obj, interceptor) {
+    interceptor(obj);
+    return obj;
+  }
+
+  // Normalize a (deep) property `path` to array.
+  // Like `_.iteratee`, this function can be customized.
+  function toPath$1(path) {
+    return isArray(path) ? path : [path];
+  }
+  _$1.toPath = toPath$1;
+
+  // Internal wrapper for `_.toPath` to enable minification.
+  // Similar to `cb` for `_.iteratee`.
+  function toPath(path) {
+    return _$1.toPath(path);
+  }
+
+  // Internal function to obtain a nested property in `obj` along `path`.
+  function deepGet(obj, path) {
+    var length = path.length;
+    for (var i = 0; i < length; i++) {
+      if (obj == null) return void 0;
+      obj = obj[path[i]];
+    }
+    return length ? obj : void 0;
+  }
+
+  // Get the value of the (deep) property on `path` from `object`.
+  // If any property in `path` does not exist or if the value is
+  // `undefined`, return `defaultValue` instead.
+  // The `path` is normalized through `_.toPath`.
+  function get(object, path, defaultValue) {
+    var value = deepGet(object, toPath(path));
+    return isUndefined(value) ? defaultValue : value;
+  }
+
+  // Shortcut function for checking if an object has a given property directly on
+  // itself (in other words, not on a prototype). Unlike the internal `has`
+  // function, this public version can also traverse nested properties.
+  function has(obj, path) {
+    path = toPath(path);
+    var length = path.length;
+    for (var i = 0; i < length; i++) {
+      var key = path[i];
+      if (!has$1(obj, key)) return false;
+      obj = obj[key];
+    }
+    return !!length;
+  }
+
+  // Keep the identity function around for default iteratees.
+  function identity(value) {
+    return value;
+  }
+
+  // Returns a predicate for checking whether an object has a given set of
+  // `key:value` pairs.
+  function matcher(attrs) {
+    attrs = extendOwn({}, attrs);
+    return function(obj) {
+      return isMatch(obj, attrs);
+    };
+  }
+
+  // Creates a function that, when passed an object, will traverse that object’s
+  // properties down the given `path`, specified as an array of keys or indices.
+  function property(path) {
+    path = toPath(path);
+    return function(obj) {
+      return deepGet(obj, path);
+    };
+  }
+
+  // Internal function that returns an efficient (for current engines) version
+  // of the passed-in callback, to be repeatedly applied in other Underscore
+  // functions.
+  function optimizeCb(func, context, argCount) {
+    if (context === void 0) return func;
+    switch (argCount == null ? 3 : argCount) {
+      case 1: return function(value) {
+        return func.call(context, value);
+      };
+      // The 2-argument case is omitted because we’re not using it.
+      case 3: return function(value, index, collection) {
+        return func.call(context, value, index, collection);
+      };
+      case 4: return function(accumulator, value, index, collection) {
+        return func.call(context, accumulator, value, index, collection);
+      };
+    }
+    return function() {
+      return func.apply(context, arguments);
+    };
+  }
+
+  // An internal function to generate callbacks that can be applied to each
+  // element in a collection, returning the desired result β€” either `_.identity`,
+  // an arbitrary callback, a property matcher, or a property accessor.
+  function baseIteratee(value, context, argCount) {
+    if (value == null) return identity;
+    if (isFunction$1(value)) return optimizeCb(value, context, argCount);
+    if (isObject(value) && !isArray(value)) return matcher(value);
+    return property(value);
+  }
+
+  // External wrapper for our callback generator. Users may customize
+  // `_.iteratee` if they want additional predicate/iteratee shorthand styles.
+  // This abstraction hides the internal-only `argCount` argument.
+  function iteratee(value, context) {
+    return baseIteratee(value, context, Infinity);
+  }
+  _$1.iteratee = iteratee;
+
+  // The function we call internally to generate a callback. It invokes
+  // `_.iteratee` if overridden, otherwise `baseIteratee`.
+  function cb(value, context, argCount) {
+    if (_$1.iteratee !== iteratee) return _$1.iteratee(value, context);
+    return baseIteratee(value, context, argCount);
+  }
+
+  // Returns the results of applying the `iteratee` to each element of `obj`.
+  // In contrast to `_.map` it returns an object.
+  function mapObject(obj, iteratee, context) {
+    iteratee = cb(iteratee, context);
+    var _keys = keys(obj),
+        length = _keys.length,
+        results = {};
+    for (var index = 0; index < length; index++) {
+      var currentKey = _keys[index];
+      results[currentKey] = iteratee(obj[currentKey], currentKey, obj);
+    }
+    return results;
+  }
+
+  // Predicate-generating function. Often useful outside of Underscore.
+  function noop(){}
+
+  // Generates a function for a given object that returns a given property.
+  function propertyOf(obj) {
+    if (obj == null) return noop;
+    return function(path) {
+      return get(obj, path);
+    };
+  }
+
+  // Run a function **n** times.
+  function times(n, iteratee, context) {
+    var accum = Array(Math.max(0, n));
+    iteratee = optimizeCb(iteratee, context, 1);
+    for (var i = 0; i < n; i++) accum[i] = iteratee(i);
+    return accum;
+  }
+
+  // Return a random integer between `min` and `max` (inclusive).
+  function random(min, max) {
+    if (max == null) {
+      max = min;
+      min = 0;
+    }
+    return min + Math.floor(Math.random() * (max - min + 1));
+  }
+
+  // A (possibly faster) way to get the current timestamp as an integer.
+  var now = Date.now || function() {
+    return new Date().getTime();
+  };
+
+  // Internal helper to generate functions for escaping and unescaping strings
+  // to/from HTML interpolation.
+  function createEscaper(map) {
+    var escaper = function(match) {
+      return map[match];
+    };
+    // Regexes for identifying a key that needs to be escaped.
+    var source = '(?:' + keys(map).join('|') + ')';
+    var testRegexp = RegExp(source);
+    var replaceRegexp = RegExp(source, 'g');
+    return function(string) {
+      string = string == null ? '' : '' + string;
+      return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
+    };
+  }
+
+  // Internal list of HTML entities for escaping.
+  var escapeMap = {
+    '&': '&amp;',
+    '<': '&lt;',
+    '>': '&gt;',
+    '"': '&quot;',
+    "'": '&#x27;',
+    '`': '&#x60;'
+  };
+
+  // Function for escaping strings to HTML interpolation.
+  var _escape = createEscaper(escapeMap);
+
+  // Internal list of HTML entities for unescaping.
+  var unescapeMap = invert(escapeMap);
+
+  // Function for unescaping strings from HTML interpolation.
+  var _unescape = createEscaper(unescapeMap);
+
+  // By default, Underscore uses ERB-style template delimiters. Change the
+  // following template settings to use alternative delimiters.
+  var templateSettings = _$1.templateSettings = {
+    evaluate: /<%([\s\S]+?)%>/g,
+    interpolate: /<%=([\s\S]+?)%>/g,
+    escape: /<%-([\s\S]+?)%>/g
+  };
+
+  // When customizing `_.templateSettings`, if you don't want to define an
+  // interpolation, evaluation or escaping regex, we need one that is
+  // guaranteed not to match.
+  var noMatch = /(.)^/;
+
+  // Certain characters need to be escaped so that they can be put into a
+  // string literal.
+  var escapes = {
+    "'": "'",
+    '\\': '\\',
+    '\r': 'r',
+    '\n': 'n',
+    '\u2028': 'u2028',
+    '\u2029': 'u2029'
+  };
+
+  var escapeRegExp = /\\|'|\r|\n|\u2028|\u2029/g;
+
+  function escapeChar(match) {
+    return '\\' + escapes[match];
+  }
+
+  // In order to prevent third-party code injection through
+  // `_.templateSettings.variable`, we test it against the following regular
+  // expression. It is intentionally a bit more liberal than just matching valid
+  // identifiers, but still prevents possible loopholes through defaults or
+  // destructuring assignment.
+  var bareIdentifier = /^\s*(\w|\$)+\s*$/;
+
+  // JavaScript micro-templating, similar to John Resig's implementation.
+  // Underscore templating handles arbitrary delimiters, preserves whitespace,
+  // and correctly escapes quotes within interpolated code.
+  // NB: `oldSettings` only exists for backwards compatibility.
+  function template(text, settings, oldSettings) {
+    if (!settings && oldSettings) settings = oldSettings;
+    settings = defaults({}, settings, _$1.templateSettings);
+
+    // Combine delimiters into one regular expression via alternation.
+    var matcher = RegExp([
+      (settings.escape || noMatch).source,
+      (settings.interpolate || noMatch).source,
+      (settings.evaluate || noMatch).source
+    ].join('|') + '|$', 'g');
+
+    // Compile the template source, escaping string literals appropriately.
+    var index = 0;
+    var source = "__p+='";
+    text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
+      source += text.slice(index, offset).replace(escapeRegExp, escapeChar);
+      index = offset + match.length;
+
+      if (escape) {
+        source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
+      } else if (interpolate) {
+        source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
+      } else if (evaluate) {
+        source += "';\n" + evaluate + "\n__p+='";
+      }
+
+      // Adobe VMs need the match returned to produce the correct offset.
+      return match;
+    });
+    source += "';\n";
+
+    var argument = settings.variable;
+    if (argument) {
+      // Insure against third-party code injection. (CVE-2021-23358)
+      if (!bareIdentifier.test(argument)) throw new Error(
+        'variable is not a bare identifier: ' + argument
+      );
+    } else {
+      // If a variable is not specified, place data values in local scope.
+      source = 'with(obj||{}){\n' + source + '}\n';
+      argument = 'obj';
+    }
+
+    source = "var __t,__p='',__j=Array.prototype.join," +
+      "print=function(){__p+=__j.call(arguments,'');};\n" +
+      source + 'return __p;\n';
+
+    var render;
+    try {
+      render = new Function(argument, '_', source);
+    } catch (e) {
+      e.source = source;
+      throw e;
+    }
+
+    var template = function(data) {
+      return render.call(this, data, _$1);
+    };
+
+    // Provide the compiled source as a convenience for precompilation.
+    template.source = 'function(' + argument + '){\n' + source + '}';
+
+    return template;
+  }
+
+  // Traverses the children of `obj` along `path`. If a child is a function, it
+  // is invoked with its parent as context. Returns the value of the final
+  // child, or `fallback` if any child is undefined.
+  function result(obj, path, fallback) {
+    path = toPath(path);
+    var length = path.length;
+    if (!length) {
+      return isFunction$1(fallback) ? fallback.call(obj) : fallback;
+    }
+    for (var i = 0; i < length; i++) {
+      var prop = obj == null ? void 0 : obj[path[i]];
+      if (prop === void 0) {
+        prop = fallback;
+        i = length; // Ensure we don't continue iterating.
+      }
+      obj = isFunction$1(prop) ? prop.call(obj) : prop;
+    }
+    return obj;
+  }
+
+  // Generate a unique integer id (unique within the entire client session).
+  // Useful for temporary DOM ids.
+  var idCounter = 0;
+  function uniqueId(prefix) {
+    var id = ++idCounter + '';
+    return prefix ? prefix + id : id;
+  }
+
+  // Start chaining a wrapped Underscore object.
+  function chain(obj) {
+    var instance = _$1(obj);
+    instance._chain = true;
+    return instance;
+  }
+
+  // Internal function to execute `sourceFunc` bound to `context` with optional
+  // `args`. Determines whether to execute a function as a constructor or as a
+  // normal function.
+  function executeBound(sourceFunc, boundFunc, context, callingContext, args) {
+    if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args);
+    var self = baseCreate(sourceFunc.prototype);
+    var result = sourceFunc.apply(self, args);
+    if (isObject(result)) return result;
+    return self;
+  }
+
+  // Partially apply a function by creating a version that has had some of its
+  // arguments pre-filled, without changing its dynamic `this` context. `_` acts
+  // as a placeholder by default, allowing any combination of arguments to be
+  // pre-filled. Set `_.partial.placeholder` for a custom placeholder argument.
+  var partial = restArguments(function(func, boundArgs) {
+    var placeholder = partial.placeholder;
+    var bound = function() {
+      var position = 0, length = boundArgs.length;
+      var args = Array(length);
+      for (var i = 0; i < length; i++) {
+        args[i] = boundArgs[i] === placeholder ? arguments[position++] : boundArgs[i];
+      }
+      while (position < arguments.length) args.push(arguments[position++]);
+      return executeBound(func, bound, this, this, args);
+    };
+    return bound;
+  });
+
+  partial.placeholder = _$1;
+
+  // Create a function bound to a given object (assigning `this`, and arguments,
+  // optionally).
+  var bind = restArguments(function(func, context, args) {
+    if (!isFunction$1(func)) throw new TypeError('Bind must be called on a function');
+    var bound = restArguments(function(callArgs) {
+      return executeBound(func, bound, context, this, args.concat(callArgs));
+    });
+    return bound;
+  });
+
+  // Internal helper for collection methods to determine whether a collection
+  // should be iterated as an array or as an object.
+  // Related: https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength
+  // Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094
+  var isArrayLike = createSizePropertyCheck(getLength);
+
+  // Internal implementation of a recursive `flatten` function.
+  function flatten$1(input, depth, strict, output) {
+    output = output || [];
+    if (!depth && depth !== 0) {
+      depth = Infinity;
+    } else if (depth <= 0) {
+      return output.concat(input);
+    }
+    var idx = output.length;
+    for (var i = 0, length = getLength(input); i < length; i++) {
+      var value = input[i];
+      if (isArrayLike(value) && (isArray(value) || isArguments$1(value))) {
+        // Flatten current level of array or arguments object.
+        if (depth > 1) {
+          flatten$1(value, depth - 1, strict, output);
+          idx = output.length;
+        } else {
+          var j = 0, len = value.length;
+          while (j < len) output[idx++] = value[j++];
+        }
+      } else if (!strict) {
+        output[idx++] = value;
+      }
+    }
+    return output;
+  }
+
+  // Bind a number of an object's methods to that object. Remaining arguments
+  // are the method names to be bound. Useful for ensuring that all callbacks
+  // defined on an object belong to it.
+  var bindAll = restArguments(function(obj, keys) {
+    keys = flatten$1(keys, false, false);
+    var index = keys.length;
+    if (index < 1) throw new Error('bindAll must be passed function names');
+    while (index--) {
+      var key = keys[index];
+      obj[key] = bind(obj[key], obj);
+    }
+    return obj;
+  });
+
+  // Memoize an expensive function by storing its results.
+  function memoize(func, hasher) {
+    var memoize = function(key) {
+      var cache = memoize.cache;
+      var address = '' + (hasher ? hasher.apply(this, arguments) : key);
+      if (!has$1(cache, address)) cache[address] = func.apply(this, arguments);
+      return cache[address];
+    };
+    memoize.cache = {};
+    return memoize;
+  }
+
+  // Delays a function for the given number of milliseconds, and then calls
+  // it with the arguments supplied.
+  var delay = restArguments(function(func, wait, args) {
+    return setTimeout(function() {
+      return func.apply(null, args);
+    }, wait);
+  });
+
+  // Defers a function, scheduling it to run after the current call stack has
+  // cleared.
+  var defer = partial(delay, _$1, 1);
+
+  // Returns a function, that, when invoked, will only be triggered at most once
+  // during a given window of time. Normally, the throttled function will run
+  // as much as it can, without ever going more than once per `wait` duration;
+  // but if you'd like to disable the execution on the leading edge, pass
+  // `{leading: false}`. To disable execution on the trailing edge, ditto.
+  function throttle(func, wait, options) {
+    var timeout, context, args, result;
+    var previous = 0;
+    if (!options) options = {};
+
+    var later = function() {
+      previous = options.leading === false ? 0 : now();
+      timeout = null;
+      result = func.apply(context, args);
+      if (!timeout) context = args = null;
+    };
+
+    var throttled = function() {
+      var _now = now();
+      if (!previous && options.leading === false) previous = _now;
+      var remaining = wait - (_now - previous);
+      context = this;
+      args = arguments;
+      if (remaining <= 0 || remaining > wait) {
+        if (timeout) {
+          clearTimeout(timeout);
+          timeout = null;
+        }
+        previous = _now;
+        result = func.apply(context, args);
+        if (!timeout) context = args = null;
+      } else if (!timeout && options.trailing !== false) {
+        timeout = setTimeout(later, remaining);
+      }
+      return result;
+    };
+
+    throttled.cancel = function() {
+      clearTimeout(timeout);
+      previous = 0;
+      timeout = context = args = null;
+    };
+
+    return throttled;
+  }
+
+  // When a sequence of calls of the returned function ends, the argument
+  // function is triggered. The end of a sequence is defined by the `wait`
+  // parameter. If `immediate` is passed, the argument function will be
+  // triggered at the beginning of the sequence instead of at the end.
+  function debounce(func, wait, immediate) {
+    var timeout, previous, args, result, context;
+
+    var later = function() {
+      var passed = now() - previous;
+      if (wait > passed) {
+        timeout = setTimeout(later, wait - passed);
+      } else {
+        timeout = null;
+        if (!immediate) result = func.apply(context, args);
+        // This check is needed because `func` can recursively invoke `debounced`.
+        if (!timeout) args = context = null;
+      }
+    };
+
+    var debounced = restArguments(function(_args) {
+      context = this;
+      args = _args;
+      previous = now();
+      if (!timeout) {
+        timeout = setTimeout(later, wait);
+        if (immediate) result = func.apply(context, args);
+      }
+      return result;
+    });
+
+    debounced.cancel = function() {
+      clearTimeout(timeout);
+      timeout = args = context = null;
+    };
+
+    return debounced;
+  }
+
+  // Returns the first function passed as an argument to the second,
+  // allowing you to adjust arguments, run code before and after, and
+  // conditionally execute the original function.
+  function wrap(func, wrapper) {
+    return partial(wrapper, func);
+  }
+
+  // Returns a negated version of the passed-in predicate.
+  function negate(predicate) {
+    return function() {
+      return !predicate.apply(this, arguments);
+    };
+  }
+
+  // Returns a function that is the composition of a list of functions, each
+  // consuming the return value of the function that follows.
+  function compose() {
+    var args = arguments;
+    var start = args.length - 1;
+    return function() {
+      var i = start;
+      var result = args[start].apply(this, arguments);
+      while (i--) result = args[i].call(this, result);
+      return result;
+    };
+  }
+
+  // Returns a function that will only be executed on and after the Nth call.
+  function after(times, func) {
+    return function() {
+      if (--times < 1) {
+        return func.apply(this, arguments);
+      }
+    };
+  }
+
+  // Returns a function that will only be executed up to (but not including) the
+  // Nth call.
+  function before(times, func) {
+    var memo;
+    return function() {
+      if (--times > 0) {
+        memo = func.apply(this, arguments);
+      }
+      if (times <= 1) func = null;
+      return memo;
+    };
+  }
+
+  // Returns a function that will be executed at most one time, no matter how
+  // often you call it. Useful for lazy initialization.
+  var once = partial(before, 2);
+
+  // Returns the first key on an object that passes a truth test.
+  function findKey(obj, predicate, context) {
+    predicate = cb(predicate, context);
+    var _keys = keys(obj), key;
+    for (var i = 0, length = _keys.length; i < length; i++) {
+      key = _keys[i];
+      if (predicate(obj[key], key, obj)) return key;
+    }
+  }
+
+  // Internal function to generate `_.findIndex` and `_.findLastIndex`.
+  function createPredicateIndexFinder(dir) {
+    return function(array, predicate, context) {
+      predicate = cb(predicate, context);
+      var length = getLength(array);
+      var index = dir > 0 ? 0 : length - 1;
+      for (; index >= 0 && index < length; index += dir) {
+        if (predicate(array[index], index, array)) return index;
+      }
+      return -1;
+    };
+  }
+
+  // Returns the first index on an array-like that passes a truth test.
+  var findIndex = createPredicateIndexFinder(1);
+
+  // Returns the last index on an array-like that passes a truth test.
+  var findLastIndex = createPredicateIndexFinder(-1);
+
+  // Use a comparator function to figure out the smallest index at which
+  // an object should be inserted so as to maintain order. Uses binary search.
+  function sortedIndex(array, obj, iteratee, context) {
+    iteratee = cb(iteratee, context, 1);
+    var value = iteratee(obj);
+    var low = 0, high = getLength(array);
+    while (low < high) {
+      var mid = Math.floor((low + high) / 2);
+      if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
+    }
+    return low;
+  }
+
+  // Internal function to generate the `_.indexOf` and `_.lastIndexOf` functions.
+  function createIndexFinder(dir, predicateFind, sortedIndex) {
+    return function(array, item, idx) {
+      var i = 0, length = getLength(array);
+      if (typeof idx == 'number') {
+        if (dir > 0) {
+          i = idx >= 0 ? idx : Math.max(idx + length, i);
+        } else {
+          length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1;
+        }
+      } else if (sortedIndex && idx && length) {
+        idx = sortedIndex(array, item);
+        return array[idx] === item ? idx : -1;
+      }
+      if (item !== item) {
+        idx = predicateFind(slice.call(array, i, length), isNaN$1);
+        return idx >= 0 ? idx + i : -1;
+      }
+      for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) {
+        if (array[idx] === item) return idx;
+      }
+      return -1;
+    };
+  }
+
+  // Return the position of the first occurrence of an item in an array,
+  // or -1 if the item is not included in the array.
+  // If the array is large and already in sort order, pass `true`
+  // for **isSorted** to use binary search.
+  var indexOf = createIndexFinder(1, findIndex, sortedIndex);
+
+  // Return the position of the last occurrence of an item in an array,
+  // or -1 if the item is not included in the array.
+  var lastIndexOf = createIndexFinder(-1, findLastIndex);
+
+  // Return the first value which passes a truth test.
+  function find(obj, predicate, context) {
+    var keyFinder = isArrayLike(obj) ? findIndex : findKey;
+    var key = keyFinder(obj, predicate, context);
+    if (key !== void 0 && key !== -1) return obj[key];
+  }
+
+  // Convenience version of a common use case of `_.find`: getting the first
+  // object containing specific `key:value` pairs.
+  function findWhere(obj, attrs) {
+    return find(obj, matcher(attrs));
+  }
+
+  // The cornerstone for collection functions, an `each`
+  // implementation, aka `forEach`.
+  // Handles raw objects in addition to array-likes. Treats all
+  // sparse array-likes as if they were dense.
+  function each(obj, iteratee, context) {
+    iteratee = optimizeCb(iteratee, context);
+    var i, length;
+    if (isArrayLike(obj)) {
+      for (i = 0, length = obj.length; i < length; i++) {
+        iteratee(obj[i], i, obj);
+      }
+    } else {
+      var _keys = keys(obj);
+      for (i = 0, length = _keys.length; i < length; i++) {
+        iteratee(obj[_keys[i]], _keys[i], obj);
+      }
+    }
+    return obj;
+  }
+
+  // Return the results of applying the iteratee to each element.
+  function map(obj, iteratee, context) {
+    iteratee = cb(iteratee, context);
+    var _keys = !isArrayLike(obj) && keys(obj),
+        length = (_keys || obj).length,
+        results = Array(length);
+    for (var index = 0; index < length; index++) {
+      var currentKey = _keys ? _keys[index] : index;
+      results[index] = iteratee(obj[currentKey], currentKey, obj);
+    }
+    return results;
+  }
+
+  // Internal helper to create a reducing function, iterating left or right.
+  function createReduce(dir) {
+    // Wrap code that reassigns argument variables in a separate function than
+    // the one that accesses `arguments.length` to avoid a perf hit. (#1991)
+    var reducer = function(obj, iteratee, memo, initial) {
+      var _keys = !isArrayLike(obj) && keys(obj),
+          length = (_keys || obj).length,
+          index = dir > 0 ? 0 : length - 1;
+      if (!initial) {
+        memo = obj[_keys ? _keys[index] : index];
+        index += dir;
+      }
+      for (; index >= 0 && index < length; index += dir) {
+        var currentKey = _keys ? _keys[index] : index;
+        memo = iteratee(memo, obj[currentKey], currentKey, obj);
+      }
+      return memo;
+    };
+
+    return function(obj, iteratee, memo, context) {
+      var initial = arguments.length >= 3;
+      return reducer(obj, optimizeCb(iteratee, context, 4), memo, initial);
+    };
+  }
+
+  // **Reduce** builds up a single result from a list of values, aka `inject`,
+  // or `foldl`.
+  var reduce = createReduce(1);
+
+  // The right-associative version of reduce, also known as `foldr`.
+  var reduceRight = createReduce(-1);
+
+  // Return all the elements that pass a truth test.
+  function filter(obj, predicate, context) {
+    var results = [];
+    predicate = cb(predicate, context);
+    each(obj, function(value, index, list) {
+      if (predicate(value, index, list)) results.push(value);
+    });
+    return results;
+  }
+
+  // Return all the elements for which a truth test fails.
+  function reject(obj, predicate, context) {
+    return filter(obj, negate(cb(predicate)), context);
+  }
+
+  // Determine whether all of the elements pass a truth test.
+  function every(obj, predicate, context) {
+    predicate = cb(predicate, context);
+    var _keys = !isArrayLike(obj) && keys(obj),
+        length = (_keys || obj).length;
+    for (var index = 0; index < length; index++) {
+      var currentKey = _keys ? _keys[index] : index;
+      if (!predicate(obj[currentKey], currentKey, obj)) return false;
+    }
+    return true;
+  }
+
+  // Determine if at least one element in the object passes a truth test.
+  function some(obj, predicate, context) {
+    predicate = cb(predicate, context);
+    var _keys = !isArrayLike(obj) && keys(obj),
+        length = (_keys || obj).length;
+    for (var index = 0; index < length; index++) {
+      var currentKey = _keys ? _keys[index] : index;
+      if (predicate(obj[currentKey], currentKey, obj)) return true;
+    }
+    return false;
+  }
+
+  // Determine if the array or object contains a given item (using `===`).
+  function contains(obj, item, fromIndex, guard) {
+    if (!isArrayLike(obj)) obj = values(obj);
+    if (typeof fromIndex != 'number' || guard) fromIndex = 0;
+    return indexOf(obj, item, fromIndex) >= 0;
+  }
+
+  // Invoke a method (with arguments) on every item in a collection.
+  var invoke = restArguments(function(obj, path, args) {
+    var contextPath, func;
+    if (isFunction$1(path)) {
+      func = path;
+    } else {
+      path = toPath(path);
+      contextPath = path.slice(0, -1);
+      path = path[path.length - 1];
+    }
+    return map(obj, function(context) {
+      var method = func;
+      if (!method) {
+        if (contextPath && contextPath.length) {
+          context = deepGet(context, contextPath);
+        }
+        if (context == null) return void 0;
+        method = context[path];
+      }
+      return method == null ? method : method.apply(context, args);
+    });
+  });
+
+  // Convenience version of a common use case of `_.map`: fetching a property.
+  function pluck(obj, key) {
+    return map(obj, property(key));
+  }
+
+  // Convenience version of a common use case of `_.filter`: selecting only
+  // objects containing specific `key:value` pairs.
+  function where(obj, attrs) {
+    return filter(obj, matcher(attrs));
+  }
+
+  // Return the maximum element (or element-based computation).
+  function max(obj, iteratee, context) {
+    var result = -Infinity, lastComputed = -Infinity,
+        value, computed;
+    if (iteratee == null || typeof iteratee == 'number' && typeof obj[0] != 'object' && obj != null) {
+      obj = isArrayLike(obj) ? obj : values(obj);
+      for (var i = 0, length = obj.length; i < length; i++) {
+        value = obj[i];
+        if (value != null && value > result) {
+          result = value;
+        }
+      }
+    } else {
+      iteratee = cb(iteratee, context);
+      each(obj, function(v, index, list) {
+        computed = iteratee(v, index, list);
+        if (computed > lastComputed || computed === -Infinity && result === -Infinity) {
+          result = v;
+          lastComputed = computed;
+        }
+      });
+    }
+    return result;
+  }
+
+  // Return the minimum element (or element-based computation).
+  function min(obj, iteratee, context) {
+    var result = Infinity, lastComputed = Infinity,
+        value, computed;
+    if (iteratee == null || typeof iteratee == 'number' && typeof obj[0] != 'object' && obj != null) {
+      obj = isArrayLike(obj) ? obj : values(obj);
+      for (var i = 0, length = obj.length; i < length; i++) {
+        value = obj[i];
+        if (value != null && value < result) {
+          result = value;
+        }
+      }
+    } else {
+      iteratee = cb(iteratee, context);
+      each(obj, function(v, index, list) {
+        computed = iteratee(v, index, list);
+        if (computed < lastComputed || computed === Infinity && result === Infinity) {
+          result = v;
+          lastComputed = computed;
+        }
+      });
+    }
+    return result;
+  }
+
+  // Sample **n** random values from a collection using the modern version of the
+  // [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
+  // If **n** is not specified, returns a single random element.
+  // The internal `guard` argument allows it to work with `_.map`.
+  function sample(obj, n, guard) {
+    if (n == null || guard) {
+      if (!isArrayLike(obj)) obj = values(obj);
+      return obj[random(obj.length - 1)];
+    }
+    var sample = isArrayLike(obj) ? clone(obj) : values(obj);
+    var length = getLength(sample);
+    n = Math.max(Math.min(n, length), 0);
+    var last = length - 1;
+    for (var index = 0; index < n; index++) {
+      var rand = random(index, last);
+      var temp = sample[index];
+      sample[index] = sample[rand];
+      sample[rand] = temp;
+    }
+    return sample.slice(0, n);
+  }
+
+  // Shuffle a collection.
+  function shuffle(obj) {
+    return sample(obj, Infinity);
+  }
+
+  // Sort the object's values by a criterion produced by an iteratee.
+  function sortBy(obj, iteratee, context) {
+    var index = 0;
+    iteratee = cb(iteratee, context);
+    return pluck(map(obj, function(value, key, list) {
+      return {
+        value: value,
+        index: index++,
+        criteria: iteratee(value, key, list)
+      };
+    }).sort(function(left, right) {
+      var a = left.criteria;
+      var b = right.criteria;
+      if (a !== b) {
+        if (a > b || a === void 0) return 1;
+        if (a < b || b === void 0) return -1;
+      }
+      return left.index - right.index;
+    }), 'value');
+  }
+
+  // An internal function used for aggregate "group by" operations.
+  function group(behavior, partition) {
+    return function(obj, iteratee, context) {
+      var result = partition ? [[], []] : {};
+      iteratee = cb(iteratee, context);
+      each(obj, function(value, index) {
+        var key = iteratee(value, index, obj);
+        behavior(result, value, key);
+      });
+      return result;
+    };
+  }
+
+  // Groups the object's values by a criterion. Pass either a string attribute
+  // to group by, or a function that returns the criterion.
+  var groupBy = group(function(result, value, key) {
+    if (has$1(result, key)) result[key].push(value); else result[key] = [value];
+  });
+
+  // Indexes the object's values by a criterion, similar to `_.groupBy`, but for
+  // when you know that your index values will be unique.
+  var indexBy = group(function(result, value, key) {
+    result[key] = value;
+  });
+
+  // Counts instances of an object that group by a certain criterion. Pass
+  // either a string attribute to count by, or a function that returns the
+  // criterion.
+  var countBy = group(function(result, value, key) {
+    if (has$1(result, key)) result[key]++; else result[key] = 1;
+  });
+
+  // Split a collection into two arrays: one whose elements all pass the given
+  // truth test, and one whose elements all do not pass the truth test.
+  var partition = group(function(result, value, pass) {
+    result[pass ? 0 : 1].push(value);
+  }, true);
+
+  // Safely create a real, live array from anything iterable.
+  var reStrSymbol = /[^\ud800-\udfff]|[\ud800-\udbff][\udc00-\udfff]|[\ud800-\udfff]/g;
+  function toArray(obj) {
+    if (!obj) return [];
+    if (isArray(obj)) return slice.call(obj);
+    if (isString(obj)) {
+      // Keep surrogate pair characters together.
+      return obj.match(reStrSymbol);
+    }
+    if (isArrayLike(obj)) return map(obj, identity);
+    return values(obj);
+  }
+
+  // Return the number of elements in a collection.
+  function size(obj) {
+    if (obj == null) return 0;
+    return isArrayLike(obj) ? obj.length : keys(obj).length;
+  }
+
+  // Internal `_.pick` helper function to determine whether `key` is an enumerable
+  // property name of `obj`.
+  function keyInObj(value, key, obj) {
+    return key in obj;
+  }
+
+  // Return a copy of the object only containing the allowed properties.
+  var pick = restArguments(function(obj, keys) {
+    var result = {}, iteratee = keys[0];
+    if (obj == null) return result;
+    if (isFunction$1(iteratee)) {
+      if (keys.length > 1) iteratee = optimizeCb(iteratee, keys[1]);
+      keys = allKeys(obj);
+    } else {
+      iteratee = keyInObj;
+      keys = flatten$1(keys, false, false);
+      obj = Object(obj);
+    }
+    for (var i = 0, length = keys.length; i < length; i++) {
+      var key = keys[i];
+      var value = obj[key];
+      if (iteratee(value, key, obj)) result[key] = value;
+    }
+    return result;
+  });
+
+  // Return a copy of the object without the disallowed properties.
+  var omit = restArguments(function(obj, keys) {
+    var iteratee = keys[0], context;
+    if (isFunction$1(iteratee)) {
+      iteratee = negate(iteratee);
+      if (keys.length > 1) context = keys[1];
+    } else {
+      keys = map(flatten$1(keys, false, false), String);
+      iteratee = function(value, key) {
+        return !contains(keys, key);
+      };
+    }
+    return pick(obj, iteratee, context);
+  });
+
+  // Returns everything but the last entry of the array. Especially useful on
+  // the arguments object. Passing **n** will return all the values in
+  // the array, excluding the last N.
+  function initial(array, n, guard) {
+    return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));
+  }
+
+  // Get the first element of an array. Passing **n** will return the first N
+  // values in the array. The **guard** check allows it to work with `_.map`.
+  function first(array, n, guard) {
+    if (array == null || array.length < 1) return n == null || guard ? void 0 : [];
+    if (n == null || guard) return array[0];
+    return initial(array, array.length - n);
+  }
+
+  // Returns everything but the first entry of the `array`. Especially useful on
+  // the `arguments` object. Passing an **n** will return the rest N values in the
+  // `array`.
+  function rest(array, n, guard) {
+    return slice.call(array, n == null || guard ? 1 : n);
+  }
+
+  // Get the last element of an array. Passing **n** will return the last N
+  // values in the array.
+  function last(array, n, guard) {
+    if (array == null || array.length < 1) return n == null || guard ? void 0 : [];
+    if (n == null || guard) return array[array.length - 1];
+    return rest(array, Math.max(0, array.length - n));
+  }
+
+  // Trim out all falsy values from an array.
+  function compact(array) {
+    return filter(array, Boolean);
+  }
+
+  // Flatten out an array, either recursively (by default), or up to `depth`.
+  // Passing `true` or `false` as `depth` means `1` or `Infinity`, respectively.
+  function flatten(array, depth) {
+    return flatten$1(array, depth, false);
+  }
+
+  // Take the difference between one array and a number of other arrays.
+  // Only the elements present in just the first array will remain.
+  var difference = restArguments(function(array, rest) {
+    rest = flatten$1(rest, true, true);
+    return filter(array, function(value){
+      return !contains(rest, value);
+    });
+  });
+
+  // Return a version of the array that does not contain the specified value(s).
+  var without = restArguments(function(array, otherArrays) {
+    return difference(array, otherArrays);
+  });
+
+  // Produce a duplicate-free version of the array. If the array has already
+  // been sorted, you have the option of using a faster algorithm.
+  // The faster algorithm will not work with an iteratee if the iteratee
+  // is not a one-to-one function, so providing an iteratee will disable
+  // the faster algorithm.
+  function uniq(array, isSorted, iteratee, context) {
+    if (!isBoolean(isSorted)) {
+      context = iteratee;
+      iteratee = isSorted;
+      isSorted = false;
+    }
+    if (iteratee != null) iteratee = cb(iteratee, context);
+    var result = [];
+    var seen = [];
+    for (var i = 0, length = getLength(array); i < length; i++) {
+      var value = array[i],
+          computed = iteratee ? iteratee(value, i, array) : value;
+      if (isSorted && !iteratee) {
+        if (!i || seen !== computed) result.push(value);
+        seen = computed;
+      } else if (iteratee) {
+        if (!contains(seen, computed)) {
+          seen.push(computed);
+          result.push(value);
+        }
+      } else if (!contains(result, value)) {
+        result.push(value);
+      }
+    }
+    return result;
+  }
+
+  // Produce an array that contains the union: each distinct element from all of
+  // the passed-in arrays.
+  var union = restArguments(function(arrays) {
+    return uniq(flatten$1(arrays, true, true));
+  });
+
+  // Produce an array that contains every item shared between all the
+  // passed-in arrays.
+  function intersection(array) {
+    var result = [];
+    var argsLength = arguments.length;
+    for (var i = 0, length = getLength(array); i < length; i++) {
+      var item = array[i];
+      if (contains(result, item)) continue;
+      var j;
+      for (j = 1; j < argsLength; j++) {
+        if (!contains(arguments[j], item)) break;
+      }
+      if (j === argsLength) result.push(item);
+    }
+    return result;
+  }
+
+  // Complement of zip. Unzip accepts an array of arrays and groups
+  // each array's elements on shared indices.
+  function unzip(array) {
+    var length = array && max(array, getLength).length || 0;
+    var result = Array(length);
+
+    for (var index = 0; index < length; index++) {
+      result[index] = pluck(array, index);
+    }
+    return result;
+  }
+
+  // Zip together multiple lists into a single array -- elements that share
+  // an index go together.
+  var zip = restArguments(unzip);
+
+  // Converts lists into objects. Pass either a single array of `[key, value]`
+  // pairs, or two parallel arrays of the same length -- one of keys, and one of
+  // the corresponding values. Passing by pairs is the reverse of `_.pairs`.
+  function object(list, values) {
+    var result = {};
+    for (var i = 0, length = getLength(list); i < length; i++) {
+      if (values) {
+        result[list[i]] = values[i];
+      } else {
+        result[list[i][0]] = list[i][1];
+      }
+    }
+    return result;
+  }
+
+  // Generate an integer Array containing an arithmetic progression. A port of
+  // the native Python `range()` function. See
+  // [the Python documentation](https://docs.python.org/library/functions.html#range).
+  function range(start, stop, step) {
+    if (stop == null) {
+      stop = start || 0;
+      start = 0;
+    }
+    if (!step) {
+      step = stop < start ? -1 : 1;
+    }
+
+    var length = Math.max(Math.ceil((stop - start) / step), 0);
+    var range = Array(length);
+
+    for (var idx = 0; idx < length; idx++, start += step) {
+      range[idx] = start;
+    }
+
+    return range;
+  }
+
+  // Chunk a single array into multiple arrays, each containing `count` or fewer
+  // items.
+  function chunk(array, count) {
+    if (count == null || count < 1) return [];
+    var result = [];
+    var i = 0, length = array.length;
+    while (i < length) {
+      result.push(slice.call(array, i, i += count));
+    }
+    return result;
+  }
+
+  // Helper function to continue chaining intermediate results.
+  function chainResult(instance, obj) {
+    return instance._chain ? _$1(obj).chain() : obj;
+  }
+
+  // Add your own custom functions to the Underscore object.
+  function mixin(obj) {
+    each(functions(obj), function(name) {
+      var func = _$1[name] = obj[name];
+      _$1.prototype[name] = function() {
+        var args = [this._wrapped];
+        push.apply(args, arguments);
+        return chainResult(this, func.apply(_$1, args));
+      };
+    });
+    return _$1;
+  }
+
+  // Add all mutator `Array` functions to the wrapper.
+  each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
+    var method = ArrayProto[name];
+    _$1.prototype[name] = function() {
+      var obj = this._wrapped;
+      if (obj != null) {
+        method.apply(obj, arguments);
+        if ((name === 'shift' || name === 'splice') && obj.length === 0) {
+          delete obj[0];
+        }
+      }
+      return chainResult(this, obj);
+    };
+  });
+
+  // Add all accessor `Array` functions to the wrapper.
+  each(['concat', 'join', 'slice'], function(name) {
+    var method = ArrayProto[name];
+    _$1.prototype[name] = function() {
+      var obj = this._wrapped;
+      if (obj != null) obj = method.apply(obj, arguments);
+      return chainResult(this, obj);
+    };
+  });
+
+  // Named Exports
+
+  var allExports = {
+    __proto__: null,
+    VERSION: VERSION,
+    restArguments: restArguments,
+    isObject: isObject,
+    isNull: isNull,
+    isUndefined: isUndefined,
+    isBoolean: isBoolean,
+    isElement: isElement,
+    isString: isString,
+    isNumber: isNumber,
+    isDate: isDate,
+    isRegExp: isRegExp,
+    isError: isError,
+    isSymbol: isSymbol,
+    isArrayBuffer: isArrayBuffer,
+    isDataView: isDataView$1,
+    isArray: isArray,
+    isFunction: isFunction$1,
+    isArguments: isArguments$1,
+    isFinite: isFinite$1,
+    isNaN: isNaN$1,
+    isTypedArray: isTypedArray$1,
+    isEmpty: isEmpty,
+    isMatch: isMatch,
+    isEqual: isEqual,
+    isMap: isMap,
+    isWeakMap: isWeakMap,
+    isSet: isSet,
+    isWeakSet: isWeakSet,
+    keys: keys,
+    allKeys: allKeys,
+    values: values,
+    pairs: pairs,
+    invert: invert,
+    functions: functions,
+    methods: functions,
+    extend: extend,
+    extendOwn: extendOwn,
+    assign: extendOwn,
+    defaults: defaults,
+    create: create,
+    clone: clone,
+    tap: tap,
+    get: get,
+    has: has,
+    mapObject: mapObject,
+    identity: identity,
+    constant: constant,
+    noop: noop,
+    toPath: toPath$1,
+    property: property,
+    propertyOf: propertyOf,
+    matcher: matcher,
+    matches: matcher,
+    times: times,
+    random: random,
+    now: now,
+    escape: _escape,
+    unescape: _unescape,
+    templateSettings: templateSettings,
+    template: template,
+    result: result,
+    uniqueId: uniqueId,
+    chain: chain,
+    iteratee: iteratee,
+    partial: partial,
+    bind: bind,
+    bindAll: bindAll,
+    memoize: memoize,
+    delay: delay,
+    defer: defer,
+    throttle: throttle,
+    debounce: debounce,
+    wrap: wrap,
+    negate: negate,
+    compose: compose,
+    after: after,
+    before: before,
+    once: once,
+    findKey: findKey,
+    findIndex: findIndex,
+    findLastIndex: findLastIndex,
+    sortedIndex: sortedIndex,
+    indexOf: indexOf,
+    lastIndexOf: lastIndexOf,
+    find: find,
+    detect: find,
+    findWhere: findWhere,
+    each: each,
+    forEach: each,
+    map: map,
+    collect: map,
+    reduce: reduce,
+    foldl: reduce,
+    inject: reduce,
+    reduceRight: reduceRight,
+    foldr: reduceRight,
+    filter: filter,
+    select: filter,
+    reject: reject,
+    every: every,
+    all: every,
+    some: some,
+    any: some,
+    contains: contains,
+    includes: contains,
+    include: contains,
+    invoke: invoke,
+    pluck: pluck,
+    where: where,
+    max: max,
+    min: min,
+    shuffle: shuffle,
+    sample: sample,
+    sortBy: sortBy,
+    groupBy: groupBy,
+    indexBy: indexBy,
+    countBy: countBy,
+    partition: partition,
+    toArray: toArray,
+    size: size,
+    pick: pick,
+    omit: omit,
+    first: first,
+    head: first,
+    take: first,
+    initial: initial,
+    last: last,
+    rest: rest,
+    tail: rest,
+    drop: rest,
+    compact: compact,
+    flatten: flatten,
+    without: without,
+    uniq: uniq,
+    unique: uniq,
+    union: union,
+    intersection: intersection,
+    difference: difference,
+    unzip: unzip,
+    transpose: unzip,
+    zip: zip,
+    object: object,
+    range: range,
+    chunk: chunk,
+    mixin: mixin,
+    'default': _$1
+  };
+
+  // Default Export
+
+  // Add all of the Underscore functions to the wrapper object.
+  var _ = mixin(allExports);
+  // Legacy Node.js API.
+  _._ = _;
+
+  return _;
+
+})));
+//# sourceMappingURL=underscore-umd.js.map
diff --git a/docs/apache-airflow-providers-sftp/4.0.0/_static/underscore.js b/docs/apache-airflow-providers-sftp/4.0.0/_static/underscore.js
new file mode 100644
index 0000000000..cf177d4285
--- /dev/null
+++ b/docs/apache-airflow-providers-sftp/4.0.0/_static/underscore.js
@@ -0,0 +1,6 @@
+!function(n,r){"object"==typeof exports&&"undefined"!=typeof module?module.exports=r():"function"==typeof define&&define.amd?define("underscore",r):(n="undefined"!=typeof globalThis?globalThis:n||self,function(){var t=n._,e=n._=r();e.noConflict=function(){return n._=t,e}}())}(this,(function(){
+//     Underscore.js 1.13.1
+//     https://underscorejs.org
+//     (c) 2009-2021 Jeremy Ashkenas, Julian Gonggrijp, and DocumentCloud and Investigative Reporters & Editors
+//     Underscore may be freely distributed under the MIT license.
+var n="1.13.1",r="object"==typeof self&&self.self===self&&self||"object"==typeof global&&global.global===global&&global||Function("return this")()||{},t=Array.prototype,e=Object.prototype,u="undefined"!=typeof Symbol?Symbol.prototype:null,o=t.push,i=t.slice,a=e.toString,f=e.hasOwnProperty,c="undefined"!=typeof ArrayBuffer,l="undefined"!=typeof DataView,s=Array.isArray,p=Object.keys,v=Object.create,h=c&&ArrayBuffer.isView,y=isNaN,d=isFinite,g=!{toString:null}.propertyIsEnumerable("toStrin [...]
\ No newline at end of file
diff --git a/docs/apache-airflow-providers-sftp/stable/commits.html b/docs/apache-airflow-providers-sftp/4.0.0/commits.html
similarity index 95%
copy from docs/apache-airflow-providers-sftp/stable/commits.html
copy to docs/apache-airflow-providers-sftp/4.0.0/commits.html
index 5080a8bf82..c5c18f504f 100644
--- a/docs/apache-airflow-providers-sftp/stable/commits.html
+++ b/docs/apache-airflow-providers-sftp/4.0.0/commits.html
@@ -5,7 +5,7 @@
 <!DOCTYPE html>
 <!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
 <!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
-    <html xmlns="http://www.w3.org/1999/xhtml">
+    <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
 <head>
         <meta charset="utf-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1">
@@ -283,7 +283,7 @@
 <div id="docs-version-selector" class="docs-version-selector sidebar__version-selector">
     <a class="dropdown-toggle" href="#" id="versionDropdown" role="button" data-toggle="dropdown" aria-haspopup="true"
        aria-expanded="false">
-        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">3.0.0</span>
+        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">4.0.0</span>
     </a>
     <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
 
@@ -420,7 +420,7 @@
 <div id="docs-version-selector" class="docs-version-selector sidebar__version-selector">
     <a class="dropdown-toggle" href="#" id="versionDropdown" role="button" data-toggle="dropdown" aria-haspopup="true"
        aria-expanded="false">
-        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">3.0.0</span>
+        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">4.0.0</span>
     </a>
     <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
 
@@ -578,13 +578,56 @@
   <blockquote>
 <div></div></blockquote>
 <div class="section" id="package-apache-airflow-providers-sftp">
-<h1>Package apache-airflow-providers-sftp<a class="headerlink" href="#package-apache-airflow-providers-sftp" title="Permalink to this headline">ΒΆ</a></h1>
+<h1>Package apache-airflow-providers-sftp<a class="headerlink" href="#package-apache-airflow-providers-sftp" title="Permalink to this heading">ΒΆ</a></h1>
 <p><a class="reference external" href="https://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/">SSH File Transfer Protocol (SFTP)</a></p>
 <p>This is detailed commit list of changes for versions provider package: <code class="docutils literal notranslate"><span class="pre">sftp</span></code>.
 For high-level changelog, see <a class="reference internal" href="index.html"><span class="doc">package information including changelog</span></a>.</p>
 <div class="section" id="id1">
-<h2>3.0.0<a class="headerlink" href="#id1" title="Permalink to this headline">ΒΆ</a></h2>
-<p>Latest change: 2022-06-07</p>
+<h2>4.0.0<a class="headerlink" href="#id1" title="Permalink to this heading">ΒΆ</a></h2>
+<p>Latest change: 2022-07-13</p>
+<table class="docutils align-default">
+<colgroup>
+<col style="width: 53%" />
+<col style="width: 6%" />
+<col style="width: 41%" />
+</colgroup>
+<thead>
+<tr class="row-odd"><th class="head"><p>Commit</p></th>
+<th class="head"><p>Committed</p></th>
+<th class="head"><p>Subject</p></th>
+</tr>
+</thead>
+<tbody>
+<tr class="row-even"><td><p><a class="reference external" href="https://github.com/apache/airflow/commit/d2459a241b54d596ebdb9d81637400279fff4f2d">d2459a241b</a></p></td>
+<td><p>2022-07-13</p></td>
+<td><p><code class="docutils literal notranslate"><span class="pre">Add</span> <span class="pre">documentation</span> <span class="pre">for</span> <span class="pre">July</span> <span class="pre">2022</span> <span class="pre">Provider's</span> <span class="pre">release</span> <span class="pre">(#25030)</span></code></p></td>
+</tr>
+<tr class="row-odd"><td><p><a class="reference external" href="https://github.com/apache/airflow/commit/acaa0635c8477c98ab78da9f6d86e6f1bad2737d">acaa0635c8</a></p></td>
+<td><p>2022-07-08</p></td>
+<td><p><code class="docutils literal notranslate"><span class="pre">Automatically</span> <span class="pre">detect</span> <span class="pre">if</span> <span class="pre">non-lazy</span> <span class="pre">logging</span> <span class="pre">interpolation</span> <span class="pre">is</span> <span class="pre">used</span> <span class="pre">(#24910)</span></code></p></td>
+</tr>
+<tr class="row-even"><td><p><a class="reference external" href="https://github.com/apache/airflow/commit/0de31bd73a8f41dded2907f0dee59dfa6c1ed7a1">0de31bd73a</a></p></td>
+<td><p>2022-06-29</p></td>
+<td><p><code class="docutils literal notranslate"><span class="pre">Move</span> <span class="pre">provider</span> <span class="pre">dependencies</span> <span class="pre">to</span> <span class="pre">inside</span> <span class="pre">provider</span> <span class="pre">folders</span> <span class="pre">(#24672)</span></code></p></td>
+</tr>
+<tr class="row-odd"><td><p><a class="reference external" href="https://github.com/apache/airflow/commit/510a6bab4595cce8bd5b1447db957309d70f35d9">510a6bab45</a></p></td>
+<td><p>2022-06-28</p></td>
+<td><p><code class="docutils literal notranslate"><span class="pre">Remove</span> <span class="pre">'hook-class-names'</span> <span class="pre">from</span> <span class="pre">provider.yaml</span> <span class="pre">(#24702)</span></code></p></td>
+</tr>
+<tr class="row-even"><td><p><a class="reference external" href="https://github.com/apache/airflow/commit/f3aacebe502c4ea5dc2b7d29373539296fa037eb">f3aacebe50</a></p></td>
+<td><p>2022-06-20</p></td>
+<td><p><code class="docutils literal notranslate"><span class="pre">Convert</span> <span class="pre">sftp</span> <span class="pre">hook</span> <span class="pre">to</span> <span class="pre">use</span> <span class="pre">paramiko</span> <span class="pre">instead</span> <span class="pre">of</span> <span class="pre">pysftp</span> <span class="pre">(#24512)</span></code></p></td>
+</tr>
+<tr class="row-odd"><td><p><a class="reference external" href="https://github.com/apache/airflow/commit/ad297c91777277e2b76dd7b7f0e3e3fc5c32e07c">ad297c9177</a></p></td>
+<td><p>2022-06-17</p></td>
+<td><p><code class="docutils literal notranslate"><span class="pre">Update</span> <span class="pre">'actual_file_to_check'</span> <span class="pre">with</span> <span class="pre">rendered</span> <span class="pre">'path'</span> <span class="pre">(#24451)</span></code></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="id2">
+<h2>3.0.0<a class="headerlink" href="#id2" title="Permalink to this heading">ΒΆ</a></h2>
+<p>Latest change: 2022-06-09</p>
 <table class="docutils align-default">
 <colgroup>
 <col style="width: 51%" />
@@ -598,27 +641,31 @@ For high-level changelog, see <a class="reference internal" href="index.html"><s
 </tr>
 </thead>
 <tbody>
-<tr class="row-even"><td><p><a class="reference external" href="https://github.com/apache/airflow/commit/717a7588bc8170363fea5cb75f17efcf68689619">717a7588bc</a></p></td>
+<tr class="row-even"><td><p><a class="reference external" href="https://github.com/apache/airflow/commit/dcdcf3a2b8054fa727efb4cd79d38d2c9c7e1bd5">dcdcf3a2b8</a></p></td>
+<td><p>2022-06-09</p></td>
+<td><p><code class="docutils literal notranslate"><span class="pre">Update</span> <span class="pre">release</span> <span class="pre">notes</span> <span class="pre">for</span> <span class="pre">RC2</span> <span class="pre">release</span> <span class="pre">of</span> <span class="pre">Providers</span> <span class="pre">for</span> <span class="pre">May</span> <span class="pre">2022</span> <span class="pre">(#24307)</span></code></p></td>
+</tr>
+<tr class="row-odd"><td><p><a class="reference external" href="https://github.com/apache/airflow/commit/717a7588bc8170363fea5cb75f17efcf68689619">717a7588bc</a></p></td>
 <td><p>2022-06-07</p></td>
 <td><p><code class="docutils literal notranslate"><span class="pre">Update</span> <span class="pre">package</span> <span class="pre">description</span> <span class="pre">to</span> <span class="pre">remove</span> <span class="pre">double</span> <span class="pre">min-airflow</span> <span class="pre">specification</span> <span class="pre">(#24292)</span></code></p></td>
 </tr>
-<tr class="row-odd"><td><p><a class="reference external" href="https://github.com/apache/airflow/commit/aeabe994b3381d082f75678a159ddbb3cbf6f4d3">aeabe994b3</a></p></td>
+<tr class="row-even"><td><p><a class="reference external" href="https://github.com/apache/airflow/commit/aeabe994b3381d082f75678a159ddbb3cbf6f4d3">aeabe994b3</a></p></td>
 <td><p>2022-06-07</p></td>
 <td><p><code class="docutils literal notranslate"><span class="pre">Prepare</span> <span class="pre">docs</span> <span class="pre">for</span> <span class="pre">May</span> <span class="pre">2022</span> <span class="pre">provider's</span> <span class="pre">release</span> <span class="pre">(#24231)</span></code></p></td>
 </tr>
-<tr class="row-even"><td><p><a class="reference external" href="https://github.com/apache/airflow/commit/e656e1de55094e8369cab80b9b1669b1d1225f54">e656e1de55</a></p></td>
+<tr class="row-odd"><td><p><a class="reference external" href="https://github.com/apache/airflow/commit/e656e1de55094e8369cab80b9b1669b1d1225f54">e656e1de55</a></p></td>
 <td><p>2022-06-06</p></td>
 <td><p><code class="docutils literal notranslate"><span class="pre">Adding</span> <span class="pre">fnmatch</span> <span class="pre">type</span> <span class="pre">regex</span> <span class="pre">to</span> <span class="pre">SFTPSensor</span> <span class="pre">(#24084)</span></code></p></td>
 </tr>
-<tr class="row-odd"><td><p><a class="reference external" href="https://github.com/apache/airflow/commit/027b707d215a9ff1151717439790effd44bab508">027b707d21</a></p></td>
+<tr class="row-even"><td><p><a class="reference external" href="https://github.com/apache/airflow/commit/027b707d215a9ff1151717439790effd44bab508">027b707d21</a></p></td>
 <td><p>2022-06-05</p></td>
 <td><p><code class="docutils literal notranslate"><span class="pre">Add</span> <span class="pre">explanatory</span> <span class="pre">note</span> <span class="pre">for</span> <span class="pre">contributors</span> <span class="pre">about</span> <span class="pre">updating</span> <span class="pre">Changelog</span> <span class="pre">(#24229)</span></code></p></td>
 </tr>
 </tbody>
 </table>
 </div>
-<div class="section" id="id2">
-<h2>2.6.0<a class="headerlink" href="#id2" title="Permalink to this headline">ΒΆ</a></h2>
+<div class="section" id="id3">
+<h2>2.6.0<a class="headerlink" href="#id3" title="Permalink to this heading">ΒΆ</a></h2>
 <p>Latest change: 2022-04-07</p>
 <table class="docutils align-default">
 <colgroup>
@@ -644,8 +691,8 @@ For high-level changelog, see <a class="reference internal" href="index.html"><s
 </tbody>
 </table>
 </div>
-<div class="section" id="id3">
-<h2>2.5.2<a class="headerlink" href="#id3" title="Permalink to this headline">ΒΆ</a></h2>
+<div class="section" id="id4">
+<h2>2.5.2<a class="headerlink" href="#id4" title="Permalink to this heading">ΒΆ</a></h2>
 <p>Latest change: 2022-03-22</p>
 <table class="docutils align-default">
 <colgroup>
@@ -667,8 +714,8 @@ For high-level changelog, see <a class="reference internal" href="index.html"><s
 </tbody>
 </table>
 </div>
-<div class="section" id="id4">
-<h2>2.5.1<a class="headerlink" href="#id4" title="Permalink to this headline">ΒΆ</a></h2>
+<div class="section" id="id5">
+<h2>2.5.1<a class="headerlink" href="#id5" title="Permalink to this heading">ΒΆ</a></h2>
 <p>Latest change: 2022-03-14</p>
 <table class="docutils align-default">
 <colgroup>
@@ -690,8 +737,8 @@ For high-level changelog, see <a class="reference internal" href="index.html"><s
 </tbody>
 </table>
 </div>
-<div class="section" id="id5">
-<h2>2.5.0<a class="headerlink" href="#id5" title="Permalink to this headline">ΒΆ</a></h2>
+<div class="section" id="id6">
+<h2>2.5.0<a class="headerlink" href="#id6" title="Permalink to this heading">ΒΆ</a></h2>
 <p>Latest change: 2022-03-07</p>
 <table class="docutils align-default">
 <colgroup>
@@ -733,8 +780,8 @@ For high-level changelog, see <a class="reference internal" href="index.html"><s
 </tbody>
 </table>
 </div>
-<div class="section" id="id6">
-<h2>2.4.1<a class="headerlink" href="#id6" title="Permalink to this headline">ΒΆ</a></h2>
+<div class="section" id="id7">
+<h2>2.4.1<a class="headerlink" href="#id7" title="Permalink to this heading">ΒΆ</a></h2>
 <p>Latest change: 2022-01-08</p>
 <table class="docutils align-default">
 <colgroup>
@@ -764,8 +811,8 @@ For high-level changelog, see <a class="reference internal" href="index.html"><s
 </tbody>
 </table>
 </div>
-<div class="section" id="id7">
-<h2>2.4.0<a class="headerlink" href="#id7" title="Permalink to this headline">ΒΆ</a></h2>
+<div class="section" id="id8">
+<h2>2.4.0<a class="headerlink" href="#id8" title="Permalink to this heading">ΒΆ</a></h2>
 <p>Latest change: 2021-12-31</p>
 <table class="docutils align-default">
 <colgroup>
@@ -807,8 +854,8 @@ For high-level changelog, see <a class="reference internal" href="index.html"><s
 </tbody>
 </table>
 </div>
-<div class="section" id="id8">
-<h2>2.3.0<a class="headerlink" href="#id8" title="Permalink to this headline">ΒΆ</a></h2>
+<div class="section" id="id9">
+<h2>2.3.0<a class="headerlink" href="#id9" title="Permalink to this heading">ΒΆ</a></h2>
 <p>Latest change: 2021-11-30</p>
 <table class="docutils align-default">
 <colgroup>
@@ -834,8 +881,8 @@ For high-level changelog, see <a class="reference internal" href="index.html"><s
 </tbody>
 </table>
 </div>
-<div class="section" id="id9">
-<h2>2.2.0<a class="headerlink" href="#id9" title="Permalink to this headline">ΒΆ</a></h2>
+<div class="section" id="id10">
+<h2>2.2.0<a class="headerlink" href="#id10" title="Permalink to this heading">ΒΆ</a></h2>
 <p>Latest change: 2021-10-29</p>
 <table class="docutils align-default">
 <colgroup>
@@ -865,8 +912,8 @@ For high-level changelog, see <a class="reference internal" href="index.html"><s
 </tbody>
 </table>
 </div>
-<div class="section" id="id10">
-<h2>2.1.1<a class="headerlink" href="#id10" title="Permalink to this headline">ΒΆ</a></h2>
+<div class="section" id="id11">
+<h2>2.1.1<a class="headerlink" href="#id11" title="Permalink to this heading">ΒΆ</a></h2>
 <p>Latest change: 2021-08-30</p>
 <table class="docutils align-default">
 <colgroup>
@@ -896,8 +943,8 @@ For high-level changelog, see <a class="reference internal" href="index.html"><s
 </tbody>
 </table>
 </div>
-<div class="section" id="id11">
-<h2>2.1.0<a class="headerlink" href="#id11" title="Permalink to this headline">ΒΆ</a></h2>
+<div class="section" id="id12">
+<h2>2.1.0<a class="headerlink" href="#id12" title="Permalink to this heading">ΒΆ</a></h2>
 <p>Latest change: 2021-07-26</p>
 <table class="docutils align-default">
 <colgroup>
@@ -935,8 +982,8 @@ For high-level changelog, see <a class="reference internal" href="index.html"><s
 </tbody>
 </table>
 </div>
-<div class="section" id="id12">
-<h2>2.0.0<a class="headerlink" href="#id12" title="Permalink to this headline">ΒΆ</a></h2>
+<div class="section" id="id13">
+<h2>2.0.0<a class="headerlink" href="#id13" title="Permalink to this heading">ΒΆ</a></h2>
 <p>Latest change: 2021-06-18</p>
 <table class="docutils align-default">
 <colgroup>
@@ -978,8 +1025,8 @@ For high-level changelog, see <a class="reference internal" href="index.html"><s
 </tbody>
 </table>
 </div>
-<div class="section" id="id13">
-<h2>1.2.0<a class="headerlink" href="#id13" title="Permalink to this headline">ΒΆ</a></h2>
+<div class="section" id="id14">
+<h2>1.2.0<a class="headerlink" href="#id14" title="Permalink to this heading">ΒΆ</a></h2>
 <p>Latest change: 2021-05-01</p>
 <table class="docutils align-default">
 <colgroup>
@@ -1017,8 +1064,8 @@ For high-level changelog, see <a class="reference internal" href="index.html"><s
 </tbody>
 </table>
 </div>
-<div class="section" id="id14">
-<h2>1.1.1<a class="headerlink" href="#id14" title="Permalink to this headline">ΒΆ</a></h2>
+<div class="section" id="id15">
+<h2>1.1.1<a class="headerlink" href="#id15" title="Permalink to this heading">ΒΆ</a></h2>
 <p>Latest change: 2021-02-27</p>
 <table class="docutils align-default">
 <colgroup>
@@ -1044,8 +1091,8 @@ For high-level changelog, see <a class="reference internal" href="index.html"><s
 </tbody>
 </table>
 </div>
-<div class="section" id="id15">
-<h2>1.1.0<a class="headerlink" href="#id15" title="Permalink to this headline">ΒΆ</a></h2>
+<div class="section" id="id16">
+<h2>1.1.0<a class="headerlink" href="#id16" title="Permalink to this heading">ΒΆ</a></h2>
 <p>Latest change: 2021-02-04</p>
 <table class="docutils align-default">
 <colgroup>
@@ -1099,8 +1146,8 @@ For high-level changelog, see <a class="reference internal" href="index.html"><s
 </tbody>
 </table>
 </div>
-<div class="section" id="id16">
-<h2>1.0.0<a class="headerlink" href="#id16" title="Permalink to this headline">ΒΆ</a></h2>
+<div class="section" id="id17">
+<h2>1.0.0<a class="headerlink" href="#id17" title="Permalink to this heading">ΒΆ</a></h2>
 <p>Latest change: 2020-12-09</p>
 <table class="docutils align-default">
 <colgroup>
@@ -1389,22 +1436,23 @@ For high-level changelog, see <a class="reference internal" href="index.html"><s
         <div class="wy-menu-vertical">
             <ul>
 <li><a class="reference internal" href="#">Package apache-airflow-providers-sftp</a><ul>
-<li><a class="reference internal" href="#id1">3.0.0</a></li>
-<li><a class="reference internal" href="#id2">2.6.0</a></li>
-<li><a class="reference internal" href="#id3">2.5.2</a></li>
-<li><a class="reference internal" href="#id4">2.5.1</a></li>
-<li><a class="reference internal" href="#id5">2.5.0</a></li>
-<li><a class="reference internal" href="#id6">2.4.1</a></li>
-<li><a class="reference internal" href="#id7">2.4.0</a></li>
-<li><a class="reference internal" href="#id8">2.3.0</a></li>
-<li><a class="reference internal" href="#id9">2.2.0</a></li>
-<li><a class="reference internal" href="#id10">2.1.1</a></li>
-<li><a class="reference internal" href="#id11">2.1.0</a></li>
-<li><a class="reference internal" href="#id12">2.0.0</a></li>
-<li><a class="reference internal" href="#id13">1.2.0</a></li>
-<li><a class="reference internal" href="#id14">1.1.1</a></li>
-<li><a class="reference internal" href="#id15">1.1.0</a></li>
-<li><a class="reference internal" href="#id16">1.0.0</a></li>
+<li><a class="reference internal" href="#id1">4.0.0</a></li>
+<li><a class="reference internal" href="#id2">3.0.0</a></li>
+<li><a class="reference internal" href="#id3">2.6.0</a></li>
+<li><a class="reference internal" href="#id4">2.5.2</a></li>
+<li><a class="reference internal" href="#id5">2.5.1</a></li>
+<li><a class="reference internal" href="#id6">2.5.0</a></li>
+<li><a class="reference internal" href="#id7">2.4.1</a></li>
+<li><a class="reference internal" href="#id8">2.4.0</a></li>
+<li><a class="reference internal" href="#id9">2.3.0</a></li>
+<li><a class="reference internal" href="#id10">2.2.0</a></li>
+<li><a class="reference internal" href="#id11">2.1.1</a></li>
+<li><a class="reference internal" href="#id12">2.1.0</a></li>
+<li><a class="reference internal" href="#id13">2.0.0</a></li>
+<li><a class="reference internal" href="#id14">1.2.0</a></li>
+<li><a class="reference internal" href="#id15">1.1.1</a></li>
+<li><a class="reference internal" href="#id16">1.1.0</a></li>
+<li><a class="reference internal" href="#id17">1.0.0</a></li>
 </ul>
 </li>
 </ul>
@@ -1571,6 +1619,7 @@ For high-level changelog, see <a class="reference internal" href="index.html"><s
         <script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
         <script src="_static/jquery.js"></script>
         <script src="_static/underscore.js"></script>
+        <script src="_static/_sphinx_javascript_frameworks_compat.js"></script>
         <script src="_static/doctools.js"></script>
         <script src="_static/clipboard.min.js"></script>
         <script src="_static/copybutton.js"></script>
diff --git a/docs/apache-airflow-providers-sftp/stable/connections/sftp.html b/docs/apache-airflow-providers-sftp/4.0.0/connections/sftp.html
similarity index 95%
copy from docs/apache-airflow-providers-sftp/stable/connections/sftp.html
copy to docs/apache-airflow-providers-sftp/4.0.0/connections/sftp.html
index ce13400bf4..c07b6094f7 100644
--- a/docs/apache-airflow-providers-sftp/stable/connections/sftp.html
+++ b/docs/apache-airflow-providers-sftp/4.0.0/connections/sftp.html
@@ -5,7 +5,7 @@
 <!DOCTYPE html>
 <!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
 <!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
-    <html xmlns="http://www.w3.org/1999/xhtml">
+    <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
 <head>
         <meta charset="utf-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1">
@@ -284,7 +284,7 @@
 <div id="docs-version-selector" class="docs-version-selector sidebar__version-selector">
     <a class="dropdown-toggle" href="#" id="versionDropdown" role="button" data-toggle="dropdown" aria-haspopup="true"
        aria-expanded="false">
-        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">3.0.0</span>
+        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">4.0.0</span>
     </a>
     <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
 
@@ -421,7 +421,7 @@
 <div id="docs-version-selector" class="docs-version-selector sidebar__version-selector">
     <a class="dropdown-toggle" href="#" id="versionDropdown" role="button" data-toggle="dropdown" aria-haspopup="true"
        aria-expanded="false">
-        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">3.0.0</span>
+        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">4.0.0</span>
     </a>
     <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
 
@@ -579,25 +579,24 @@
   <blockquote>
 <div></div></blockquote>
 <div class="section" id="sftp-connection">
-<span id="howto-connection-sftp"></span><h1>SFTP Connection<a class="headerlink" href="#sftp-connection" title="Permalink to this headline">ΒΆ</a></h1>
+<span id="howto-connection-sftp"></span><h1>SFTP Connection<a class="headerlink" href="#sftp-connection" title="Permalink to this heading">ΒΆ</a></h1>
 <p>The SFTP connection type enables SFTP Integrations.</p>
 <div class="section" id="authenticating-to-sftp">
-<h2>Authenticating to SFTP<a class="headerlink" href="#authenticating-to-sftp" title="Permalink to this headline">ΒΆ</a></h2>
+<h2>Authenticating to SFTP<a class="headerlink" href="#authenticating-to-sftp" title="Permalink to this heading">ΒΆ</a></h2>
 <p>There are two ways to connect to SFTP using Airflow.</p>
 <ol class="arabic simple">
-<li><p>Use <a class="reference external" href="https://pysftp.readthedocs.io/en/release_0.2.9/pysftp.html#pysftp.CnOpts">host key</a>
-i.e. host key entered in extras value <code class="docutils literal notranslate"><span class="pre">host_key</span></code>.</p></li>
-<li><p>Use <code class="docutils literal notranslate"><span class="pre">private_key</span></code> or <code class="docutils literal notranslate"><span class="pre">key_file</span></code>, along with the optional <code class="docutils literal notranslate"><span class="pre">private_key_pass</span></code></p></li>
+<li><p>Use <code class="docutils literal notranslate"><span class="pre">login</span></code> and <code class="docutils literal notranslate"><span class="pre">password</span></code>.</p></li>
+<li><p>Use <code class="docutils literal notranslate"><span class="pre">private_key</span></code> or <code class="docutils literal notranslate"><span class="pre">key_file</span></code>, along with the optional <code class="docutils literal notranslate"><span class="pre">private_key_passphrase</span></code></p></li>
 </ol>
 <p>Only one authorization method can be used at a time. If you need to manage multiple credentials or keys then you should
 configure multiple connections.</p>
 </div>
 <div class="section" id="default-connection-ids">
-<h2>Default Connection IDs<a class="headerlink" href="#default-connection-ids" title="Permalink to this headline">ΒΆ</a></h2>
+<h2>Default Connection IDs<a class="headerlink" href="#default-connection-ids" title="Permalink to this heading">ΒΆ</a></h2>
 <p>Hooks, operators, and sensors related to SFTP use <code class="docutils literal notranslate"><span class="pre">sftp_default</span></code> by default.</p>
 </div>
 <div class="section" id="configuring-the-connection">
-<h2>Configuring the Connection<a class="headerlink" href="#configuring-the-connection" title="Permalink to this headline">ΒΆ</a></h2>
+<h2>Configuring the Connection<a class="headerlink" href="#configuring-the-connection" title="Permalink to this heading">ΒΆ</a></h2>
 <dl class="simple">
 <dt>Login (optional)</dt><dd><p>Specify the sftp username for the remote machine.</p>
 </dd>
@@ -610,17 +609,18 @@ configure multiple connections.</p>
 <dt>Extra (optional)</dt><dd><p>Specify the extra parameters (as json dictionary) that can be used in sftp connection.
 The following parameters are all optional:</p>
 <ul class="simple">
-<li><p><code class="docutils literal notranslate"><span class="pre">private_key_pass</span></code>: Specify the password to use, if private_key is encrypted.</p></li>
-<li><p><code class="docutils literal notranslate"><span class="pre">no_host_key_check</span></code>: Set to false to restrict connecting to hosts with either no entries in ~/.ssh/known_hosts
-(Hosts file) or not present in the host_key extra. This provides maximum protection against trojan horse attacks,
-but can be troublesome when the /etc/ssh/ssh_known_hosts file is poorly maintained or connections to new hosts are
-frequently made. This option forces the user to manually add all new hosts. Default is true, ssh will automatically
-add new host keys to the user known hosts files.</p></li>
-<li><p><code class="docutils literal notranslate"><span class="pre">host_key</span></code>: The base64 encoded ssh-rsa public key of the host, as you would find in the known_hosts file.
-Specifying this, along with no_host_key_check=False allows you to only make the connection if the public key of
-the endpoint matches this value.</p></li>
-<li><p><code class="docutils literal notranslate"><span class="pre">private_key</span></code> Specify the content of the private key, the path to the private key file(str) or paramiko.AgentKey</p></li>
 <li><p><code class="docutils literal notranslate"><span class="pre">key_file</span></code> - Full Path of the private SSH Key file that will be used to connect to the remote_host.</p></li>
+<li><p><code class="docutils literal notranslate"><span class="pre">private_key</span></code> - Content of the private key used to connect to the remote_host.</p></li>
+<li><p><code class="docutils literal notranslate"><span class="pre">private_key_passphrase</span></code> - Content of the private key passphrase used to decrypt the private key.</p></li>
+<li><p><code class="docutils literal notranslate"><span class="pre">conn_timeout</span></code> - An optional timeout (in seconds) for the TCP connect. Default is <code class="docutils literal notranslate"><span class="pre">10</span></code>.</p></li>
+<li><p><code class="docutils literal notranslate"><span class="pre">timeout</span></code> - Deprecated - use conn_timeout instead.</p></li>
+<li><p><code class="docutils literal notranslate"><span class="pre">compress</span></code> - <code class="docutils literal notranslate"><span class="pre">true</span></code> to ask the remote client/server to compress traffic; <code class="docutils literal notranslate"><span class="pre">false</span></code> to refuse compression. Default is <code class="docutils literal notranslate"><span class="pre">true</span></code>.</p></li>
+<li><p><code class="docutils literal notranslate"><span class="pre">no_host_key_check</span></code> - Set to <code class="docutils literal notranslate"><span class="pre">false</span></code> to restrict connecting to hosts with no entries in <code class="docutils literal notranslate"><span class="pre">~/.ssh/known_hosts</span></code> (Hosts file). This provides maximum protection against trojan horse attacks, but can be troublesome when the <code class="docutils literal notranslate"><span [...]
+<li><p><code class="docutils literal notranslate"><span class="pre">allow_host_key_change</span></code> - Set to <code class="docutils literal notranslate"><span class="pre">true</span></code> if you want to allow connecting to hosts that has host key changed or when you get β€˜REMOTE HOST IDENTIFICATION HAS CHANGED’ error.  This won’t protect against Man-In-The-Middle attacks. Other possible solution is to remove the host entry from <code class="docutils literal notranslate"><span class=" [...]
+<li><p><code class="docutils literal notranslate"><span class="pre">look_for_keys</span></code> - Set to <code class="docutils literal notranslate"><span class="pre">false</span></code> if you want to disable searching for discoverable private key files in <code class="docutils literal notranslate"><span class="pre">~/.ssh/</span></code></p></li>
+<li><p><code class="docutils literal notranslate"><span class="pre">host_key</span></code> - The base64 encoded ssh-rsa public key of the host or β€œssh-&lt;key type&gt; &lt;key data&gt;” (as you would find in the <code class="docutils literal notranslate"><span class="pre">known_hosts</span></code> file). Specifying this allows making the connection if and only if the public key of the endpoint matches this value.</p></li>
+<li><p><code class="docutils literal notranslate"><span class="pre">disabled_algorithms</span></code> - A dictionary mapping algorithm type to an iterable of algorithm identifiers, which will be disabled for the lifetime of the transport.</p></li>
+<li><p><code class="docutils literal notranslate"><span class="pre">ciphers</span></code> - A list of ciphers to use in order of preference.</p></li>
 </ul>
 </dd>
 </dl>
@@ -898,6 +898,7 @@ it using URI syntax.</p>
         <script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
         <script src="../_static/jquery.js"></script>
         <script src="../_static/underscore.js"></script>
+        <script src="../_static/_sphinx_javascript_frameworks_compat.js"></script>
         <script src="../_static/doctools.js"></script>
         <script src="../_static/clipboard.min.js"></script>
         <script src="../_static/copybutton.js"></script>
diff --git a/docs/apache-airflow-providers-sftp/stable/genindex.html b/docs/apache-airflow-providers-sftp/4.0.0/genindex.html
similarity index 98%
copy from docs/apache-airflow-providers-sftp/stable/genindex.html
copy to docs/apache-airflow-providers-sftp/4.0.0/genindex.html
index 575952da66..4e5080073e 100644
--- a/docs/apache-airflow-providers-sftp/stable/genindex.html
+++ b/docs/apache-airflow-providers-sftp/4.0.0/genindex.html
@@ -5,7 +5,7 @@
 <!DOCTYPE html>
 <!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
 <!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
-    <html xmlns="http://www.w3.org/1999/xhtml">
+    <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
 <head>
         <meta charset="utf-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1">
@@ -282,7 +282,7 @@
 <div id="docs-version-selector" class="docs-version-selector sidebar__version-selector">
     <a class="dropdown-toggle" href="#" id="versionDropdown" role="button" data-toggle="dropdown" aria-haspopup="true"
        aria-expanded="false">
-        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">3.0.0</span>
+        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">4.0.0</span>
     </a>
     <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
 
@@ -419,7 +419,7 @@
 <div id="docs-version-selector" class="docs-version-selector sidebar__version-selector">
     <a class="dropdown-toggle" href="#" id="versionDropdown" role="button" data-toggle="dropdown" aria-haspopup="true"
        aria-expanded="false">
-        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">3.0.0</span>
+        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">4.0.0</span>
     </a>
     <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
 
@@ -584,12 +584,14 @@
  | <a href="#E"><strong>E</strong></a>
  | <a href="#G"><strong>G</strong></a>
  | <a href="#H"><strong>H</strong></a>
+ | <a href="#I"><strong>I</strong></a>
  | <a href="#L"><strong>L</strong></a>
  | <a href="#M"><strong>M</strong></a>
  | <a href="#P"><strong>P</strong></a>
  | <a href="#R"><strong>R</strong></a>
  | <a href="#S"><strong>S</strong></a>
  | <a href="#T"><strong>T</strong></a>
+ | <a href="#W"><strong>W</strong></a>
  
 </div>
 <h2 id="A">A</h2>
@@ -717,6 +719,18 @@
   </ul></td>
 </tr></table>
 
+<h2 id="I">I</h2>
+<table style="width: 100%" class="indextable genindextable"><tr>
+  <td style="width: 33%; vertical-align: top;"><ul>
+      <li><a href="_api/airflow/providers/sftp/hooks/sftp/index.html#airflow.providers.sftp.hooks.sftp.SFTPHook.isdir">isdir() (airflow.providers.sftp.hooks.sftp.SFTPHook method)</a>
+</li>
+  </ul></td>
+  <td style="width: 33%; vertical-align: top;"><ul>
+      <li><a href="_api/airflow/providers/sftp/hooks/sftp/index.html#airflow.providers.sftp.hooks.sftp.SFTPHook.isfile">isfile() (airflow.providers.sftp.hooks.sftp.SFTPHook method)</a>
+</li>
+  </ul></td>
+</tr></table>
+
 <h2 id="L">L</h2>
 <table style="width: 100%" class="indextable genindextable"><tr>
   <td style="width: 33%; vertical-align: top;"><ul>
@@ -728,6 +742,8 @@
 <h2 id="M">M</h2>
 <table style="width: 100%" class="indextable genindextable"><tr>
   <td style="width: 33%; vertical-align: top;"><ul>
+      <li><a href="_api/airflow/providers/sftp/hooks/sftp/index.html#airflow.providers.sftp.hooks.sftp.SFTPHook.mkdir">mkdir() (airflow.providers.sftp.hooks.sftp.SFTPHook method)</a>
+</li>
       <li>
     module
 
@@ -806,6 +822,14 @@
   </ul></td>
 </tr></table>
 
+<h2 id="W">W</h2>
+<table style="width: 100%" class="indextable genindextable"><tr>
+  <td style="width: 33%; vertical-align: top;"><ul>
+      <li><a href="_api/airflow/providers/sftp/hooks/sftp/index.html#airflow.providers.sftp.hooks.sftp.SFTPHook.walktree">walktree() (airflow.providers.sftp.hooks.sftp.SFTPHook method)</a>
+</li>
+  </ul></td>
+</tr></table>
+
 
 
     <div class="pager" role="navigation" aria-label="related navigation"><button class="btn-hollow btn-blue bodytext__medium--cerulean-blue" disabled>Previous</button><button class="btn-hollow btn-blue bodytext__medium--cerulean-blue" disabled>Next</button>
@@ -1038,6 +1062,7 @@
         <script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
         <script src="_static/jquery.js"></script>
         <script src="_static/underscore.js"></script>
+        <script src="_static/_sphinx_javascript_frameworks_compat.js"></script>
         <script src="_static/doctools.js"></script>
         <script src="_static/clipboard.min.js"></script>
         <script src="_static/copybutton.js"></script>
diff --git a/docs/apache-airflow-providers-sftp/stable/index.html b/docs/apache-airflow-providers-sftp/4.0.0/index.html
similarity index 93%
copy from docs/apache-airflow-providers-sftp/stable/index.html
copy to docs/apache-airflow-providers-sftp/4.0.0/index.html
index e2eab52095..fdbcf38c65 100644
--- a/docs/apache-airflow-providers-sftp/stable/index.html
+++ b/docs/apache-airflow-providers-sftp/4.0.0/index.html
@@ -5,7 +5,7 @@
 <!DOCTYPE html>
 <!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
 <!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
-    <html xmlns="http://www.w3.org/1999/xhtml">
+    <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
 <head>
         <meta charset="utf-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1">
@@ -283,7 +283,7 @@
 <div id="docs-version-selector" class="docs-version-selector sidebar__version-selector">
     <a class="dropdown-toggle" href="#" id="versionDropdown" role="button" data-toggle="dropdown" aria-haspopup="true"
        aria-expanded="false">
-        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">3.0.0</span>
+        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">4.0.0</span>
     </a>
     <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
 
@@ -420,7 +420,7 @@
 <div id="docs-version-selector" class="docs-version-selector sidebar__version-selector">
     <a class="dropdown-toggle" href="#" id="versionDropdown" role="button" data-toggle="dropdown" aria-haspopup="true"
        aria-expanded="false">
-        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">3.0.0</span>
+        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">4.0.0</span>
     </a>
     <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
 
@@ -578,9 +578,9 @@
   <blockquote>
 <div></div></blockquote>
 <div class="section" id="apache-airflow-providers-sftp">
-<h1><code class="docutils literal notranslate"><span class="pre">apache-airflow-providers-sftp</span></code><a class="headerlink" href="#apache-airflow-providers-sftp" title="Permalink to this headline">ΒΆ</a></h1>
+<h1><code class="docutils literal notranslate"><span class="pre">apache-airflow-providers-sftp</span></code><a class="headerlink" href="#apache-airflow-providers-sftp" title="Permalink to this heading">ΒΆ</a></h1>
 <div class="section" id="content">
-<h2>Content<a class="headerlink" href="#content" title="Permalink to this headline">ΒΆ</a></h2>
+<h2>Content<a class="headerlink" href="#content" title="Permalink to this heading">ΒΆ</a></h2>
 <div class="toctree-wrapper compound">
 <p class="caption" role="heading"><span class="caption-text">References</span></p>
 <ul>
@@ -603,23 +603,23 @@
 </div>
 </div>
 <div class="section" id="package-apache-airflow-providers-sftp">
-<h2>Package apache-airflow-providers-sftp<a class="headerlink" href="#package-apache-airflow-providers-sftp" title="Permalink to this headline">ΒΆ</a></h2>
+<h2>Package apache-airflow-providers-sftp<a class="headerlink" href="#package-apache-airflow-providers-sftp" title="Permalink to this heading">ΒΆ</a></h2>
 <p><a class="reference external" href="https://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/">SSH File Transfer Protocol (SFTP)</a></p>
-<p>Release: 3.0.0</p>
+<p>Release: 4.0.0</p>
 </div>
 <div class="section" id="provider-package">
-<h2>Provider package<a class="headerlink" href="#provider-package" title="Permalink to this headline">ΒΆ</a></h2>
+<h2>Provider package<a class="headerlink" href="#provider-package" title="Permalink to this heading">ΒΆ</a></h2>
 <p>This is a provider package for <code class="docutils literal notranslate"><span class="pre">sftp</span></code> provider. All classes for this provider package
 are in <code class="docutils literal notranslate"><span class="pre">airflow.providers.sftp</span></code> python package.</p>
 </div>
 <div class="section" id="installation">
-<h2>Installation<a class="headerlink" href="#installation" title="Permalink to this headline">ΒΆ</a></h2>
+<h2>Installation<a class="headerlink" href="#installation" title="Permalink to this heading">ΒΆ</a></h2>
 <p>You can install this package on top of an existing Airflow 2 installation (see <code class="docutils literal notranslate"><span class="pre">Requirements</span></code> below)
 for the minimum Airflow version supported) via
 <code class="docutils literal notranslate"><span class="pre">pip</span> <span class="pre">install</span> <span class="pre">apache-airflow-providers-sftp</span></code></p>
 </div>
 <div class="section" id="requirements">
-<h2>Requirements<a class="headerlink" href="#requirements" title="Permalink to this headline">ΒΆ</a></h2>
+<h2>Requirements<a class="headerlink" href="#requirements" title="Permalink to this heading">ΒΆ</a></h2>
 <table class="docutils align-default">
 <colgroup>
 <col style="width: 64%" />
@@ -637,20 +637,11 @@ for the minimum Airflow version supported) via
 <tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">apache-airflow-providers-ssh</span></code></p></td>
 <td><p><code class="docutils literal notranslate"><span class="pre">&gt;=2.1.0</span></code></p></td>
 </tr>
-<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">paramiko</span></code></p></td>
-<td><p><code class="docutils literal notranslate"><span class="pre">&gt;=2.6.0</span></code></p></td>
-</tr>
-<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">pysftp</span></code></p></td>
-<td><p><code class="docutils literal notranslate"><span class="pre">&gt;=0.2.9</span></code></p></td>
-</tr>
-<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">sshtunnel</span></code></p></td>
-<td><p><code class="docutils literal notranslate"><span class="pre">&gt;=0.3.2</span></code></p></td>
-</tr>
 </tbody>
 </table>
 </div>
 <div class="section" id="cross-provider-package-dependencies">
-<h2>Cross provider package dependencies<a class="headerlink" href="#cross-provider-package-dependencies" title="Permalink to this headline">ΒΆ</a></h2>
+<h2>Cross provider package dependencies<a class="headerlink" href="#cross-provider-package-dependencies" title="Permalink to this heading">ΒΆ</a></h2>
 <p>Those are dependencies that might be needed in order to use all the features of the package.
 You need to install the specified provider packages in order to use them.</p>
 <p>You can install such cross-provider dependencies when installing from PyPI. For example:</p>
@@ -675,136 +666,151 @@ You need to install the specified provider packages in order to use them.</p>
 </table>
 </div>
 <div class="section" id="downloading-official-packages">
-<h2>Downloading official packages<a class="headerlink" href="#downloading-official-packages" title="Permalink to this headline">ΒΆ</a></h2>
+<h2>Downloading official packages<a class="headerlink" href="#downloading-official-packages" title="Permalink to this heading">ΒΆ</a></h2>
 <p>You can download officially released packages and verify their checksums and signatures from the
 <a class="reference external" href="https://downloads.apache.org/airflow/providers/">Official Apache Download site</a></p>
 <ul class="simple">
-<li><p><a class="reference external" href="https://downloads.apache.org/airflow/providers/apache-airflow-providers-sftp-3.0.0.tar.gz">The apache-airflow-providers-sftp 3.0.0 sdist package</a> (<a class="reference external" href="https://downloads.apache.org/airflow/providers/apache-airflow-providers-sftp-3.0.0.tar.gz.asc">asc</a>, <a class="reference external" href="https://downloads.apache.org/airflow/providers/apache-airflow-providers-sftp-3.0.0.tar.gz.sha512">sha512</a>)</p></li>
-<li><p><a class="reference external" href="https://downloads.apache.org/airflow/providers/apache_airflow_providers_sftp-3.0.0-py3-none-any.whl">The apache-airflow-providers-sftp 3.0.0 wheel package</a> (<a class="reference external" href="https://downloads.apache.org/airflow/providers/apache_airflow_providers_sftp-3.0.0-py3-none-any.whl.asc">asc</a>, <a class="reference external" href="https://downloads.apache.org/airflow/providers/apache_airflow_providers_sftp-3.0.0-py3-none-any.whl.sha [...]
+<li><p><a class="reference external" href="https://downloads.apache.org/airflow/providers/apache-airflow-providers-sftp-4.0.0.tar.gz">The apache-airflow-providers-sftp 4.0.0 sdist package</a> (<a class="reference external" href="https://downloads.apache.org/airflow/providers/apache-airflow-providers-sftp-4.0.0.tar.gz.asc">asc</a>, <a class="reference external" href="https://downloads.apache.org/airflow/providers/apache-airflow-providers-sftp-4.0.0.tar.gz.sha512">sha512</a>)</p></li>
+<li><p><a class="reference external" href="https://downloads.apache.org/airflow/providers/apache_airflow_providers_sftp-4.0.0-py3-none-any.whl">The apache-airflow-providers-sftp 4.0.0 wheel package</a> (<a class="reference external" href="https://downloads.apache.org/airflow/providers/apache_airflow_providers_sftp-4.0.0-py3-none-any.whl.asc">asc</a>, <a class="reference external" href="https://downloads.apache.org/airflow/providers/apache_airflow_providers_sftp-4.0.0-py3-none-any.whl.sha [...]
 </ul>
 <blockquote>
 <div></div></blockquote>
 </div>
 <div class="section" id="changelog">
-<h2>Changelog<a class="headerlink" href="#changelog" title="Permalink to this headline">ΒΆ</a></h2>
+<h2>Changelog<a class="headerlink" href="#changelog" title="Permalink to this heading">ΒΆ</a></h2>
 <div class="section" id="id1">
-<h3>3.0.0<a class="headerlink" href="#id1" title="Permalink to this headline">ΒΆ</a></h3>
+<h3>4.0.0<a class="headerlink" href="#id1" title="Permalink to this heading">ΒΆ</a></h3>
 <div class="section" id="breaking-changes">
-<h4>Breaking changes<a class="headerlink" href="#breaking-changes" title="Permalink to this headline">ΒΆ</a></h4>
+<h4>Breaking changes<a class="headerlink" href="#breaking-changes" title="Permalink to this heading">ΒΆ</a></h4>
 <ul class="simple">
-<li><p>This release of provider is only available for Airflow 2.2+ as explained in the Apache Airflow
-providers support policy <a class="reference external" href="https://github.com/apache/airflow/blob/main/README.md#support-for-providers">https://github.com/apache/airflow/blob/main/README.md#support-for-providers</a></p></li>
+<li><p><code class="docutils literal notranslate"><span class="pre">Convert</span> <span class="pre">sftp</span> <span class="pre">hook</span> <span class="pre">to</span> <span class="pre">use</span> <span class="pre">paramiko</span> <span class="pre">instead</span> <span class="pre">of</span> <span class="pre">pysftp</span> <span class="pre">(#24512)</span></code></p></li>
 </ul>
 </div>
 <div class="section" id="features">
-<h4>Features<a class="headerlink" href="#features" title="Permalink to this headline">ΒΆ</a></h4>
+<h4>Features<a class="headerlink" href="#features" title="Permalink to this heading">ΒΆ</a></h4>
 <ul class="simple">
-<li><p><code class="docutils literal notranslate"><span class="pre">Adding</span> <span class="pre">fnmatch</span> <span class="pre">type</span> <span class="pre">regex</span> <span class="pre">to</span> <span class="pre">SFTPSensor</span> <span class="pre">(#24084)</span></code></p></li>
+<li><p><code class="docutils literal notranslate"><span class="pre">Update</span> <span class="pre">'actual_file_to_check'</span> <span class="pre">with</span> <span class="pre">rendered</span> <span class="pre">'path'</span> <span class="pre">(#24451)</span></code></p></li>
 </ul>
 </div>
 </div>
 <div class="section" id="id2">
-<h3>2.6.0<a class="headerlink" href="#id2" title="Permalink to this headline">ΒΆ</a></h3>
+<h3>3.0.0<a class="headerlink" href="#id2" title="Permalink to this heading">ΒΆ</a></h3>
 <div class="section" id="id3">
-<h4>Features<a class="headerlink" href="#id3" title="Permalink to this headline">ΒΆ</a></h4>
+<h4>Breaking changes<a class="headerlink" href="#id3" title="Permalink to this heading">ΒΆ</a></h4>
+<ul class="simple">
+<li><p>This release of provider is only available for Airflow 2.2+ as explained in the Apache Airflow
+providers support policy <a class="reference external" href="https://github.com/apache/airflow/blob/main/README.md#support-for-providers">https://github.com/apache/airflow/blob/main/README.md#support-for-providers</a></p></li>
+</ul>
+</div>
+<div class="section" id="id4">
+<h4>Features<a class="headerlink" href="#id4" title="Permalink to this heading">ΒΆ</a></h4>
+<ul class="simple">
+<li><p><code class="docutils literal notranslate"><span class="pre">Adding</span> <span class="pre">fnmatch</span> <span class="pre">type</span> <span class="pre">regex</span> <span class="pre">to</span> <span class="pre">SFTPSensor</span> <span class="pre">(#24084)</span></code></p></li>
+</ul>
+</div>
+</div>
+<div class="section" id="id5">
+<h3>2.6.0<a class="headerlink" href="#id5" title="Permalink to this heading">ΒΆ</a></h3>
+<div class="section" id="id6">
+<h4>Features<a class="headerlink" href="#id6" title="Permalink to this heading">ΒΆ</a></h4>
 <ul class="simple">
 <li><p><code class="docutils literal notranslate"><span class="pre">add</span> <span class="pre">newer_than</span> <span class="pre">parameter</span> <span class="pre">to</span> <span class="pre">SFTP</span> <span class="pre">sensor</span> <span class="pre">(#21655)</span> <span class="pre">(#22377)</span></code></p></li>
 </ul>
 </div>
 </div>
-<div class="section" id="id4">
-<h3>2.5.2<a class="headerlink" href="#id4" title="Permalink to this headline">ΒΆ</a></h3>
+<div class="section" id="id7">
+<h3>2.5.2<a class="headerlink" href="#id7" title="Permalink to this heading">ΒΆ</a></h3>
 <div class="section" id="bug-fixes">
-<h4>Bug Fixes<a class="headerlink" href="#bug-fixes" title="Permalink to this headline">ΒΆ</a></h4>
+<h4>Bug Fixes<a class="headerlink" href="#bug-fixes" title="Permalink to this heading">ΒΆ</a></h4>
 <ul class="simple">
 <li><p><code class="docutils literal notranslate"><span class="pre">Fix</span> <span class="pre">mistakenly</span> <span class="pre">added</span> <span class="pre">install_requires</span> <span class="pre">for</span> <span class="pre">all</span> <span class="pre">providers</span> <span class="pre">(#22382)</span></code></p></li>
 </ul>
 </div>
 </div>
-<div class="section" id="id5">
-<h3>2.5.1<a class="headerlink" href="#id5" title="Permalink to this headline">ΒΆ</a></h3>
+<div class="section" id="id8">
+<h3>2.5.1<a class="headerlink" href="#id8" title="Permalink to this heading">ΒΆ</a></h3>
 <div class="section" id="misc">
-<h4>Misc<a class="headerlink" href="#misc" title="Permalink to this headline">ΒΆ</a></h4>
+<h4>Misc<a class="headerlink" href="#misc" title="Permalink to this heading">ΒΆ</a></h4>
 <ul class="simple">
 <li><p><code class="docutils literal notranslate"><span class="pre">Add</span> <span class="pre">Trove</span> <span class="pre">classifiers</span> <span class="pre">in</span> <span class="pre">PyPI</span> <span class="pre">(Framework</span> <span class="pre">::</span> <span class="pre">Apache</span> <span class="pre">Airflow</span> <span class="pre">::</span> <span class="pre">Provider)</span></code></p></li>
 </ul>
 </div>
 </div>
-<div class="section" id="id6">
-<h3>2.5.0<a class="headerlink" href="#id6" title="Permalink to this headline">ΒΆ</a></h3>
-<div class="section" id="id7">
-<h4>Features<a class="headerlink" href="#id7" title="Permalink to this headline">ΒΆ</a></h4>
+<div class="section" id="id9">
+<h3>2.5.0<a class="headerlink" href="#id9" title="Permalink to this heading">ΒΆ</a></h3>
+<div class="section" id="id10">
+<h4>Features<a class="headerlink" href="#id10" title="Permalink to this heading">ΒΆ</a></h4>
 <ul class="simple">
 <li><p><code class="docutils literal notranslate"><span class="pre">Updates</span> <span class="pre">FTPHook</span> <span class="pre">provider</span> <span class="pre">to</span> <span class="pre">have</span> <span class="pre">test_connection</span> <span class="pre">(#21997)</span></code></p></li>
 </ul>
 </div>
-<div class="section" id="id8">
-<h4>Misc<a class="headerlink" href="#id8" title="Permalink to this headline">ΒΆ</a></h4>
+<div class="section" id="id11">
+<h4>Misc<a class="headerlink" href="#id11" title="Permalink to this heading">ΒΆ</a></h4>
 <ul class="simple">
 <li><p><code class="docutils literal notranslate"><span class="pre">Support</span> <span class="pre">for</span> <span class="pre">Python</span> <span class="pre">3.10</span></code></p></li>
 <li><p><code class="docutils literal notranslate"><span class="pre">Add</span> <span class="pre">optional</span> <span class="pre">features</span> <span class="pre">in</span> <span class="pre">providers.</span> <span class="pre">(#21074)</span></code></p></li>
 </ul>
 </div>
 </div>
-<div class="section" id="id9">
-<h3>2.4.1<a class="headerlink" href="#id9" title="Permalink to this headline">ΒΆ</a></h3>
-<div class="section" id="id10">
-<h4>Bug Fixes<a class="headerlink" href="#id10" title="Permalink to this headline">ΒΆ</a></h4>
+<div class="section" id="id12">
+<h3>2.4.1<a class="headerlink" href="#id12" title="Permalink to this heading">ΒΆ</a></h3>
+<div class="section" id="id13">
+<h4>Bug Fixes<a class="headerlink" href="#id13" title="Permalink to this heading">ΒΆ</a></h4>
 <ul class="simple">
 <li><p><code class="docutils literal notranslate"><span class="pre">Bugfix:</span> <span class="pre">''SFTPHook''</span> <span class="pre">does</span> <span class="pre">not</span> <span class="pre">respect</span> <span class="pre">''ssh_conn_id''</span> <span class="pre">arg</span> <span class="pre">(#20756)</span></code></p></li>
 <li><p><code class="docutils literal notranslate"><span class="pre">fix</span> <span class="pre">deprecation</span> <span class="pre">messages</span> <span class="pre">for</span> <span class="pre">SFTPHook</span> <span class="pre">(#20692)</span></code></p></li>
 </ul>
 </div>
 </div>
-<div class="section" id="id11">
-<h3>2.4.0<a class="headerlink" href="#id11" title="Permalink to this headline">ΒΆ</a></h3>
-<div class="section" id="id12">
-<h4>Features<a class="headerlink" href="#id12" title="Permalink to this headline">ΒΆ</a></h4>
+<div class="section" id="id14">
+<h3>2.4.0<a class="headerlink" href="#id14" title="Permalink to this heading">ΒΆ</a></h3>
+<div class="section" id="id15">
+<h4>Features<a class="headerlink" href="#id15" title="Permalink to this heading">ΒΆ</a></h4>
 <ul class="simple">
 <li><p><code class="docutils literal notranslate"><span class="pre">Making</span> <span class="pre">SFTPHook's</span> <span class="pre">constructor</span> <span class="pre">consistent</span> <span class="pre">with</span> <span class="pre">its</span> <span class="pre">superclass</span> <span class="pre">SSHHook</span> <span class="pre">(#20164)</span></code></p></li>
 </ul>
 </div>
 </div>
-<div class="section" id="id13">
-<h3>2.3.0<a class="headerlink" href="#id13" title="Permalink to this headline">ΒΆ</a></h3>
-<div class="section" id="id14">
-<h4>Features<a class="headerlink" href="#id14" title="Permalink to this headline">ΒΆ</a></h4>
+<div class="section" id="id16">
+<h3>2.3.0<a class="headerlink" href="#id16" title="Permalink to this heading">ΒΆ</a></h3>
+<div class="section" id="id17">
+<h4>Features<a class="headerlink" href="#id17" title="Permalink to this heading">ΒΆ</a></h4>
 <ul class="simple">
 <li><p><code class="docutils literal notranslate"><span class="pre">Add</span> <span class="pre">test_connection</span> <span class="pre">method</span> <span class="pre">for</span> <span class="pre">sftp</span> <span class="pre">hook</span> <span class="pre">(#19609)</span></code></p></li>
 </ul>
 </div>
 </div>
-<div class="section" id="id15">
-<h3>2.2.0<a class="headerlink" href="#id15" title="Permalink to this headline">ΒΆ</a></h3>
-<div class="section" id="id16">
-<h4>Features<a class="headerlink" href="#id16" title="Permalink to this headline">ΒΆ</a></h4>
+<div class="section" id="id18">
+<h3>2.2.0<a class="headerlink" href="#id18" title="Permalink to this heading">ΒΆ</a></h3>
+<div class="section" id="id19">
+<h4>Features<a class="headerlink" href="#id19" title="Permalink to this heading">ΒΆ</a></h4>
 <ul class="simple">
 <li><p><code class="docutils literal notranslate"><span class="pre">SFTP</span> <span class="pre">hook</span> <span class="pre">to</span> <span class="pre">prefer</span> <span class="pre">the</span> <span class="pre">SSH</span> <span class="pre">paramiko</span> <span class="pre">key</span> <span class="pre">over</span> <span class="pre">the</span> <span class="pre">key</span> <span class="pre">file</span> <span class="pre">path</span> <span class="pre">(#18988)</span></code></p></li>
 </ul>
 </div>
 </div>
-<div class="section" id="id17">
-<h3>2.1.1<a class="headerlink" href="#id17" title="Permalink to this headline">ΒΆ</a></h3>
-<div class="section" id="id18">
-<h4>Misc<a class="headerlink" href="#id18" title="Permalink to this headline">ΒΆ</a></h4>
+<div class="section" id="id20">
+<h3>2.1.1<a class="headerlink" href="#id20" title="Permalink to this heading">ΒΆ</a></h3>
+<div class="section" id="id21">
+<h4>Misc<a class="headerlink" href="#id21" title="Permalink to this heading">ΒΆ</a></h4>
 <ul class="simple">
 <li><p><code class="docutils literal notranslate"><span class="pre">Optimise</span> <span class="pre">connection</span> <span class="pre">importing</span> <span class="pre">for</span> <span class="pre">Airflow</span> <span class="pre">2.2.0</span></code></p></li>
 </ul>
 </div>
 </div>
-<div class="section" id="id19">
-<h3>2.1.0<a class="headerlink" href="#id19" title="Permalink to this headline">ΒΆ</a></h3>
-<div class="section" id="id20">
-<h4>Features<a class="headerlink" href="#id20" title="Permalink to this headline">ΒΆ</a></h4>
+<div class="section" id="id22">
+<h3>2.1.0<a class="headerlink" href="#id22" title="Permalink to this heading">ΒΆ</a></h3>
+<div class="section" id="id23">
+<h4>Features<a class="headerlink" href="#id23" title="Permalink to this heading">ΒΆ</a></h4>
 <ul class="simple">
 <li><p><code class="docutils literal notranslate"><span class="pre">Add</span> <span class="pre">support</span> <span class="pre">for</span> <span class="pre">non-RSA</span> <span class="pre">type</span> <span class="pre">key</span> <span class="pre">for</span> <span class="pre">SFTP</span> <span class="pre">hook</span> <span class="pre">(#16314)</span></code></p></li>
 </ul>
 </div>
 </div>
-<div class="section" id="id21">
-<h3>2.0.0<a class="headerlink" href="#id21" title="Permalink to this headline">ΒΆ</a></h3>
-<div class="section" id="id22">
-<h4>Breaking changes<a class="headerlink" href="#id22" title="Permalink to this headline">ΒΆ</a></h4>
+<div class="section" id="id24">
+<h3>2.0.0<a class="headerlink" href="#id24" title="Permalink to this heading">ΒΆ</a></h3>
+<div class="section" id="id25">
+<h4>Breaking changes<a class="headerlink" href="#id25" title="Permalink to this heading">ΒΆ</a></h4>
 <ul class="simple">
 <li><p><code class="docutils literal notranslate"><span class="pre">Auto-apply</span> <span class="pre">apply_default</span> <span class="pre">decorator</span> <span class="pre">(#15667)</span></code></p></li>
 </ul>
@@ -816,51 +822,51 @@ Airflow to at least version 2.1.0. Otherwise your Airflow package version will b
 automatically and you will have to manually run <code class="docutils literal notranslate"><span class="pre">airflow</span> <span class="pre">upgrade</span> <span class="pre">db</span></code> to complete the migration.</p>
 </div>
 </div>
-<div class="section" id="id23">
-<h4>Features<a class="headerlink" href="#id23" title="Permalink to this headline">ΒΆ</a></h4>
+<div class="section" id="id26">
+<h4>Features<a class="headerlink" href="#id26" title="Permalink to this heading">ΒΆ</a></h4>
 <ul class="simple">
 <li><p><code class="docutils literal notranslate"><span class="pre">Depreciate</span> <span class="pre">private_key_pass</span> <span class="pre">in</span> <span class="pre">SFTPHook</span> <span class="pre">conn</span> <span class="pre">extra</span> <span class="pre">and</span> <span class="pre">rename</span> <span class="pre">to</span> <span class="pre">private_key_passphrase</span> <span class="pre">(#14028)</span></code></p></li>
 </ul>
 </div>
 </div>
-<div class="section" id="id24">
-<h3>1.2.0<a class="headerlink" href="#id24" title="Permalink to this headline">ΒΆ</a></h3>
-<div class="section" id="id25">
-<h4>Features<a class="headerlink" href="#id25" title="Permalink to this headline">ΒΆ</a></h4>
+<div class="section" id="id27">
+<h3>1.2.0<a class="headerlink" href="#id27" title="Permalink to this heading">ΒΆ</a></h3>
+<div class="section" id="id28">
+<h4>Features<a class="headerlink" href="#id28" title="Permalink to this heading">ΒΆ</a></h4>
 <ul class="simple">
 <li><p><code class="docutils literal notranslate"><span class="pre">Undeprecate</span> <span class="pre">private_key</span> <span class="pre">option</span> <span class="pre">in</span> <span class="pre">SFTPHook</span> <span class="pre">(#15348)</span></code></p></li>
 <li><p><code class="docutils literal notranslate"><span class="pre">Add</span> <span class="pre">logs</span> <span class="pre">to</span> <span class="pre">show</span> <span class="pre">last</span> <span class="pre">modified</span> <span class="pre">in</span> <span class="pre">SFTP,</span> <span class="pre">FTP</span> <span class="pre">and</span> <span class="pre">Filesystem</span> <span class="pre">sensor</span> <span class="pre">(#15134)</span></code></p></li>
 </ul>
 </div>
 </div>
-<div class="section" id="id26">
-<h3>1.1.1<a class="headerlink" href="#id26" title="Permalink to this headline">ΒΆ</a></h3>
-<div class="section" id="id27">
-<h4>Features<a class="headerlink" href="#id27" title="Permalink to this headline">ΒΆ</a></h4>
+<div class="section" id="id29">
+<h3>1.1.1<a class="headerlink" href="#id29" title="Permalink to this heading">ΒΆ</a></h3>
+<div class="section" id="id30">
+<h4>Features<a class="headerlink" href="#id30" title="Permalink to this heading">ΒΆ</a></h4>
 <ul class="simple">
 <li><p><code class="docutils literal notranslate"><span class="pre">SFTPHook</span> <span class="pre">private_key_pass</span> <span class="pre">extra</span> <span class="pre">param</span> <span class="pre">is</span> <span class="pre">deprecated</span> <span class="pre">and</span> <span class="pre">renamed</span> <span class="pre">to</span> <span class="pre">private_key_passphrase,</span> <span class="pre">for</span> <span class="pre">consistency</span> <span class="pre">with</span>
 <span class="pre">arguments'</span> <span class="pre">naming</span> <span class="pre">in</span> <span class="pre">SSHHook</span></code></p></li>
 </ul>
 </div>
-<div class="section" id="id28">
-<h4>Bug fixes<a class="headerlink" href="#id28" title="Permalink to this headline">ΒΆ</a></h4>
+<div class="section" id="id31">
+<h4>Bug fixes<a class="headerlink" href="#id31" title="Permalink to this heading">ΒΆ</a></h4>
 <ul class="simple">
 <li><p><code class="docutils literal notranslate"><span class="pre">Corrections</span> <span class="pre">in</span> <span class="pre">docs</span> <span class="pre">and</span> <span class="pre">tools</span> <span class="pre">after</span> <span class="pre">releasing</span> <span class="pre">provider</span> <span class="pre">RCs</span> <span class="pre">(#14082)</span></code></p></li>
 </ul>
 </div>
 </div>
-<div class="section" id="id29">
-<h3>1.1.0<a class="headerlink" href="#id29" title="Permalink to this headline">ΒΆ</a></h3>
+<div class="section" id="id32">
+<h3>1.1.0<a class="headerlink" href="#id32" title="Permalink to this heading">ΒΆ</a></h3>
 <p>Updated documentation and readme files.</p>
-<div class="section" id="id30">
-<h4>Features<a class="headerlink" href="#id30" title="Permalink to this headline">ΒΆ</a></h4>
+<div class="section" id="id33">
+<h4>Features<a class="headerlink" href="#id33" title="Permalink to this heading">ΒΆ</a></h4>
 <ul class="simple">
 <li><p><code class="docutils literal notranslate"><span class="pre">Add</span> <span class="pre">retryer</span> <span class="pre">to</span> <span class="pre">SFTP</span> <span class="pre">hook</span> <span class="pre">connection</span> <span class="pre">(#13065)</span></code></p></li>
 </ul>
 </div>
 </div>
-<div class="section" id="id31">
-<h3>1.0.0<a class="headerlink" href="#id31" title="Permalink to this headline">ΒΆ</a></h3>
+<div class="section" id="id34">
+<h3>1.0.0<a class="headerlink" href="#id34" title="Permalink to this heading">ΒΆ</a></h3>
 <p>Initial version of the provider.</p>
 </div>
 </div>
@@ -949,71 +955,76 @@ automatically and you will have to manually run <code class="docutils literal no
 <li><a class="reference internal" href="#cross-provider-package-dependencies">Cross provider package dependencies</a></li>
 <li><a class="reference internal" href="#downloading-official-packages">Downloading official packages</a></li>
 <li><a class="reference internal" href="#changelog">Changelog</a><ul>
-<li><a class="reference internal" href="#id1">3.0.0</a><ul>
+<li><a class="reference internal" href="#id1">4.0.0</a><ul>
 <li><a class="reference internal" href="#breaking-changes">Breaking changes</a></li>
 <li><a class="reference internal" href="#features">Features</a></li>
 </ul>
 </li>
-<li><a class="reference internal" href="#id2">2.6.0</a><ul>
-<li><a class="reference internal" href="#id3">Features</a></li>
+<li><a class="reference internal" href="#id2">3.0.0</a><ul>
+<li><a class="reference internal" href="#id3">Breaking changes</a></li>
+<li><a class="reference internal" href="#id4">Features</a></li>
 </ul>
 </li>
-<li><a class="reference internal" href="#id4">2.5.2</a><ul>
-<li><a class="reference internal" href="#bug-fixes">Bug Fixes</a></li>
+<li><a class="reference internal" href="#id5">2.6.0</a><ul>
+<li><a class="reference internal" href="#id6">Features</a></li>
 </ul>
 </li>
-<li><a class="reference internal" href="#id5">2.5.1</a><ul>
-<li><a class="reference internal" href="#misc">Misc</a></li>
+<li><a class="reference internal" href="#id7">2.5.2</a><ul>
+<li><a class="reference internal" href="#bug-fixes">Bug Fixes</a></li>
 </ul>
 </li>
-<li><a class="reference internal" href="#id6">2.5.0</a><ul>
-<li><a class="reference internal" href="#id7">Features</a></li>
-<li><a class="reference internal" href="#id8">Misc</a></li>
+<li><a class="reference internal" href="#id8">2.5.1</a><ul>
+<li><a class="reference internal" href="#misc">Misc</a></li>
 </ul>
 </li>
-<li><a class="reference internal" href="#id9">2.4.1</a><ul>
-<li><a class="reference internal" href="#id10">Bug Fixes</a></li>
+<li><a class="reference internal" href="#id9">2.5.0</a><ul>
+<li><a class="reference internal" href="#id10">Features</a></li>
+<li><a class="reference internal" href="#id11">Misc</a></li>
 </ul>
 </li>
-<li><a class="reference internal" href="#id11">2.4.0</a><ul>
-<li><a class="reference internal" href="#id12">Features</a></li>
+<li><a class="reference internal" href="#id12">2.4.1</a><ul>
+<li><a class="reference internal" href="#id13">Bug Fixes</a></li>
 </ul>
 </li>
-<li><a class="reference internal" href="#id13">2.3.0</a><ul>
-<li><a class="reference internal" href="#id14">Features</a></li>
+<li><a class="reference internal" href="#id14">2.4.0</a><ul>
+<li><a class="reference internal" href="#id15">Features</a></li>
 </ul>
 </li>
-<li><a class="reference internal" href="#id15">2.2.0</a><ul>
-<li><a class="reference internal" href="#id16">Features</a></li>
+<li><a class="reference internal" href="#id16">2.3.0</a><ul>
+<li><a class="reference internal" href="#id17">Features</a></li>
 </ul>
 </li>
-<li><a class="reference internal" href="#id17">2.1.1</a><ul>
-<li><a class="reference internal" href="#id18">Misc</a></li>
+<li><a class="reference internal" href="#id18">2.2.0</a><ul>
+<li><a class="reference internal" href="#id19">Features</a></li>
 </ul>
 </li>
-<li><a class="reference internal" href="#id19">2.1.0</a><ul>
-<li><a class="reference internal" href="#id20">Features</a></li>
+<li><a class="reference internal" href="#id20">2.1.1</a><ul>
+<li><a class="reference internal" href="#id21">Misc</a></li>
 </ul>
 </li>
-<li><a class="reference internal" href="#id21">2.0.0</a><ul>
-<li><a class="reference internal" href="#id22">Breaking changes</a></li>
+<li><a class="reference internal" href="#id22">2.1.0</a><ul>
 <li><a class="reference internal" href="#id23">Features</a></li>
 </ul>
 </li>
-<li><a class="reference internal" href="#id24">1.2.0</a><ul>
-<li><a class="reference internal" href="#id25">Features</a></li>
+<li><a class="reference internal" href="#id24">2.0.0</a><ul>
+<li><a class="reference internal" href="#id25">Breaking changes</a></li>
+<li><a class="reference internal" href="#id26">Features</a></li>
 </ul>
 </li>
-<li><a class="reference internal" href="#id26">1.1.1</a><ul>
-<li><a class="reference internal" href="#id27">Features</a></li>
-<li><a class="reference internal" href="#id28">Bug fixes</a></li>
+<li><a class="reference internal" href="#id27">1.2.0</a><ul>
+<li><a class="reference internal" href="#id28">Features</a></li>
 </ul>
 </li>
-<li><a class="reference internal" href="#id29">1.1.0</a><ul>
+<li><a class="reference internal" href="#id29">1.1.1</a><ul>
 <li><a class="reference internal" href="#id30">Features</a></li>
+<li><a class="reference internal" href="#id31">Bug fixes</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#id32">1.1.0</a><ul>
+<li><a class="reference internal" href="#id33">Features</a></li>
 </ul>
 </li>
-<li><a class="reference internal" href="#id31">1.0.0</a></li>
+<li><a class="reference internal" href="#id34">1.0.0</a></li>
 </ul>
 </li>
 </ul>
@@ -1182,6 +1193,7 @@ automatically and you will have to manually run <code class="docutils literal no
         <script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
         <script src="_static/jquery.js"></script>
         <script src="_static/underscore.js"></script>
+        <script src="_static/_sphinx_javascript_frameworks_compat.js"></script>
         <script src="_static/doctools.js"></script>
         <script src="_static/clipboard.min.js"></script>
         <script src="_static/copybutton.js"></script>
diff --git a/docs/apache-airflow-providers-sftp/stable/installing-providers-from-sources.html b/docs/apache-airflow-providers-sftp/4.0.0/installing-providers-from-sources.html
similarity index 98%
copy from docs/apache-airflow-providers-sftp/stable/installing-providers-from-sources.html
copy to docs/apache-airflow-providers-sftp/4.0.0/installing-providers-from-sources.html
index 0552c28def..93e826d9f9 100644
--- a/docs/apache-airflow-providers-sftp/stable/installing-providers-from-sources.html
+++ b/docs/apache-airflow-providers-sftp/4.0.0/installing-providers-from-sources.html
@@ -5,7 +5,7 @@
 <!DOCTYPE html>
 <!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
 <!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
-    <html xmlns="http://www.w3.org/1999/xhtml">
+    <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
 <head>
         <meta charset="utf-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1">
@@ -284,7 +284,7 @@
 <div id="docs-version-selector" class="docs-version-selector sidebar__version-selector">
     <a class="dropdown-toggle" href="#" id="versionDropdown" role="button" data-toggle="dropdown" aria-haspopup="true"
        aria-expanded="false">
-        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">3.0.0</span>
+        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">4.0.0</span>
     </a>
     <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
 
@@ -421,7 +421,7 @@
 <div id="docs-version-selector" class="docs-version-selector sidebar__version-selector">
     <a class="dropdown-toggle" href="#" id="versionDropdown" role="button" data-toggle="dropdown" aria-haspopup="true"
        aria-expanded="false">
-        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">3.0.0</span>
+        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">4.0.0</span>
     </a>
     <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
 
@@ -581,29 +581,29 @@
 <blockquote>
 <div></div></blockquote>
 <div class="section" id="installing-from-sources">
-<h1>Installing from sources<a class="headerlink" href="#installing-from-sources" title="Permalink to this headline">ΒΆ</a></h1>
+<h1>Installing from sources<a class="headerlink" href="#installing-from-sources" title="Permalink to this heading">ΒΆ</a></h1>
 <div class="section" id="released-packages">
-<h2>Released packages<a class="headerlink" href="#released-packages" title="Permalink to this headline">ΒΆ</a></h2>
+<h2>Released packages<a class="headerlink" href="#released-packages" title="Permalink to this heading">ΒΆ</a></h2>
 <p>This page describes downloading and verifying <code class="docutils literal notranslate"><span class="pre">apache-airflow-providers-sftp</span></code> provider version
-<code class="docutils literal notranslate"><span class="pre">3.0.0</span></code> using officially released packages.
+<code class="docutils literal notranslate"><span class="pre">4.0.0</span></code> using officially released packages.
 You can also install the provider package - as most Python packages - via
-<a class="reference external" href="https://pypi.org/project/apache-airflow-providers-sftp/3.0.0">PyPI</a> .
+<a class="reference external" href="https://pypi.org/project/apache-airflow-providers-sftp/4.0.0">PyPI</a> .
 You can choose different version of the provider by selecting different version from the drop-down at
 the top-left of the page.</p>
-<p>The <code class="docutils literal notranslate"><span class="pre">sdist</span></code> and <code class="docutils literal notranslate"><span class="pre">whl</span></code> packages released are the &quot;official&quot; sources of installation that you can use if
+<p>The <code class="docutils literal notranslate"><span class="pre">sdist</span></code> and <code class="docutils literal notranslate"><span class="pre">whl</span></code> packages released are the β€œofficial” sources of installation that you can use if
 you want to verify the origin of the packages and want to verify checksums and signatures of the packages.
 The packages are available via the
 <a class="reference external" href="http://ws.apache.org/mirrors.cgi">Official Apache Software Foundations Downloads</a></p>
 <p>The downloads are available at:</p>
 <ul class="simple">
-<li><p><a class="reference external" href="https://www.apache.org/dyn/closer.lua/airflow/providers/apache-airflow-providers-sftp-3.0.0.tar.gz">Sdist package</a> (<a class="reference external" href="https://downloads.apache.org/airflow/providers/apache-airflow-providers-sftp-3.0.0.tar.gz.asc">asc</a>, <a class="reference external" href="https://downloads.apache.org/airflow/providers/apache-airflow-providers-sftp-3.0.0.tar.gz.sha512">sha512</a>) - those are also official sources for the pa [...]
-<li><p><a class="reference external" href="https://www.apache.org/dyn/closer.lua/airflow/providers/apache_airflow_providers_sftp-3.0.0-py3-none-any.whl">Whl package</a> (<a class="reference external" href="https://downloads.apache.org/airflow/providers/apache_airflow_providers_sftp-3.0.0-py3-none-any.whl.asc">asc</a>, <a class="reference external" href="https://downloads.apache.org/airflow/providers/apache_airflow_providers_sftp-3.0.0-py3-none-any.whl.sha512">sha512</a>)</p></li>
+<li><p><a class="reference external" href="https://www.apache.org/dyn/closer.lua/airflow/providers/apache-airflow-providers-sftp-4.0.0.tar.gz">Sdist package</a> (<a class="reference external" href="https://downloads.apache.org/airflow/providers/apache-airflow-providers-sftp-4.0.0.tar.gz.asc">asc</a>, <a class="reference external" href="https://downloads.apache.org/airflow/providers/apache-airflow-providers-sftp-4.0.0.tar.gz.sha512">sha512</a>) - those are also official sources for the pa [...]
+<li><p><a class="reference external" href="https://www.apache.org/dyn/closer.lua/airflow/providers/apache_airflow_providers_sftp-4.0.0-py3-none-any.whl">Whl package</a> (<a class="reference external" href="https://downloads.apache.org/airflow/providers/apache_airflow_providers_sftp-4.0.0-py3-none-any.whl.asc">asc</a>, <a class="reference external" href="https://downloads.apache.org/airflow/providers/apache_airflow_providers_sftp-4.0.0-py3-none-any.whl.sha512">sha512</a>)</p></li>
 </ul>
 <p>If you want to install from the source code, you can download from the sources link above, it will contain
 a <code class="docutils literal notranslate"><span class="pre">INSTALL</span></code> file containing details on how you can build and install the provider.</p>
 </div>
 <div class="section" id="release-integrity">
-<h2>Release integrity<a class="headerlink" href="#release-integrity" title="Permalink to this headline">ΒΆ</a></h2>
+<h2>Release integrity<a class="headerlink" href="#release-integrity" title="Permalink to this heading">ΒΆ</a></h2>
 <p><a class="reference external" href="https://downloads.apache.org/airflow/KEYS">PGP signatures KEYS</a></p>
 <p>It is essential that you verify the integrity of the downloaded files using the PGP or SHA signatures.
 The PGP signatures can be verified using GPG or PGP. Please download the KEYS as well as the asc
@@ -634,7 +634,7 @@ distribution directory and follow the below guide.</p>
 </pre></div>
 </div>
 <p>Example:</p>
-<div class="highlight-console notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>gpg --verify apache-airflow-providers-sftp-3.0.0.tar.gz.asc apache-airflow-providers-sftp-3.0.0.tar.gz
+<div class="highlight-console notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>gpg --verify apache-airflow-providers-sftp-4.0.0.tar.gz.asc apache-airflow-providers-sftp-4.0.0.tar.gz
 <span class="go">  gpg: Signature made Sat 11 Sep 12:49:54 2021 BST</span>
 <span class="go">  gpg:                using RSA key CDE15C6E4D3A8EC4ECF4BA4B6674E08AD7DE406F</span>
 <span class="go">  gpg:                issuer &quot;kaxilnaik@apache.org&quot;</span>
@@ -645,9 +645,9 @@ distribution directory and follow the below guide.</p>
 <span class="go">  Primary key fingerprint: CDE1 5C6E 4D3A 8EC4 ECF4  BA4B 6674 E08A D7DE 406F</span>
 </pre></div>
 </div>
-<p>The &quot;Good signature from ...&quot; is indication that the signatures are correct.
-Do not worry about the &quot;not certified with a trusted signature&quot; warning. Most of the certificates used
-by release managers are self signed, that's why you get this warning. By importing the server in the
+<p>The β€œGood signature from …” is indication that the signatures are correct.
+Do not worry about the β€œnot certified with a trusted signature” warning. Most of the certificates used
+by release managers are self signed, that’s why you get this warning. By importing the server in the
 previous step and importing it via ID from <code class="docutils literal notranslate"><span class="pre">KEYS</span></code> page, you know that this is a valid Key already.</p>
 <p>For SHA512 sum check, download the relevant <code class="docutils literal notranslate"><span class="pre">sha512</span></code> and run the following:</p>
 <div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>shasum -a <span class="m">512</span> apache-airflow-providers-********  <span class="p">|</span> diff - apache-airflow-providers-********.sha512
@@ -655,23 +655,23 @@ previous step and importing it via ID from <code class="docutils literal notrans
 </div>
 <p>The <code class="docutils literal notranslate"><span class="pre">SHASUM</span></code> of the file should match the one provided in <code class="docutils literal notranslate"><span class="pre">.sha512</span></code> file.</p>
 <p>Example:</p>
-<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>shasum -a <span class="m">512</span> apache-airflow-providers-sftp-3.0.0.tar.gz  <span class="p">|</span> diff - apache-airflow-providers-sftp-3.0.0.tar.gz.sha512
+<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>shasum -a <span class="m">512</span> apache-airflow-providers-sftp-4.0.0.tar.gz  <span class="p">|</span> diff - apache-airflow-providers-sftp-4.0.0.tar.gz.sha512
 </pre></div>
 </div>
 </div>
 <div class="section" id="verifying-pypi-releases">
-<h2>Verifying PyPI releases<a class="headerlink" href="#verifying-pypi-releases" title="Permalink to this headline">ΒΆ</a></h2>
+<h2>Verifying PyPI releases<a class="headerlink" href="#verifying-pypi-releases" title="Permalink to this heading">ΒΆ</a></h2>
 <p>You can verify the Provider <code class="docutils literal notranslate"><span class="pre">.whl</span></code> packages from PyPI by locally downloading the package and signature
 and SHA sum files with the script below:</p>
 <div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="ch">#!/bin/bash</span>
-<span class="nv">PACKAGE_VERSION</span><span class="o">=</span><span class="m">3</span>.0.0
+<span class="nv">PACKAGE_VERSION</span><span class="o">=</span><span class="m">4</span>.0.0
 <span class="nv">PACKAGE_NAME</span><span class="o">=</span>apache-airflow-providers-sftp
 <span class="nv">provider_download_dir</span><span class="o">=</span><span class="k">$(</span>mktemp -d<span class="k">)</span>
 pip download --no-deps <span class="s2">&quot;</span><span class="si">${</span><span class="nv">PACKAGE_NAME</span><span class="si">}</span><span class="s2">==</span><span class="si">${</span><span class="nv">PACKAGE_VERSION</span><span class="si">}</span><span class="s2">&quot;</span> --dest <span class="s2">&quot;</span><span class="si">${</span><span class="nv">provider_download_dir</span><span class="si">}</span><span class="s2">&quot;</span>
-curl <span class="s2">&quot;https://downloads.apache.org/airflow/providers/apache_airflow_providers_sftp-3.0.0-py3-none-any.whl.asc&quot;</span> <span class="se">\</span>
-    -L -o <span class="s2">&quot;</span><span class="si">${</span><span class="nv">provider_download_dir</span><span class="si">}</span><span class="s2">/apache_airflow_providers_sftp-3.0.0-py3-none-any.whl.asc&quot;</span>
-curl <span class="s2">&quot;https://downloads.apache.org/airflow/providers/apache_airflow_providers_sftp-3.0.0-py3-none-any.whl.sha512&quot;</span> <span class="se">\</span>
-    -L -o <span class="s2">&quot;</span><span class="si">${</span><span class="nv">provider_download_dir</span><span class="si">}</span><span class="s2">/apache_airflow_providers_sftp-3.0.0-py3-none-any.whl.sha512&quot;</span>
+curl <span class="s2">&quot;https://downloads.apache.org/airflow/providers/apache_airflow_providers_sftp-4.0.0-py3-none-any.whl.asc&quot;</span> <span class="se">\</span>
+    -L -o <span class="s2">&quot;</span><span class="si">${</span><span class="nv">provider_download_dir</span><span class="si">}</span><span class="s2">/apache_airflow_providers_sftp-4.0.0-py3-none-any.whl.asc&quot;</span>
+curl <span class="s2">&quot;https://downloads.apache.org/airflow/providers/apache_airflow_providers_sftp-4.0.0-py3-none-any.whl.sha512&quot;</span> <span class="se">\</span>
+    -L -o <span class="s2">&quot;</span><span class="si">${</span><span class="nv">provider_download_dir</span><span class="si">}</span><span class="s2">/apache_airflow_providers_sftp-4.0.0-py3-none-any.whl.sha512&quot;</span>
 <span class="nb">echo</span>
 <span class="nb">echo</span> <span class="s2">&quot;Please verify files downloaded to </span><span class="si">${</span><span class="nv">provider_download_dir</span><span class="si">}</span><span class="s2">&quot;</span>
 ls -la <span class="s2">&quot;</span><span class="si">${</span><span class="nv">provider_download_dir</span><span class="si">}</span><span class="s2">&quot;</span>
@@ -928,6 +928,7 @@ folder created.</p>
         <script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
         <script src="_static/jquery.js"></script>
         <script src="_static/underscore.js"></script>
+        <script src="_static/_sphinx_javascript_frameworks_compat.js"></script>
         <script src="_static/doctools.js"></script>
         <script src="_static/clipboard.min.js"></script>
         <script src="_static/copybutton.js"></script>
diff --git a/docs/apache-airflow-providers-sftp/4.0.0/objects.inv b/docs/apache-airflow-providers-sftp/4.0.0/objects.inv
new file mode 100644
index 0000000000..874ad7e944
Binary files /dev/null and b/docs/apache-airflow-providers-sftp/4.0.0/objects.inv differ
diff --git a/docs/apache-airflow-providers-sftp/stable/py-modindex.html b/docs/apache-airflow-providers-sftp/4.0.0/py-modindex.html
similarity index 99%
copy from docs/apache-airflow-providers-sftp/stable/py-modindex.html
copy to docs/apache-airflow-providers-sftp/4.0.0/py-modindex.html
index 90c156eb8f..05811b5a42 100644
--- a/docs/apache-airflow-providers-sftp/stable/py-modindex.html
+++ b/docs/apache-airflow-providers-sftp/4.0.0/py-modindex.html
@@ -5,7 +5,7 @@
 <!DOCTYPE html>
 <!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
 <!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
-    <html xmlns="http://www.w3.org/1999/xhtml">
+    <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
 <head>
         <meta charset="utf-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1">
@@ -285,7 +285,7 @@
 <div id="docs-version-selector" class="docs-version-selector sidebar__version-selector">
     <a class="dropdown-toggle" href="#" id="versionDropdown" role="button" data-toggle="dropdown" aria-haspopup="true"
        aria-expanded="false">
-        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">3.0.0</span>
+        <span class="bodytext__medium--greyish-brown">Version: </span><span class="version">4.0.0</span>
     </a>
     <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
... 13525 lines suppressed ...