Skip to content

Commit d701d1e

Browse files
authored
SNOW-1998295: Update docs for SnowflakeFile writes general availability (#3182)
1 parent 9701e34 commit d701d1e

File tree

4 files changed

+40
-34
lines changed

4 files changed

+40
-34
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@
1212
- Removed the need to `cache_result` in the internal implementation of the input dataframe resulting in a pure lazy dataframe operation.
1313
- The `seed` argument now behaves as expected with repeatable results across multiple calls and sessions.
1414
- `DataFrame.fillna` and `DataFrame.replace` now both support fitting `int` and `float` into `Decimal` columns if `include_decimal` is set to True.
15+
- Added documentation for the following UDF and stored procedure functions in `files.py` as a result of their General Availability.
16+
- `SnowflakeFile.write`
17+
- `SnowflakeFile.writelines`
18+
- `SnowflakeFile.writeable`
19+
- Minor documentation changes for `SnowflakeFile` and `SnowflakeFile.open()`
1520

1621
#### Bug Fixes
1722

docs/source/snowpark/files.rst

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,23 @@ Files
2727

2828
~SnowflakeFile.close
2929
~SnowflakeFile.fileno
30+
~SnowflakeFile.isatty
3031
~SnowflakeFile.open
32+
~SnowflakeFile.open_new_result
3133
~SnowflakeFile.read
3234
~SnowflakeFile.read1
33-
~SnowflakeFile.readline
3435
~SnowflakeFile.readable
3536
~SnowflakeFile.readall
3637
~SnowflakeFile.readinto
3738
~SnowflakeFile.readinto1
39+
~SnowflakeFile.readline
40+
~SnowflakeFile.readlines
3841
~SnowflakeFile.seek
3942
~SnowflakeFile.seekable
4043
~SnowflakeFile.tell
44+
~SnowflakeFile.write
45+
~SnowflakeFile.writable
46+
~SnowflakeFile.writelines
4147

4248

4349
.. rubric:: Attributes

src/snowflake/snowpark/files.py

Lines changed: 28 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
import sys
1616
from io import RawIOBase
1717

18-
from snowflake.snowpark._internal.utils import private_preview
19-
2018
# Python 3.8 needs to use typing.Iterable because collections.abc.Iterable is not subscriptable
2119
# Python 3.9 can use both
2220
# Python 3.10 needs to use collections.abc.Iterable because typing.Iterable is removed
@@ -34,7 +32,7 @@ class SnowflakeFile(RawIOBase):
3432
SnowflakeFile supports most operations supported by Python IOBase objects.
3533
A SnowflakeFile object can be used as a Python IOBase object.
3634
37-
The constructor of this class is not supposed to be called directly. Call :meth:`~snowflake.snowpark.file.SnowflakeFile.open` to create a SnowflakeFile object.
35+
The constructor of this class is not supposed to be called directly. Call :meth:`~snowflake.snowpark.file.SnowflakeFile.open` to create a read-only SnowflakeFile object, and call :meth:`~snowflake.snowpark.file.SnowflakeFile.open_new_result` to create a write-only SnowflakeFile object.
3836
3937
This class is intended for usage within UDFs and stored procedures and many methods do not work locally.
4038
"""
@@ -73,26 +71,39 @@ def open(
7371
require_scoped_url: bool = True,
7472
) -> SnowflakeFile:
7573
"""
76-
Returns a :class:`~snowflake.snowpark.file.SnowflakeFile`.
77-
In UDF and Stored Procedures, the object works like a Python IOBase object and as a wrapper for an IO stream of remote files. The IO Stream is to support the file operations defined in this class.
74+
Used to create a :class:`~snowflake.snowpark.file.SnowflakeFile` which can only be used for read-based IO operations on the file.
75+
76+
In UDFs and Stored Procedures, the object works like a read-only Python IOBase object and as a wrapper for an IO stream of remote files.
7877
7978
All files are accessed in the context of the UDF owner (with the exception of caller's rights stored procedures which use the caller's context).
8079
UDF callers should use scoped URLs to allow the UDF to access their files. By accepting only scoped URLs the UDF owner can ensure
81-
the UDF caller had access to the provided file. Removing the requirement that the URL is a scoped URL (require_scoped_url=false) allows the caller
80+
the UDF caller had access to the provided file. Removing the requirement that the URL is a scoped URL (require_scoped_url=False) allows the caller
8281
to provide URLs that may be only accessible by the UDF owner.
8382
8483
is_owner_file is marked for deprecation. For Snowflake release 7.8 and onwards please use require_scoped_url instead.
8584
8685
Args:
8786
file_location: scoped URL, file URL, or string path for files located in a stage
88-
mode: A string used to mark the type of an IO stream.
87+
mode: A string used to mark the type of an IO stream. Supported modes are "r" for text read and "rb" for binary read.
8988
is_owner_file: (Deprecated) A boolean value, if True, the API is intended to access owner's files and all URI/URL are allowed. If False, the API is intended to access files passed into the function by the caller and only scoped URL is allowed.
9089
require_scoped_url: A boolean value, if True, file_location must be a scoped URL. A scoped URL ensures that the caller cannot access the UDF owners files that the caller does not have access to.
9190
"""
9291
return cls(
9392
file_location, mode, is_owner_file, require_scoped_url=require_scoped_url
9493
)
9594

95+
@classmethod
96+
def open_new_result(cls, mode: str = "w") -> SnowflakeFile:
97+
"""
98+
Used to create a :class:`~snowflake.snowpark.file.SnowflakeFile` which can only be used for write-based IO operations. UDFs/Stored Procedures should return the file to materialize it, and it is then made accessible via a scoped URL returned in the query results.
99+
100+
In UDFs and Stored Procedures, the object works like a write-only Python IOBase object and as a wrapper for an IO stream of remote files.
101+
102+
Args:
103+
mode: A string used to mark the type of an IO stream. Supported modes are "w" for text write and "wb" for binary write.
104+
"""
105+
return cls("new results file", mode, require_scoped_url=0, from_result_api=True)
106+
96107
def close(self) -> None:
97108
"""
98109
In UDF and Stored Procedures, the close func closes the IO Stream included in the SnowflakeFile.
@@ -121,24 +132,10 @@ def flush(self) -> None:
121132

122133
def isatty(self) -> None:
123134
"""
124-
Returns false, file streams in stored procedures and UDFs are never interactive in Snowflake.
135+
Returns False, file streams in stored procedures and UDFs are never interactive in Snowflake.
125136
"""
126137
raise NotImplementedError(_DEFER_IMPLEMENTATION_ERR_MSG)
127138

128-
@classmethod
129-
@private_preview(version="1.22.1")
130-
def open_new_result(cls, mode: str = "w") -> SnowflakeFile:
131-
"""
132-
Returns a :class:`~snowflake.snowpark.file.SnowflakeFile`.
133-
In UDF and Stored Procedures, the object works like a Python IOBase object and as a wrapper for an IO stream of remote files. The IO Stream is to support the file operations defined in this class.
134-
135-
This stream will open a writable result file that will be materialized when it's returned by a UDF or Stored Procedure. When the file is materialized then file_uri will be set to a scoped URL that temporarily references this file.
136-
137-
Args:
138-
mode: A string used to mark the type of an IO stream.
139-
"""
140-
return cls("new results file", mode, require_scoped_url=0, from_result_api=True)
141-
142139
def read(self, size: int = -1) -> None:
143140
"""
144141
See https://docs.python.org/3/library/io.html#io.RawIOBase.read
@@ -151,12 +148,6 @@ def read1(self, size: int = -1) -> None:
151148
"""
152149
raise NotImplementedError(_DEFER_IMPLEMENTATION_ERR_MSG)
153150

154-
def readline(self, size: int = -1) -> None:
155-
"""
156-
See https://docs.python.org/3/library/io.html#io.IOBase.readline
157-
"""
158-
raise NotImplementedError(_DEFER_IMPLEMENTATION_ERR_MSG)
159-
160151
def readable(self) -> None:
161152
"""
162153
See https://docs.python.org/3/library/io.html#io.IOBase.readable
@@ -181,6 +172,12 @@ def readinto1(self, b: bytes | bytearray | array.array) -> None:
181172
"""
182173
raise NotImplementedError(_DEFER_IMPLEMENTATION_ERR_MSG)
183174

175+
def readline(self, size: int = -1) -> None:
176+
"""
177+
See https://docs.python.org/3/library/io.html#io.IOBase.readline
178+
"""
179+
raise NotImplementedError(_DEFER_IMPLEMENTATION_ERR_MSG)
180+
184181
def readlines(self, hint: int = -1) -> None:
185182
"""
186183
See https://docs.python.org/3/library/io.html#io.IOBase.readlines
@@ -213,18 +210,18 @@ def truncate(self, size: int | None = None) -> None:
213210

214211
def write(self, b: bytes | bytearray | array.array) -> None:
215212
"""
216-
Not yet supported in UDF and Stored Procedures.
213+
See https://docs.python.org/3/library/io.html#io.RawIOBase.write
217214
"""
218215
raise NotImplementedError(_DEFER_IMPLEMENTATION_ERR_MSG)
219216

220217
def writable(self) -> None:
221218
"""
222-
Not yet supported in UDF and Stored Procedures.
219+
See https://docs.python.org/3/library/io.html#io.IOBase.writable
223220
"""
224221
raise NotImplementedError(_DEFER_IMPLEMENTATION_ERR_MSG)
225222

226223
def writelines(self, lines: Iterable[str] | list[str]) -> None:
227224
"""
228-
Not yet supported in UDF and Stored Procedures.
225+
See https://docs.python.org/3/library/io.html#io.IOBase.writelines
229226
"""
230227
raise NotImplementedError(_DEFER_IMPLEMENTATION_ERR_MSG)

tests/unit/test_files.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
import pytest
88

9-
from snowflake.snowpark._internal.utils import private_preview
109
from snowflake.snowpark.files import _DEFER_IMPLEMENTATION_ERR_MSG, SnowflakeFile
1110

1211

@@ -16,7 +15,6 @@ def test_create_snowflakefile():
1615
assert snowflake_file._mode == "r"
1716

1817

19-
@private_preview(version="1.22.1")
2018
def test_write_snowflakefile():
2119
with SnowflakeFile.open_new_result("w") as snowflake_file:
2220
assert snowflake_file._file_location == "new results file"

0 commit comments

Comments
 (0)