From 7c8c009a93d38060ee496ab400ebf27e1adf3d62 Mon Sep 17 00:00:00 2001 From: Theo Vanderkooy Date: Mon, 20 Jan 2025 10:56:00 -0500 Subject: [PATCH 1/3] accept stage paths starting with / for GET --- src/snowflake/snowpark/_internal/utils.py | 2 ++ tests/unit/test_internal_utils.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/snowflake/snowpark/_internal/utils.py b/src/snowflake/snowpark/_internal/utils.py index ea7c5e346c9..9efec324196 100644 --- a/src/snowflake/snowpark/_internal/utils.py +++ b/src/snowflake/snowpark/_internal/utils.py @@ -65,9 +65,11 @@ STAGE_PREFIX = "@" SNOWURL_PREFIX = "snow://" +RELATIVE_PATH_PREFIX = "/" SNOWFLAKE_PATH_PREFIXES = [ STAGE_PREFIX, SNOWURL_PREFIX, + RELATIVE_PATH_PREFIX, ] # Scala uses 3 but this can be larger. Consider allowing users to configure it. diff --git a/tests/unit/test_internal_utils.py b/tests/unit/test_internal_utils.py index 5be4f633dd3..4c830ae1384 100644 --- a/tests/unit/test_internal_utils.py +++ b/tests/unit/test_internal_utils.py @@ -62,6 +62,8 @@ def test_split_path(path: str, expected_dir: str, expected_file: str) -> None: False, "'snow://domain/test_entity/versions/test_version/file.txt'", ), + ("/some/file.yml", False, "'/some/file.yml'"), + ("'/some/file.yml'", False, "'/some/file.yml'"), ], ) def test_normalize_path(path: str, is_local: bool, expected: str) -> None: From 96de4a19ccce3e322a20d2a9c0d19c132a1d8df3 Mon Sep 17 00:00:00 2001 From: Theo Vanderkooy Date: Mon, 27 Jan 2025 15:55:24 -0500 Subject: [PATCH 2/3] Keep existing behaviour for `session.read.()`, that paths starting with `/` are an error. --- src/snowflake/snowpark/_internal/utils.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/snowflake/snowpark/_internal/utils.py b/src/snowflake/snowpark/_internal/utils.py index 9efec324196..081f15938da 100644 --- a/src/snowflake/snowpark/_internal/utils.py +++ b/src/snowflake/snowpark/_internal/utils.py @@ -69,6 +69,8 @@ SNOWFLAKE_PATH_PREFIXES = [ STAGE_PREFIX, SNOWURL_PREFIX, +] +SNOWFLAKE_PATH_PREFIXES_FOR_GET = SNOWFLAKE_PATH_PREFIXES + [ RELATIVE_PATH_PREFIX, ] @@ -374,7 +376,7 @@ def normalize_path(path: str, is_local: bool) -> str: a directory named "load data". Therefore, if `path` is already wrapped by single quotes, we do nothing. """ - prefixes = ["file://"] if is_local else SNOWFLAKE_PATH_PREFIXES + prefixes = ["file://"] if is_local else SNOWFLAKE_PATH_PREFIXES_FOR_GET if is_single_quoted(path): return path if is_local and OPERATING_SYSTEM == "Windows": @@ -410,7 +412,7 @@ def split_path(path: str) -> Tuple[str, str]: def unwrap_stage_location_single_quote(name: str) -> str: new_name = unwrap_single_quote(name) - if any(new_name.startswith(prefix) for prefix in SNOWFLAKE_PATH_PREFIXES): + if any(new_name.startswith(prefix) for prefix in SNOWFLAKE_PATH_PREFIXES_FOR_GET): return new_name return f"{STAGE_PREFIX}{new_name}" From fa61064a0601180162a5807bef6958292fc855fb Mon Sep 17 00:00:00 2001 From: Theo Vanderkooy Date: Tue, 28 Jan 2025 17:27:41 -0500 Subject: [PATCH 3/3] Add changelog entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7caba13dd65..32390bfc296 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -74,6 +74,7 @@ - Added support for creating a temporary view via `DataFrame.create_or_replace_temp_view` from a DataFrame created by reading a file from a stage. - Added support for `value_contains_null` parameter to MapType. - Added `interactive` to telemetry that indicates whether the current environment is an interactive one. +- Allow `session.file.get` in a Native App to read file paths starting with `/` from the current version #### Bug Fixes