snowflake-connector-python 3.13.0__tar.gz → 3.13.2__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.
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/DESCRIPTION.md +7 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/PKG-INFO +8 -1
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/auth/_auth.py +6 -1
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/cache.py +11 -3
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/cursor.py +6 -2
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/encryption_util.py +2 -1
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/file_util.py +4 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/ocsp_snowflake.py +161 -5
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/pandas_tools.py +99 -29
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/storage_client.py +7 -2
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/util_text.py +5 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/version.py +1 -1
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake_connector_python.egg-info/PKG-INFO +8 -1
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/CONTRIBUTING.md +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/LICENSE.txt +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/MANIFEST.in +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/NOTICE +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/README.md +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/SECURITY.md +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/pyproject.toml +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/setup.cfg +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/setup.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/__init__.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/_query_context_cache.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/_sql_util.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/_utils.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/arrow_context.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/auth/__init__.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/auth/by_plugin.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/auth/default.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/auth/idtoken.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/auth/keypair.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/auth/oauth.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/auth/okta.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/auth/pat.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/auth/usrpwdmfa.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/auth/webbrowser.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/azure_storage_client.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/backoff_policies.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/bind_upload_agent.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/compat.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/config_manager.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/connection.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/connection_diagnostic.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/constants.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/converter.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/converter_issue23517.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/converter_null.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/converter_snowsql.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/dbapi.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/description.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/errorcode.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/errors.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/feature.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/file_compression_type.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/file_transfer_agent.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/gcs_storage_client.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/gzip_decoder.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/local_storage_client.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/log_configuration.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/ArrayConverter.cpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/ArrayConverter.hpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/BinaryConverter.cpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/BinaryConverter.hpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/BooleanConverter.cpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/BooleanConverter.hpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowChunkIterator.cpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowChunkIterator.hpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowIterator.cpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowIterator.hpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowTableIterator.cpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/CArrowTableIterator.hpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/DateConverter.cpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/DateConverter.hpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/DecimalConverter.cpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/DecimalConverter.hpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/FixedSizeListConverter.cpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/FixedSizeListConverter.hpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/FloatConverter.cpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/FloatConverter.hpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/IColumnConverter.hpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/IntConverter.cpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/IntConverter.hpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/LICENSE.txt +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/MapConverter.cpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/MapConverter.hpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/ObjectConverter.cpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/ObjectConverter.hpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Common.cpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Common.hpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Helpers.cpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/Python/Helpers.hpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/SnowflakeType.cpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/SnowflakeType.hpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/StringConverter.cpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/StringConverter.hpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeConverter.cpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeConverter.hpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeStampConverter.cpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/TimeStampConverter.hpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/Util/macros.hpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/Util/time.cpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/Util/time.hpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_accessors.h +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_alloc.h +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_assert.h +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_builder.h +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_emitter.h +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_endian.h +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_epilogue.h +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_flatbuffers.h +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_identifier.h +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_iov.h +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_prologue.h +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_refmap.h +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_rtconfig.h +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_types.h +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/flatcc_verifier.h +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/flatcc_portable.h +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/paligned_alloc.h +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pattributes.h +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic.h +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic_pop.h +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pdiagnostic_push.h +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pendian.h +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pendian_detect.h +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pinline.h +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pinttypes.h +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/portable.h +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/portable_basic.h +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstatic_assert.h +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstdalign.h +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pstdint.h +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/punaligned.h +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pversion.h +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc/portable/pwarnings.h +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/flatcc.c +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow.c +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow.h +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow.hpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_arrow_iterator.pyx +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_device.c +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_device.h +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_ipc.c +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/ArrowIterator/nanoarrow_ipc.h +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/Logging/logging.cpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/nanoarrow_cpp/Logging/logging.hpp +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/network.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/ocsp_asn1crypto.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/options.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/proxy.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/py.typed +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/result_batch.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/result_set.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/s3_storage_client.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/secret_detector.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/sf_dirs.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/sfbinaryformat.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/sfdatetime.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/snow_logging.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/sqlstate.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/ssd_internal_keys.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/ssl_wrap_socket.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/telemetry.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/telemetry_oob.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/test_util.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/time_util.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/tool/__init__.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/tool/dump_certs.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/tool/dump_ocsp_response.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/tool/dump_ocsp_response_cache.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/tool/probe_connection.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/url_util.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/__init__.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/requests/LICENSE +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/requests/__init__.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/requests/__version__.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/requests/_internal_utils.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/requests/adapters.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/requests/api.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/requests/auth.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/requests/certs.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/requests/compat.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/requests/cookies.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/requests/exceptions.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/requests/help.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/requests/hooks.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/requests/models.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/requests/sessions.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/requests/status_codes.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/requests/structures.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/requests/utils.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/LICENSE.txt +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/__init__.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/_collections.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/_version.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/connection.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/connectionpool.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/contrib/__init__.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/contrib/_appengine_environ.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/contrib/_securetransport/__init__.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/contrib/_securetransport/bindings.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/contrib/_securetransport/low_level.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/contrib/appengine.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/contrib/ntlmpool.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/contrib/pyopenssl.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/contrib/securetransport.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/contrib/socks.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/exceptions.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/fields.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/filepost.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/packages/__init__.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/packages/backports/__init__.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/packages/backports/makefile.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/packages/backports/weakref_finalize.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/packages/six.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/poolmanager.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/request.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/response.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/util/__init__.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/util/connection.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/util/proxy.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/util/queue.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/util/request.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/util/response.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/util/retry.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/util/ssl_.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/util/ssl_match_hostname.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/util/ssltransport.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/util/timeout.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/util/url.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake/connector/vendored/urllib3/util/wait.py +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake_connector_python.egg-info/SOURCES.txt +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake_connector_python.egg-info/dependency_links.txt +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake_connector_python.egg-info/entry_points.txt +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake_connector_python.egg-info/not-zip-safe +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake_connector_python.egg-info/requires.txt +0 -0
- {snowflake_connector_python-3.13.0 → snowflake_connector_python-3.13.2}/src/snowflake_connector_python.egg-info/top_level.txt +0 -0
|
@@ -7,6 +7,13 @@ https://docs.snowflake.com/
|
|
|
7
7
|
Source code is also available at: https://github.com/snowflakedb/snowflake-connector-python
|
|
8
8
|
|
|
9
9
|
# Release Notes
|
|
10
|
+
- v3.13.2(January 29, 2025)
|
|
11
|
+
- Changed not to use scoped temporary objects.
|
|
12
|
+
|
|
13
|
+
- v3.13.1(January 29, 2025)
|
|
14
|
+
- Remedied SQL injection vulnerability in snowflake.connector.pandas_tools.write_pandas. See more https://github.com/snowflakedb/snowflake-connector-python/security/advisories/GHSA-2vpq-fh52-j3wv
|
|
15
|
+
- Remedied vulnerability in deserialization of the OCSP response cache. See more: https://github.com/snowflakedb/snowflake-connector-python/security/advisories/GHSA-m4f6-vcj4-w5mx
|
|
16
|
+
- Remedied vulnerability connected to cache files permissions. See more: https://github.com/snowflakedb/snowflake-connector-python/security/advisories/GHSA-r2x6-cjg7-8r43
|
|
10
17
|
|
|
11
18
|
- v3.13.0(January 23,2025)
|
|
12
19
|
- Added a feature to limit the sizes of IO-bound ThreadPoolExecutors during PUT and GET commands.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: snowflake-connector-python
|
|
3
|
-
Version: 3.13.
|
|
3
|
+
Version: 3.13.2
|
|
4
4
|
Summary: Snowflake Connector for Python
|
|
5
5
|
Home-page: https://www.snowflake.com/
|
|
6
6
|
Author: Snowflake, Inc
|
|
@@ -84,6 +84,13 @@ https://docs.snowflake.com/
|
|
|
84
84
|
Source code is also available at: https://github.com/snowflakedb/snowflake-connector-python
|
|
85
85
|
|
|
86
86
|
# Release Notes
|
|
87
|
+
- v3.13.2(January 29, 2025)
|
|
88
|
+
- Changed not to use scoped temporary objects.
|
|
89
|
+
|
|
90
|
+
- v3.13.1(January 29, 2025)
|
|
91
|
+
- Remedied SQL injection vulnerability in snowflake.connector.pandas_tools.write_pandas. See more https://github.com/snowflakedb/snowflake-connector-python/security/advisories/GHSA-2vpq-fh52-j3wv
|
|
92
|
+
- Remedied vulnerability in deserialization of the OCSP response cache. See more: https://github.com/snowflakedb/snowflake-connector-python/security/advisories/GHSA-m4f6-vcj4-w5mx
|
|
93
|
+
- Remedied vulnerability connected to cache files permissions. See more: https://github.com/snowflakedb/snowflake-connector-python/security/advisories/GHSA-r2x6-cjg7-8r43
|
|
87
94
|
|
|
88
95
|
- v3.13.0(January 23,2025)
|
|
89
96
|
- Added a feature to limit the sizes of IO-bound ThreadPoolExecutors during PUT and GET commands.
|
|
@@ -52,6 +52,7 @@ from ..errors import (
|
|
|
52
52
|
ProgrammingError,
|
|
53
53
|
ServiceUnavailableError,
|
|
54
54
|
)
|
|
55
|
+
from ..file_util import owner_rw_opener
|
|
55
56
|
from ..network import (
|
|
56
57
|
ACCEPT_TYPE_APPLICATION_SNOWFLAKE,
|
|
57
58
|
CONTENT_TYPE_APPLICATION_JSON,
|
|
@@ -625,7 +626,11 @@ def flush_temporary_credentials() -> None:
|
|
|
625
626
|
)
|
|
626
627
|
try:
|
|
627
628
|
with open(
|
|
628
|
-
TEMPORARY_CREDENTIAL_FILE,
|
|
629
|
+
TEMPORARY_CREDENTIAL_FILE,
|
|
630
|
+
"w",
|
|
631
|
+
encoding="utf-8",
|
|
632
|
+
errors="ignore",
|
|
633
|
+
opener=owner_rw_opener,
|
|
629
634
|
) as f:
|
|
630
635
|
json.dump(TEMPORARY_CREDENTIAL, f)
|
|
631
636
|
except Exception as ex:
|
|
@@ -388,6 +388,7 @@ class SFDictFileCache(SFDictCache):
|
|
|
388
388
|
file_path: str | dict[str, str],
|
|
389
389
|
entry_lifetime: int = constants.DAY_IN_SECONDS,
|
|
390
390
|
file_timeout: int = 0,
|
|
391
|
+
load_if_file_exists: bool = True,
|
|
391
392
|
) -> None:
|
|
392
393
|
"""Inits an SFDictFileCache with path, lifetime.
|
|
393
394
|
|
|
@@ -445,7 +446,7 @@ class SFDictFileCache(SFDictCache):
|
|
|
445
446
|
self._file_lock_path = f"{self.file_path}.lock"
|
|
446
447
|
self._file_lock = FileLock(self._file_lock_path, timeout=self.file_timeout)
|
|
447
448
|
self.last_loaded: datetime.datetime | None = None
|
|
448
|
-
if os.path.exists(self.file_path):
|
|
449
|
+
if os.path.exists(self.file_path) and load_if_file_exists:
|
|
449
450
|
with self._lock:
|
|
450
451
|
self._load()
|
|
451
452
|
# indicate whether the cache is modified or not, this variable is for
|
|
@@ -498,7 +499,7 @@ class SFDictFileCache(SFDictCache):
|
|
|
498
499
|
"""Load cache from disk if possible, returns whether it was able to load."""
|
|
499
500
|
try:
|
|
500
501
|
with open(self.file_path, "rb") as r_file:
|
|
501
|
-
other: SFDictFileCache =
|
|
502
|
+
other: SFDictFileCache = self._deserialize(r_file)
|
|
502
503
|
# Since we want to know whether we are dirty after loading
|
|
503
504
|
# we have to know whether the file could learn anything from self
|
|
504
505
|
# so instead of calling self.update we call other.update and swap
|
|
@@ -529,6 +530,13 @@ class SFDictFileCache(SFDictCache):
|
|
|
529
530
|
with self._lock:
|
|
530
531
|
return self._load()
|
|
531
532
|
|
|
533
|
+
def _serialize(self):
|
|
534
|
+
return pickle.dumps(self)
|
|
535
|
+
|
|
536
|
+
@classmethod
|
|
537
|
+
def _deserialize(cls, r_file):
|
|
538
|
+
return pickle.load(r_file)
|
|
539
|
+
|
|
532
540
|
def _save(self, load_first: bool = True, force_flush: bool = False) -> bool:
|
|
533
541
|
"""Save cache to disk if possible, returns whether it was able to save.
|
|
534
542
|
|
|
@@ -559,7 +567,7 @@ class SFDictFileCache(SFDictCache):
|
|
|
559
567
|
# python program.
|
|
560
568
|
# thus we fall back to the approach using the normal open() method to open a file and write.
|
|
561
569
|
with open(tmp_file, "wb") as w_file:
|
|
562
|
-
w_file.write(
|
|
570
|
+
w_file.write(self._serialize())
|
|
563
571
|
# We write to a tmp file and then move it to have atomic write
|
|
564
572
|
os.replace(tmp_file_path, self.file_path)
|
|
565
573
|
self.last_loaded = datetime.datetime.fromtimestamp(
|
|
@@ -875,6 +875,7 @@ class SnowflakeCursor:
|
|
|
875
875
|
_skip_upload_on_content_match: bool = False,
|
|
876
876
|
file_stream: IO[bytes] | None = None,
|
|
877
877
|
num_statements: int | None = None,
|
|
878
|
+
_force_qmark_paramstyle: bool = False,
|
|
878
879
|
_dataframe_ast: str | None = None,
|
|
879
880
|
) -> Self | dict[str, Any] | None:
|
|
880
881
|
"""Executes a command/query.
|
|
@@ -910,6 +911,7 @@ class SnowflakeCursor:
|
|
|
910
911
|
file_stream: File-like object to be uploaded with PUT
|
|
911
912
|
num_statements: Query level parameter submitted in _statement_params constraining exact number of
|
|
912
913
|
statements being submitted (or 0 if submitting an uncounted number) when using a multi-statement query.
|
|
914
|
+
_force_qmark_paramstyle: Force the use of qmark paramstyle regardless of the connection's paramstyle.
|
|
913
915
|
_dataframe_ast: Base64-encoded dataframe request abstract syntax tree.
|
|
914
916
|
|
|
915
917
|
Returns:
|
|
@@ -958,7 +960,7 @@ class SnowflakeCursor:
|
|
|
958
960
|
"dataframe_ast": _dataframe_ast,
|
|
959
961
|
}
|
|
960
962
|
|
|
961
|
-
if self._connection.is_pyformat:
|
|
963
|
+
if self._connection.is_pyformat and not _force_qmark_paramstyle:
|
|
962
964
|
query = self._preprocess_pyformat_query(command, params)
|
|
963
965
|
else:
|
|
964
966
|
# qmark and numeric paramstyle
|
|
@@ -1458,7 +1460,9 @@ class SnowflakeCursor:
|
|
|
1458
1460
|
else:
|
|
1459
1461
|
if re.search(";/s*$", command) is None:
|
|
1460
1462
|
command = command + "; "
|
|
1461
|
-
if self._connection.is_pyformat
|
|
1463
|
+
if self._connection.is_pyformat and not kwargs.get(
|
|
1464
|
+
"_force_qmark_paramstyle", False
|
|
1465
|
+
):
|
|
1462
1466
|
processed_queries = [
|
|
1463
1467
|
self._preprocess_pyformat_query(command, params)
|
|
1464
1468
|
for params in seqparams
|
|
@@ -17,6 +17,7 @@ from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
|
|
|
17
17
|
|
|
18
18
|
from .compat import PKCS5_OFFSET, PKCS5_PAD, PKCS5_UNPAD
|
|
19
19
|
from .constants import UTF8, EncryptionMetadata, MaterialDescriptor, kilobyte
|
|
20
|
+
from .file_util import owner_rw_opener
|
|
20
21
|
from .util_text import random_string
|
|
21
22
|
|
|
22
23
|
block_size = int(algorithms.AES.block_size / 8) # in bytes
|
|
@@ -213,7 +214,7 @@ class SnowflakeEncryptionUtil:
|
|
|
213
214
|
|
|
214
215
|
logger.debug("encrypted file: %s, tmp file: %s", in_filename, temp_output_file)
|
|
215
216
|
with open(in_filename, "rb") as infile:
|
|
216
|
-
with open(temp_output_file, "wb") as outfile:
|
|
217
|
+
with open(temp_output_file, "wb", opener=owner_rw_opener) as outfile:
|
|
217
218
|
SnowflakeEncryptionUtil.decrypt_stream(
|
|
218
219
|
metadata, encryption_material, infile, outfile, chunk_size
|
|
219
220
|
)
|
|
@@ -21,6 +21,10 @@ from .constants import UTF8, kilobyte
|
|
|
21
21
|
logger = getLogger(__name__)
|
|
22
22
|
|
|
23
23
|
|
|
24
|
+
def owner_rw_opener(path, flags) -> int:
|
|
25
|
+
return os.open(path, flags, mode=0o600)
|
|
26
|
+
|
|
27
|
+
|
|
24
28
|
class SnowflakeFileUtil:
|
|
25
29
|
@staticmethod
|
|
26
30
|
def get_digest_and_size(src: IO[bytes]) -> tuple[str, int]:
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
from __future__ import annotations
|
|
7
7
|
|
|
8
8
|
import codecs
|
|
9
|
+
import importlib
|
|
9
10
|
import json
|
|
10
11
|
import os
|
|
11
12
|
import platform
|
|
@@ -30,6 +31,7 @@ from asn1crypto.ocsp import CertId, OCSPRequest, SingleResponse
|
|
|
30
31
|
from asn1crypto.x509 import Certificate
|
|
31
32
|
from OpenSSL.SSL import Connection
|
|
32
33
|
|
|
34
|
+
from snowflake.connector import SNOWFLAKE_CONNECTOR_VERSION
|
|
33
35
|
from snowflake.connector.compat import OK, urlsplit, urlunparse
|
|
34
36
|
from snowflake.connector.constants import HTTP_HEADER_USER_AGENT
|
|
35
37
|
from snowflake.connector.errorcode import (
|
|
@@ -58,9 +60,10 @@ from snowflake.connector.network import PYTHON_CONNECTOR_USER_AGENT
|
|
|
58
60
|
|
|
59
61
|
from . import constants
|
|
60
62
|
from .backoff_policies import exponential_backoff
|
|
61
|
-
from .cache import SFDictCache, SFDictFileCache
|
|
63
|
+
from .cache import CacheEntry, SFDictCache, SFDictFileCache
|
|
62
64
|
from .telemetry import TelemetryField, generate_telemetry_data_dict
|
|
63
65
|
from .url_util import extract_top_level_domain_from_hostname, url_encode_str
|
|
66
|
+
from .util_text import _base64_bytes_to_str
|
|
64
67
|
|
|
65
68
|
|
|
66
69
|
class OCSPResponseValidationResult(NamedTuple):
|
|
@@ -72,19 +75,172 @@ class OCSPResponseValidationResult(NamedTuple):
|
|
|
72
75
|
ts: int | None = None
|
|
73
76
|
validated: bool = False
|
|
74
77
|
|
|
78
|
+
def _serialize(self):
|
|
79
|
+
def serialize_exception(exc):
|
|
80
|
+
# serialization exception is not supported for all exceptions
|
|
81
|
+
# in the ocsp_snowflake.py, most exceptions are RevocationCheckError which is easy to serialize.
|
|
82
|
+
# however, it would require non-trivial effort to serialize other exceptions especially 3rd part errors
|
|
83
|
+
# as there can be un-serializable members and nondeterministic constructor arguments.
|
|
84
|
+
# here we do a general best efforts serialization for other exceptions recording only the error message.
|
|
85
|
+
if not exc:
|
|
86
|
+
return None
|
|
87
|
+
|
|
88
|
+
exc_type = type(exc)
|
|
89
|
+
ret = {"class": exc_type.__name__, "module": exc_type.__module__}
|
|
90
|
+
if isinstance(exc, RevocationCheckError):
|
|
91
|
+
ret.update({"errno": exc.errno, "msg": exc.raw_msg})
|
|
92
|
+
else:
|
|
93
|
+
ret.update({"msg": str(exc)})
|
|
94
|
+
return ret
|
|
95
|
+
|
|
96
|
+
return json.dumps(
|
|
97
|
+
{
|
|
98
|
+
"exception": serialize_exception(self.exception),
|
|
99
|
+
"issuer": (
|
|
100
|
+
_base64_bytes_to_str(self.issuer.dump()) if self.issuer else None
|
|
101
|
+
),
|
|
102
|
+
"subject": (
|
|
103
|
+
_base64_bytes_to_str(self.subject.dump()) if self.subject else None
|
|
104
|
+
),
|
|
105
|
+
"cert_id": (
|
|
106
|
+
_base64_bytes_to_str(self.cert_id.dump()) if self.cert_id else None
|
|
107
|
+
),
|
|
108
|
+
"ocsp_response": _base64_bytes_to_str(self.ocsp_response),
|
|
109
|
+
"ts": self.ts,
|
|
110
|
+
"validated": self.validated,
|
|
111
|
+
}
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
@classmethod
|
|
115
|
+
def _deserialize(cls, json_str: str) -> OCSPResponseValidationResult:
|
|
116
|
+
json_obj = json.loads(json_str)
|
|
117
|
+
|
|
118
|
+
def deserialize_exception(exception_dict: dict | None) -> Exception | None:
|
|
119
|
+
# as pointed out in the serialization method, here we do the best effort deserialization
|
|
120
|
+
# for non-RevocationCheckError exceptions. If we can not deserialize the exception, we will
|
|
121
|
+
# return a RevocationCheckError with a message indicating the failure.
|
|
122
|
+
if not exception_dict:
|
|
123
|
+
return
|
|
124
|
+
exc_class = exception_dict.get("class")
|
|
125
|
+
exc_module = exception_dict.get("module")
|
|
126
|
+
try:
|
|
127
|
+
if (
|
|
128
|
+
exc_class == "RevocationCheckError"
|
|
129
|
+
and exc_module == "snowflake.connector.errors"
|
|
130
|
+
):
|
|
131
|
+
return RevocationCheckError(
|
|
132
|
+
msg=exception_dict["msg"],
|
|
133
|
+
errno=exception_dict["errno"],
|
|
134
|
+
)
|
|
135
|
+
else:
|
|
136
|
+
module = importlib.import_module(exc_module)
|
|
137
|
+
exc_cls = getattr(module, exc_class)
|
|
138
|
+
return exc_cls(exception_dict["msg"])
|
|
139
|
+
except Exception as deserialize_exc:
|
|
140
|
+
logger.debug(
|
|
141
|
+
f"hitting error {str(deserialize_exc)} while deserializing exception,"
|
|
142
|
+
f" the original error error class and message are {exc_class} and {exception_dict['msg']}"
|
|
143
|
+
)
|
|
144
|
+
return RevocationCheckError(
|
|
145
|
+
f"Got error {str(deserialize_exc)} while deserializing ocsp cache, please try "
|
|
146
|
+
f"cleaning up the "
|
|
147
|
+
f"OCSP cache under directory {OCSP_RESPONSE_VALIDATION_CACHE.file_path}",
|
|
148
|
+
errno=ER_OCSP_RESPONSE_LOAD_FAILURE,
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
return OCSPResponseValidationResult(
|
|
152
|
+
exception=deserialize_exception(json_obj.get("exception")),
|
|
153
|
+
issuer=(
|
|
154
|
+
Certificate.load(b64decode(json_obj.get("issuer")))
|
|
155
|
+
if json_obj.get("issuer")
|
|
156
|
+
else None
|
|
157
|
+
),
|
|
158
|
+
subject=(
|
|
159
|
+
Certificate.load(b64decode(json_obj.get("subject")))
|
|
160
|
+
if json_obj.get("subject")
|
|
161
|
+
else None
|
|
162
|
+
),
|
|
163
|
+
cert_id=(
|
|
164
|
+
CertId.load(b64decode(json_obj.get("cert_id")))
|
|
165
|
+
if json_obj.get("cert_id")
|
|
166
|
+
else None
|
|
167
|
+
),
|
|
168
|
+
ocsp_response=(
|
|
169
|
+
b64decode(json_obj.get("ocsp_response"))
|
|
170
|
+
if json_obj.get("ocsp_response")
|
|
171
|
+
else None
|
|
172
|
+
),
|
|
173
|
+
ts=json_obj.get("ts"),
|
|
174
|
+
validated=json_obj.get("validated"),
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
class _OCSPResponseValidationResultCache(SFDictFileCache):
|
|
179
|
+
def _serialize(self) -> bytes:
|
|
180
|
+
entries = {
|
|
181
|
+
(
|
|
182
|
+
_base64_bytes_to_str(k[0]),
|
|
183
|
+
_base64_bytes_to_str(k[1]),
|
|
184
|
+
_base64_bytes_to_str(k[2]),
|
|
185
|
+
): (v.expiry.isoformat(), v.entry._serialize())
|
|
186
|
+
for k, v in self._cache.items()
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return json.dumps(
|
|
190
|
+
{
|
|
191
|
+
"cache_keys": list(entries.keys()),
|
|
192
|
+
"cache_items": list(entries.values()),
|
|
193
|
+
"entry_lifetime": self._entry_lifetime.total_seconds(),
|
|
194
|
+
"file_path": str(self.file_path),
|
|
195
|
+
"file_timeout": self.file_timeout,
|
|
196
|
+
"last_loaded": (
|
|
197
|
+
self.last_loaded.isoformat() if self.last_loaded else None
|
|
198
|
+
),
|
|
199
|
+
"telemetry": self.telemetry,
|
|
200
|
+
"connector_version": SNOWFLAKE_CONNECTOR_VERSION, # reserved for schema version control
|
|
201
|
+
}
|
|
202
|
+
).encode()
|
|
203
|
+
|
|
204
|
+
@classmethod
|
|
205
|
+
def _deserialize(cls, opened_fd) -> _OCSPResponseValidationResultCache:
|
|
206
|
+
data = json.loads(opened_fd.read().decode())
|
|
207
|
+
cache_instance = cls(
|
|
208
|
+
file_path=data["file_path"],
|
|
209
|
+
entry_lifetime=int(data["entry_lifetime"]),
|
|
210
|
+
file_timeout=data["file_timeout"],
|
|
211
|
+
load_if_file_exists=False,
|
|
212
|
+
)
|
|
213
|
+
cache_instance.file_path = os.path.expanduser(data["file_path"])
|
|
214
|
+
cache_instance.telemetry = data["telemetry"]
|
|
215
|
+
cache_instance.last_loaded = (
|
|
216
|
+
datetime.fromisoformat(data["last_loaded"]) if data["last_loaded"] else None
|
|
217
|
+
)
|
|
218
|
+
for k, v in zip(data["cache_keys"], data["cache_items"]):
|
|
219
|
+
cache_instance._cache[
|
|
220
|
+
(b64decode(k[0]), b64decode(k[1]), b64decode(k[2]))
|
|
221
|
+
] = CacheEntry(
|
|
222
|
+
datetime.fromisoformat(v[0]),
|
|
223
|
+
OCSPResponseValidationResult._deserialize(v[1]),
|
|
224
|
+
)
|
|
225
|
+
return cache_instance
|
|
226
|
+
|
|
75
227
|
|
|
76
228
|
try:
|
|
77
229
|
OCSP_RESPONSE_VALIDATION_CACHE: SFDictFileCache[
|
|
78
230
|
tuple[bytes, bytes, bytes],
|
|
79
231
|
OCSPResponseValidationResult,
|
|
80
|
-
] =
|
|
232
|
+
] = _OCSPResponseValidationResultCache(
|
|
81
233
|
entry_lifetime=constants.DAY_IN_SECONDS,
|
|
82
234
|
file_path={
|
|
83
235
|
"linux": os.path.join(
|
|
84
|
-
"~", ".cache", "snowflake", "ocsp_response_validation_cache"
|
|
236
|
+
"~", ".cache", "snowflake", "ocsp_response_validation_cache.json"
|
|
85
237
|
),
|
|
86
238
|
"darwin": os.path.join(
|
|
87
|
-
"~",
|
|
239
|
+
"~",
|
|
240
|
+
"Library",
|
|
241
|
+
"Caches",
|
|
242
|
+
"Snowflake",
|
|
243
|
+
"ocsp_response_validation_cache.json",
|
|
88
244
|
),
|
|
89
245
|
"windows": os.path.join(
|
|
90
246
|
"~",
|
|
@@ -92,7 +248,7 @@ try:
|
|
|
92
248
|
"Local",
|
|
93
249
|
"Snowflake",
|
|
94
250
|
"Caches",
|
|
95
|
-
"ocsp_response_validation_cache",
|
|
251
|
+
"ocsp_response_validation_cache.json",
|
|
96
252
|
),
|
|
97
253
|
},
|
|
98
254
|
)
|
|
@@ -85,9 +85,16 @@ def _do_create_temp_stage(
|
|
|
85
85
|
overwrite: bool,
|
|
86
86
|
use_scoped_temp_object: bool,
|
|
87
87
|
) -> None:
|
|
88
|
-
create_stage_sql = f"CREATE {get_temp_type_for_object(use_scoped_temp_object)} STAGE /* Python:snowflake.connector.pandas_tools.write_pandas() */
|
|
89
|
-
|
|
90
|
-
|
|
88
|
+
create_stage_sql = f"CREATE {get_temp_type_for_object(use_scoped_temp_object)} STAGE /* Python:snowflake.connector.pandas_tools.write_pandas() */ identifier(?) FILE_FORMAT=(TYPE=PARQUET COMPRESSION={compression}{' BINARY_AS_TEXT=FALSE' if auto_create_table or overwrite else ''})"
|
|
89
|
+
params = (stage_location,)
|
|
90
|
+
logger.debug(f"creating stage with '{create_stage_sql}'. params: %s", params)
|
|
91
|
+
cursor.execute(
|
|
92
|
+
create_stage_sql,
|
|
93
|
+
_is_internal=True,
|
|
94
|
+
_force_qmark_paramstyle=True,
|
|
95
|
+
params=params,
|
|
96
|
+
num_statements=1,
|
|
97
|
+
)
|
|
91
98
|
|
|
92
99
|
|
|
93
100
|
def _create_temp_stage(
|
|
@@ -147,12 +154,19 @@ def _do_create_temp_file_format(
|
|
|
147
154
|
use_scoped_temp_object: bool,
|
|
148
155
|
) -> None:
|
|
149
156
|
file_format_sql = (
|
|
150
|
-
f"CREATE {get_temp_type_for_object(use_scoped_temp_object)} FILE FORMAT
|
|
157
|
+
f"CREATE {get_temp_type_for_object(use_scoped_temp_object)} FILE FORMAT identifier(?) "
|
|
151
158
|
f"/* Python:snowflake.connector.pandas_tools.write_pandas() */ "
|
|
152
159
|
f"TYPE=PARQUET COMPRESSION={compression}{sql_use_logical_type}"
|
|
153
160
|
)
|
|
154
|
-
|
|
155
|
-
|
|
161
|
+
params = (file_format_location,)
|
|
162
|
+
logger.debug(f"creating file format with '{file_format_sql}'. params: %s", params)
|
|
163
|
+
cursor.execute(
|
|
164
|
+
file_format_sql,
|
|
165
|
+
_is_internal=True,
|
|
166
|
+
_force_qmark_paramstyle=True,
|
|
167
|
+
params=params,
|
|
168
|
+
num_statements=1,
|
|
169
|
+
)
|
|
156
170
|
|
|
157
171
|
|
|
158
172
|
def _create_temp_file_format(
|
|
@@ -307,6 +321,12 @@ def write_pandas(
|
|
|
307
321
|
else False
|
|
308
322
|
)
|
|
309
323
|
|
|
324
|
+
"""sfc-gh-yixie: scoped temp stage isn't required out side of a SP.
|
|
325
|
+
TODO: remove the following line when merging SP connector and Python Connector.
|
|
326
|
+
Make sure `create scoped temp stage` is supported when it's not run in a SP.
|
|
327
|
+
"""
|
|
328
|
+
_use_scoped_temp_object = False
|
|
329
|
+
|
|
310
330
|
if create_temp_table:
|
|
311
331
|
warnings.warn(
|
|
312
332
|
"create_temp_table is deprecated, we still respect this parameter when it is True but "
|
|
@@ -379,14 +399,20 @@ def write_pandas(
|
|
|
379
399
|
# Upload parquet file
|
|
380
400
|
upload_sql = (
|
|
381
401
|
"PUT /* Python:snowflake.connector.pandas_tools.write_pandas() */ "
|
|
382
|
-
"'file://{path}'
|
|
402
|
+
"'file://{path}' ? PARALLEL={parallel}"
|
|
383
403
|
).format(
|
|
384
404
|
path=chunk_path.replace("\\", "\\\\").replace("'", "\\'"),
|
|
385
|
-
stage_location=stage_location,
|
|
386
405
|
parallel=parallel,
|
|
387
406
|
)
|
|
388
|
-
|
|
389
|
-
|
|
407
|
+
params = ("@" + stage_location,)
|
|
408
|
+
logger.debug(f"uploading files with '{upload_sql}', params: %s", params)
|
|
409
|
+
cursor.execute(
|
|
410
|
+
upload_sql,
|
|
411
|
+
_is_internal=True,
|
|
412
|
+
_force_qmark_paramstyle=True,
|
|
413
|
+
params=params,
|
|
414
|
+
num_statements=1,
|
|
415
|
+
)
|
|
390
416
|
# Remove chunk file
|
|
391
417
|
os.remove(chunk_path)
|
|
392
418
|
|
|
@@ -403,9 +429,16 @@ def write_pandas(
|
|
|
403
429
|
columns = quote + f"{quote},{quote}".join(snowflake_column_names) + quote
|
|
404
430
|
|
|
405
431
|
def drop_object(name: str, object_type: str) -> None:
|
|
406
|
-
drop_sql = f"DROP {object_type.upper()} IF EXISTS
|
|
407
|
-
|
|
408
|
-
|
|
432
|
+
drop_sql = f"DROP {object_type.upper()} IF EXISTS identifier(?) /* Python:snowflake.connector.pandas_tools.write_pandas() */"
|
|
433
|
+
params = (name,)
|
|
434
|
+
logger.debug(f"dropping {object_type} with '{drop_sql}'. params: %s", params)
|
|
435
|
+
cursor.execute(
|
|
436
|
+
drop_sql,
|
|
437
|
+
_is_internal=True,
|
|
438
|
+
_force_qmark_paramstyle=True,
|
|
439
|
+
params=params,
|
|
440
|
+
num_statements=1,
|
|
441
|
+
)
|
|
409
442
|
|
|
410
443
|
if auto_create_table or overwrite:
|
|
411
444
|
file_format_location = _create_temp_file_format(
|
|
@@ -417,10 +450,17 @@ def write_pandas(
|
|
|
417
450
|
sql_use_logical_type,
|
|
418
451
|
_use_scoped_temp_object,
|
|
419
452
|
)
|
|
420
|
-
infer_schema_sql =
|
|
421
|
-
|
|
453
|
+
infer_schema_sql = "SELECT COLUMN_NAME, TYPE FROM table(infer_schema(location=>?, file_format=>?))"
|
|
454
|
+
params = (f"@{stage_location}", file_format_location)
|
|
455
|
+
logger.debug(f"inferring schema with '{infer_schema_sql}'. params: %s", params)
|
|
422
456
|
column_type_mapping = dict(
|
|
423
|
-
cursor.execute(
|
|
457
|
+
cursor.execute(
|
|
458
|
+
infer_schema_sql,
|
|
459
|
+
_is_internal=True,
|
|
460
|
+
_force_qmark_paramstyle=True,
|
|
461
|
+
params=params,
|
|
462
|
+
num_statements=1,
|
|
463
|
+
).fetchall()
|
|
424
464
|
)
|
|
425
465
|
# Infer schema can return the columns out of order depending on the chunking we do when uploading
|
|
426
466
|
# so we have to iterate through the dataframe columns to make sure we create the table with its
|
|
@@ -440,12 +480,21 @@ def write_pandas(
|
|
|
440
480
|
)
|
|
441
481
|
|
|
442
482
|
create_table_sql = (
|
|
443
|
-
f"CREATE {table_type.upper()} TABLE IF NOT EXISTS
|
|
483
|
+
f"CREATE {table_type.upper()} TABLE IF NOT EXISTS identifier(?) "
|
|
444
484
|
f"({create_table_columns})"
|
|
445
485
|
f" /* Python:snowflake.connector.pandas_tools.write_pandas() */ "
|
|
446
486
|
)
|
|
447
|
-
|
|
448
|
-
|
|
487
|
+
params = (target_table_location,)
|
|
488
|
+
logger.debug(
|
|
489
|
+
f"auto creating table with '{create_table_sql}'. params: %s", params
|
|
490
|
+
)
|
|
491
|
+
cursor.execute(
|
|
492
|
+
create_table_sql,
|
|
493
|
+
_is_internal=True,
|
|
494
|
+
_force_qmark_paramstyle=True,
|
|
495
|
+
params=params,
|
|
496
|
+
num_statements=1,
|
|
497
|
+
)
|
|
449
498
|
# need explicit casting when the underlying table schema is inferred
|
|
450
499
|
parquet_columns = "$1:" + ",$1:".join(
|
|
451
500
|
f"{quote}{snowflake_col}{quote}::{column_type_mapping[col]}"
|
|
@@ -464,12 +513,19 @@ def write_pandas(
|
|
|
464
513
|
|
|
465
514
|
try:
|
|
466
515
|
if overwrite and (not auto_create_table):
|
|
467
|
-
truncate_sql =
|
|
468
|
-
|
|
469
|
-
|
|
516
|
+
truncate_sql = "TRUNCATE TABLE identifier(?) /* Python:snowflake.connector.pandas_tools.write_pandas() */"
|
|
517
|
+
params = (target_table_location,)
|
|
518
|
+
logger.debug(f"truncating table with '{truncate_sql}'. params: %s", params)
|
|
519
|
+
cursor.execute(
|
|
520
|
+
truncate_sql,
|
|
521
|
+
_is_internal=True,
|
|
522
|
+
_force_qmark_paramstyle=True,
|
|
523
|
+
params=params,
|
|
524
|
+
num_statements=1,
|
|
525
|
+
)
|
|
470
526
|
|
|
471
527
|
copy_into_sql = (
|
|
472
|
-
f"COPY INTO
|
|
528
|
+
f"COPY INTO identifier(?) /* Python:snowflake.connector.pandas_tools.write_pandas() */ "
|
|
473
529
|
f"({columns}) "
|
|
474
530
|
f"FROM (SELECT {parquet_columns} FROM @{stage_location}) "
|
|
475
531
|
f"FILE_FORMAT=("
|
|
@@ -478,10 +534,17 @@ def write_pandas(
|
|
|
478
534
|
f"{' BINARY_AS_TEXT=FALSE' if auto_create_table or overwrite else ''}"
|
|
479
535
|
f"{sql_use_logical_type}"
|
|
480
536
|
f") "
|
|
481
|
-
f"PURGE=TRUE ON_ERROR
|
|
537
|
+
f"PURGE=TRUE ON_ERROR=?"
|
|
482
538
|
)
|
|
483
|
-
|
|
484
|
-
|
|
539
|
+
params = (target_table_location, on_error)
|
|
540
|
+
logger.debug(f"copying into with '{copy_into_sql}'. params: %s", params)
|
|
541
|
+
copy_results = cursor.execute(
|
|
542
|
+
copy_into_sql,
|
|
543
|
+
_is_internal=True,
|
|
544
|
+
_force_qmark_paramstyle=True,
|
|
545
|
+
params=params,
|
|
546
|
+
num_statements=1,
|
|
547
|
+
).fetchall()
|
|
485
548
|
|
|
486
549
|
if overwrite and auto_create_table:
|
|
487
550
|
original_table_location = build_location_helper(
|
|
@@ -491,9 +554,16 @@ def write_pandas(
|
|
|
491
554
|
quote_identifiers=quote_identifiers,
|
|
492
555
|
)
|
|
493
556
|
drop_object(original_table_location, "table")
|
|
494
|
-
rename_table_sql =
|
|
495
|
-
|
|
496
|
-
|
|
557
|
+
rename_table_sql = "ALTER TABLE identifier(?) RENAME TO identifier(?) /* Python:snowflake.connector.pandas_tools.write_pandas() */"
|
|
558
|
+
params = (target_table_location, original_table_location)
|
|
559
|
+
logger.debug(f"rename table with '{rename_table_sql}'. params: %s", params)
|
|
560
|
+
cursor.execute(
|
|
561
|
+
rename_table_sql,
|
|
562
|
+
_is_internal=True,
|
|
563
|
+
_force_qmark_paramstyle=True,
|
|
564
|
+
params=params,
|
|
565
|
+
num_statements=1,
|
|
566
|
+
)
|
|
497
567
|
except ProgrammingError:
|
|
498
568
|
if overwrite and auto_create_table:
|
|
499
569
|
# drop table only if we created a new one with a random name
|
|
@@ -329,6 +329,11 @@ class SnowflakeStorageClient(ABC):
|
|
|
329
329
|
f"{verb} with url {url} failed for exceeding maximum retries."
|
|
330
330
|
)
|
|
331
331
|
|
|
332
|
+
def _open_intermediate_dst_path(self, mode):
|
|
333
|
+
if not self.intermediate_dst_path.exists():
|
|
334
|
+
self.intermediate_dst_path.touch(mode=0o600)
|
|
335
|
+
return self.intermediate_dst_path.open(mode)
|
|
336
|
+
|
|
332
337
|
def prepare_download(self) -> None:
|
|
333
338
|
# TODO: add nicer error message for when target directory is not writeable
|
|
334
339
|
# but this should be done before we get here
|
|
@@ -352,13 +357,13 @@ class SnowflakeStorageClient(ABC):
|
|
|
352
357
|
self.num_of_chunks = ceil(file_header.content_length / self.chunk_size)
|
|
353
358
|
|
|
354
359
|
# Preallocate encrypted file.
|
|
355
|
-
with self.
|
|
360
|
+
with self._open_intermediate_dst_path("wb+") as fd:
|
|
356
361
|
fd.truncate(self.meta.src_file_size)
|
|
357
362
|
|
|
358
363
|
def write_downloaded_chunk(self, chunk_id: int, data: bytes) -> None:
|
|
359
364
|
"""Writes given data to the temp location starting at chunk_id * chunk_size."""
|
|
360
365
|
# TODO: should we use chunking and write content in smaller chunks?
|
|
361
|
-
with self.
|
|
366
|
+
with self._open_intermediate_dst_path("rb+") as fd:
|
|
362
367
|
fd.seek(self.chunk_size * chunk_id)
|
|
363
368
|
fd.write(data)
|
|
364
369
|
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
from __future__ import annotations
|
|
7
7
|
|
|
8
|
+
import base64
|
|
8
9
|
import hashlib
|
|
9
10
|
import logging
|
|
10
11
|
import random
|
|
@@ -292,6 +293,10 @@ def random_string(
|
|
|
292
293
|
return "".join([prefix, random_part, suffix])
|
|
293
294
|
|
|
294
295
|
|
|
296
|
+
def _base64_bytes_to_str(x) -> str | None:
|
|
297
|
+
return base64.b64encode(x).decode("utf-8") if x else None
|
|
298
|
+
|
|
299
|
+
|
|
295
300
|
def get_md5(text: str | bytes) -> bytes:
|
|
296
301
|
if isinstance(text, str):
|
|
297
302
|
text = text.encode("utf-8")
|