apache-airflow-providers-sftp 5.3.0rc1__tar.gz → 5.3.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/PKG-INFO +8 -8
  2. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/README.rst +3 -3
  3. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/docs/changelog.rst +11 -0
  4. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/docs/index.rst +3 -3
  5. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/provider.yaml +2 -1
  6. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/pyproject.toml +5 -5
  7. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/src/airflow/providers/sftp/__init__.py +1 -1
  8. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/src/airflow/providers/sftp/sensors/sftp.py +14 -14
  9. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/tests/unit/sftp/sensors/test_sftp.py +15 -2
  10. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/docs/.latest-doc-only-change.txt +0 -0
  11. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/docs/commits.rst +0 -0
  12. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/docs/conf.py +0 -0
  13. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/docs/connections/sftp.rst +0 -0
  14. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/docs/installing-providers-from-sources.rst +0 -0
  15. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/docs/integration-logos/SFTP.png +0 -0
  16. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/docs/security.rst +0 -0
  17. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/docs/sensors/sftp_sensor.rst +0 -0
  18. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/src/airflow/__init__.py +0 -0
  19. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/src/airflow/providers/__init__.py +0 -0
  20. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/src/airflow/providers/sftp/LICENSE +0 -0
  21. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/src/airflow/providers/sftp/decorators/__init__.py +0 -0
  22. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/src/airflow/providers/sftp/decorators/sensors/__init__.py +0 -0
  23. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/src/airflow/providers/sftp/decorators/sensors/sftp.py +0 -0
  24. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/src/airflow/providers/sftp/get_provider_info.py +0 -0
  25. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/src/airflow/providers/sftp/hooks/__init__.py +0 -0
  26. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/src/airflow/providers/sftp/hooks/sftp.py +0 -0
  27. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/src/airflow/providers/sftp/operators/__init__.py +0 -0
  28. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/src/airflow/providers/sftp/operators/sftp.py +0 -0
  29. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/src/airflow/providers/sftp/sensors/__init__.py +0 -0
  30. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/src/airflow/providers/sftp/triggers/__init__.py +0 -0
  31. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/src/airflow/providers/sftp/triggers/sftp.py +0 -0
  32. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/src/airflow/providers/sftp/version_compat.py +0 -0
  33. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/tests/conftest.py +0 -0
  34. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/tests/system/__init__.py +0 -0
  35. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/tests/system/sftp/__init__.py +0 -0
  36. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/tests/system/sftp/example_sftp_sensor.py +0 -0
  37. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/tests/unit/__init__.py +0 -0
  38. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/tests/unit/sftp/__init__.py +0 -0
  39. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/tests/unit/sftp/decorators/__init__.py +0 -0
  40. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/tests/unit/sftp/decorators/sensors/__init__.py +0 -0
  41. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/tests/unit/sftp/decorators/sensors/test_sftp.py +0 -0
  42. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/tests/unit/sftp/hooks/__init__.py +0 -0
  43. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/tests/unit/sftp/hooks/test_sftp.py +0 -0
  44. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/tests/unit/sftp/operators/__init__.py +0 -0
  45. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/tests/unit/sftp/operators/test_sftp.py +0 -0
  46. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/tests/unit/sftp/sensors/__init__.py +0 -0
  47. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/tests/unit/sftp/triggers/__init__.py +0 -0
  48. {apache_airflow_providers_sftp-5.3.0rc1 → apache_airflow_providers_sftp-5.3.1}/tests/unit/sftp/triggers/test_sftp.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: apache-airflow-providers-sftp
3
- Version: 5.3.0rc1
3
+ Version: 5.3.1
4
4
  Summary: Provider package apache-airflow-providers-sftp for Apache Airflow
5
5
  Keywords: airflow-provider,sftp,airflow,integration
6
6
  Author-email: Apache Software Foundation <dev@airflow.apache.org>
@@ -20,15 +20,15 @@ Classifier: Programming Language :: Python :: 3.10
20
20
  Classifier: Programming Language :: Python :: 3.11
21
21
  Classifier: Programming Language :: Python :: 3.12
22
22
  Classifier: Topic :: System :: Monitoring
23
- Requires-Dist: apache-airflow>=2.10.0rc1
24
- Requires-Dist: apache-airflow-providers-ssh>=2.1.0rc1
23
+ Requires-Dist: apache-airflow>=2.10.0
24
+ Requires-Dist: apache-airflow-providers-ssh>=2.1.0
25
25
  Requires-Dist: paramiko>=2.9.0
26
26
  Requires-Dist: asyncssh>=2.12.0
27
27
  Requires-Dist: apache-airflow-providers-common-compat ; extra == "common-compat"
28
28
  Requires-Dist: apache-airflow-providers-openlineage ; extra == "openlineage"
29
29
  Project-URL: Bug Tracker, https://github.com/apache/airflow/issues
30
- Project-URL: Changelog, https://airflow.staged.apache.org/docs/apache-airflow-providers-sftp/5.3.0/changelog.html
31
- Project-URL: Documentation, https://airflow.staged.apache.org/docs/apache-airflow-providers-sftp/5.3.0
30
+ Project-URL: Changelog, https://airflow.apache.org/docs/apache-airflow-providers-sftp/5.3.1/changelog.html
31
+ Project-URL: Documentation, https://airflow.apache.org/docs/apache-airflow-providers-sftp/5.3.1
32
32
  Project-URL: Mastodon, https://fosstodon.org/@airflow
33
33
  Project-URL: Slack Chat, https://s.apache.org/airflow-slack
34
34
  Project-URL: Source Code, https://github.com/apache/airflow
@@ -61,7 +61,7 @@ Provides-Extra: openlineage
61
61
 
62
62
  Package ``apache-airflow-providers-sftp``
63
63
 
64
- Release: ``5.3.0``
64
+ Release: ``5.3.1``
65
65
 
66
66
 
67
67
  `SSH File Transfer Protocol (SFTP) <https://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/>`__
@@ -74,7 +74,7 @@ This is a provider package for ``sftp`` provider. All classes for this provider
74
74
  are in ``airflow.providers.sftp`` python package.
75
75
 
76
76
  You can find package information and changelog for the provider
77
- in the `documentation <https://airflow.apache.org/docs/apache-airflow-providers-sftp/5.3.0/>`_.
77
+ in the `documentation <https://airflow.apache.org/docs/apache-airflow-providers-sftp/5.3.1/>`_.
78
78
 
79
79
  Installation
80
80
  ------------
@@ -119,5 +119,5 @@ Dependent package
119
119
  ================================================================================================================== =================
120
120
 
121
121
  The changelog for the provider package can be found in the
122
- `changelog <https://airflow.apache.org/docs/apache-airflow-providers-sftp/5.3.0/changelog.html>`_.
122
+ `changelog <https://airflow.apache.org/docs/apache-airflow-providers-sftp/5.3.1/changelog.html>`_.
123
123
 
@@ -23,7 +23,7 @@
23
23
 
24
24
  Package ``apache-airflow-providers-sftp``
25
25
 
26
- Release: ``5.3.0``
26
+ Release: ``5.3.1``
27
27
 
28
28
 
29
29
  `SSH File Transfer Protocol (SFTP) <https://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/>`__
@@ -36,7 +36,7 @@ This is a provider package for ``sftp`` provider. All classes for this provider
36
36
  are in ``airflow.providers.sftp`` python package.
37
37
 
38
38
  You can find package information and changelog for the provider
39
- in the `documentation <https://airflow.apache.org/docs/apache-airflow-providers-sftp/5.3.0/>`_.
39
+ in the `documentation <https://airflow.apache.org/docs/apache-airflow-providers-sftp/5.3.1/>`_.
40
40
 
41
41
  Installation
42
42
  ------------
@@ -81,4 +81,4 @@ Dependent package
81
81
  ================================================================================================================== =================
82
82
 
83
83
  The changelog for the provider package can be found in the
84
- `changelog <https://airflow.apache.org/docs/apache-airflow-providers-sftp/5.3.0/changelog.html>`_.
84
+ `changelog <https://airflow.apache.org/docs/apache-airflow-providers-sftp/5.3.1/changelog.html>`_.
@@ -27,6 +27,17 @@
27
27
  Changelog
28
28
  ---------
29
29
 
30
+ 5.3.1
31
+ .....
32
+
33
+ Bug Fixes
34
+ ~~~~~~~~~
35
+
36
+ * ``Updating SFTPSensor to properly handle scenario where file is missing (#51167)``
37
+
38
+ .. Below changes are excluded from the changelog. Move them to
39
+ appropriate section above if needed. Do not delete the lines(!):
40
+
30
41
  5.3.0
31
42
  .....
32
43
 
@@ -70,7 +70,7 @@ apache-airflow-providers-sftp package
70
70
  `SSH File Transfer Protocol (SFTP) <https://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/>`__
71
71
 
72
72
 
73
- Release: 5.3.0
73
+ Release: 5.3.1
74
74
 
75
75
  Provider package
76
76
  ----------------
@@ -126,5 +126,5 @@ Downloading official packages
126
126
  You can download officially released packages and verify their checksums and signatures from the
127
127
  `Official Apache Download site <https://downloads.apache.org/airflow/providers/>`_
128
128
 
129
- * `The apache-airflow-providers-sftp 5.3.0 sdist package <https://downloads.apache.org/airflow/providers/apache_airflow_providers_sftp-5.3.0.tar.gz>`_ (`asc <https://downloads.apache.org/airflow/providers/apache_airflow_providers_sftp-5.3.0.tar.gz.asc>`__, `sha512 <https://downloads.apache.org/airflow/providers/apache_airflow_providers_sftp-5.3.0.tar.gz.sha512>`__)
130
- * `The apache-airflow-providers-sftp 5.3.0 wheel package <https://downloads.apache.org/airflow/providers/apache_airflow_providers_sftp-5.3.0-py3-none-any.whl>`_ (`asc <https://downloads.apache.org/airflow/providers/apache_airflow_providers_sftp-5.3.0-py3-none-any.whl.asc>`__, `sha512 <https://downloads.apache.org/airflow/providers/apache_airflow_providers_sftp-5.3.0-py3-none-any.whl.sha512>`__)
129
+ * `The apache-airflow-providers-sftp 5.3.1 sdist package <https://downloads.apache.org/airflow/providers/apache_airflow_providers_sftp-5.3.1.tar.gz>`_ (`asc <https://downloads.apache.org/airflow/providers/apache_airflow_providers_sftp-5.3.1.tar.gz.asc>`__, `sha512 <https://downloads.apache.org/airflow/providers/apache_airflow_providers_sftp-5.3.1.tar.gz.sha512>`__)
130
+ * `The apache-airflow-providers-sftp 5.3.1 wheel package <https://downloads.apache.org/airflow/providers/apache_airflow_providers_sftp-5.3.1-py3-none-any.whl>`_ (`asc <https://downloads.apache.org/airflow/providers/apache_airflow_providers_sftp-5.3.1-py3-none-any.whl.asc>`__, `sha512 <https://downloads.apache.org/airflow/providers/apache_airflow_providers_sftp-5.3.1-py3-none-any.whl.sha512>`__)
@@ -22,12 +22,13 @@ description: |
22
22
  `SSH File Transfer Protocol (SFTP) <https://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/>`__
23
23
 
24
24
  state: ready
25
- source-date-epoch: 1747133724
25
+ source-date-epoch: 1749896917
26
26
  # Note that those versions are maintained by release manager - do not update them manually
27
27
  # with the exception of case where other provider in sources has >= new provider version.
28
28
  # In such case adding >= NEW_VERSION and bumping to NEW_VERSION in a provider have
29
29
  # to be done in the same PR
30
30
  versions:
31
+ - 5.3.1
31
32
  - 5.3.0
32
33
  - 5.2.1
33
34
  - 5.2.0
@@ -25,7 +25,7 @@ build-backend = "flit_core.buildapi"
25
25
 
26
26
  [project]
27
27
  name = "apache-airflow-providers-sftp"
28
- version = "5.3.0rc1"
28
+ version = "5.3.1"
29
29
  description = "Provider package apache-airflow-providers-sftp for Apache Airflow"
30
30
  readme = "README.rst"
31
31
  authors = [
@@ -57,8 +57,8 @@ requires-python = "~=3.9"
57
57
  # Make sure to run ``breeze static-checks --type update-providers-dependencies --all-files``
58
58
  # After you modify the dependencies, and rebuild your Breeze CI image with ``breeze ci-image build``
59
59
  dependencies = [
60
- "apache-airflow>=2.10.0rc1",
61
- "apache-airflow-providers-ssh>=2.1.0rc1",
60
+ "apache-airflow>=2.10.0",
61
+ "apache-airflow-providers-ssh>=2.1.0",
62
62
  "paramiko>=2.9.0",
63
63
  "asyncssh>=2.12.0",
64
64
  ]
@@ -110,8 +110,8 @@ apache-airflow-providers-common-sql = {workspace = true}
110
110
  apache-airflow-providers-standard = {workspace = true}
111
111
 
112
112
  [project.urls]
113
- "Documentation" = "https://airflow.staged.apache.org/docs/apache-airflow-providers-sftp/5.3.0"
114
- "Changelog" = "https://airflow.staged.apache.org/docs/apache-airflow-providers-sftp/5.3.0/changelog.html"
113
+ "Documentation" = "https://airflow.apache.org/docs/apache-airflow-providers-sftp/5.3.1"
114
+ "Changelog" = "https://airflow.apache.org/docs/apache-airflow-providers-sftp/5.3.1/changelog.html"
115
115
  "Bug Tracker" = "https://github.com/apache/airflow/issues"
116
116
  "Source Code" = "https://github.com/apache/airflow"
117
117
  "Slack Chat" = "https://s.apache.org/airflow-slack"
@@ -29,7 +29,7 @@ from airflow import __version__ as airflow_version
29
29
 
30
30
  __all__ = ["__version__"]
31
31
 
32
- __version__ = "5.3.0"
32
+ __version__ = "5.3.1"
33
33
 
34
34
  if packaging.version.parse(packaging.version.parse(airflow_version).base_version) < packaging.version.parse(
35
35
  "2.10.0"
@@ -89,25 +89,25 @@ class SFTPSensor(BaseSensorOperator):
89
89
  if self.file_pattern:
90
90
  files_from_pattern = self.hook.get_files_by_pattern(self.path, self.file_pattern)
91
91
  if files_from_pattern:
92
- actual_files_to_check = [
92
+ actual_files_present = [
93
93
  os.path.join(self.path, file_from_pattern) for file_from_pattern in files_from_pattern
94
94
  ]
95
95
  else:
96
96
  return False
97
97
  else:
98
98
  try:
99
- self.hook.isfile(self.path)
100
- actual_files_to_check = [self.path]
101
- except OSError as e:
102
- if e.errno != SFTP_NO_SUCH_FILE:
103
- raise AirflowException from e
104
- actual_files_to_check = []
99
+ # If a file is present, it is the single element added to the actual_files_present list to be
100
+ # processed. If the file is a directory, actual_file_present will be assigned an empty list,
101
+ # since SFTPHook.isfile(...) returns False
102
+ actual_files_present = [self.path] if self.hook.isfile(self.path) else []
103
+ except Exception as e:
104
+ raise AirflowException from e
105
105
 
106
106
  if self.newer_than:
107
- for actual_file_to_check in actual_files_to_check:
107
+ for actual_file_present in actual_files_present:
108
108
  try:
109
- mod_time = self.hook.get_mod_time(actual_file_to_check)
110
- self.log.info("Found File %s last modified: %s", actual_file_to_check, mod_time)
109
+ mod_time = self.hook.get_mod_time(actual_file_present)
110
+ self.log.info("Found File %s last modified: %s", actual_file_present, mod_time)
111
111
  except OSError as e:
112
112
  if e.errno != SFTP_NO_SUCH_FILE:
113
113
  raise AirflowException from e
@@ -118,22 +118,22 @@ class SFTPSensor(BaseSensorOperator):
118
118
  _mod_time = convert_to_utc(datetime.strptime(mod_time, "%Y%m%d%H%M%S"))
119
119
  _newer_than = convert_to_utc(self.newer_than)
120
120
  if _newer_than <= _mod_time:
121
- files_found.append(actual_file_to_check)
121
+ files_found.append(actual_file_present)
122
122
  self.log.info(
123
123
  "File %s has modification time: '%s', which is newer than: '%s'",
124
- actual_file_to_check,
124
+ actual_file_present,
125
125
  str(_mod_time),
126
126
  str(_newer_than),
127
127
  )
128
128
  else:
129
129
  self.log.info(
130
130
  "File %s has modification time: '%s', which is older than: '%s'",
131
- actual_file_to_check,
131
+ actual_file_present,
132
132
  str(_mod_time),
133
133
  str(_newer_than),
134
134
  )
135
135
  else:
136
- files_found = actual_files_to_check
136
+ files_found = actual_files_present
137
137
 
138
138
  if not len(files_found):
139
139
  return False
@@ -22,7 +22,7 @@ from unittest import mock
22
22
  from unittest.mock import Mock, patch
23
23
 
24
24
  import pytest
25
- from paramiko.sftp import SFTP_FAILURE, SFTP_NO_SUCH_FILE
25
+ from paramiko.sftp import SFTP_FAILURE
26
26
  from pendulum import datetime as pendulum_datetime, timezone
27
27
 
28
28
  from airflow.exceptions import AirflowException
@@ -44,9 +44,22 @@ class TestSFTPSensor:
44
44
  sftp_hook_mock.return_value.close_conn.assert_not_called()
45
45
  assert output
46
46
 
47
+ @patch("airflow.providers.sftp.sensors.sftp.SFTPHook")
48
+ def test_file_irregular(self, sftp_hook_mock):
49
+ # This mocks the behavior of SFTPHook.isfile when an OSError is raised in that method, resulting in
50
+ # False being returned
51
+ sftp_hook_mock.return_value.isfile.return_value = False
52
+ sftp_sensor = SFTPSensor(task_id="unit_test", path="/path/to/file/1970-01-01.txt")
53
+ context = {"ds": "1970-01-01"}
54
+ output = sftp_sensor.poke(context)
55
+ sftp_hook_mock.return_value.isfile.assert_called_once_with("/path/to/file/1970-01-01.txt")
56
+ sftp_hook_mock.return_value.close_conn.assert_not_called()
57
+ assert not output
58
+
47
59
  @patch("airflow.providers.sftp.sensors.sftp.SFTPHook")
48
60
  def test_file_absent(self, sftp_hook_mock):
49
- sftp_hook_mock.return_value.isfile.side_effect = OSError(SFTP_NO_SUCH_FILE, "File missing")
61
+ # This is the same implementation above, however, it's simulating instead the absence of a file
62
+ sftp_hook_mock.return_value.isfile.return_value = False
50
63
  sftp_sensor = SFTPSensor(task_id="unit_test", path="/path/to/file/1970-01-01.txt")
51
64
  context = {"ds": "1970-01-01"}
52
65
  output = sftp_sensor.poke(context)