diff -Nru rasterio-1.3.2/CHANGES.txt rasterio-1.3.4/CHANGES.txt --- rasterio-1.3.2/CHANGES.txt 2022-08-19 15:45:01.000000000 +0000 +++ rasterio-1.3.4/CHANGES.txt 2022-11-16 19:51:17.000000000 +0000 @@ -1,6 +1,46 @@ Changes ======= +1.3.4 (2022-11-16) +------------------ + +This version is good for use with GDAL 3.6.0 as well as previous versions. + +Changes: + +- Resampling tests have been updated to account for changes in GDAL 3.6.0 + (#2653). +- Variables in TransformerBase.xy have been renamed for better clarity (#2609). +- Avoid use of a fixed port for the warp test server (#2619). + +Bug fixes: + +- Use Python long for FilePath VSI plugin's file position (#2652). +- In the case that a GDAL function returns NULL but doesn't set an error, we + now raise SystemError instead of silently failing (#2645). +- Azure storage access key can be taken from the environment if not explicitly + provided to AzureSession (#2637). +- Skip empty parts of PATH on Windows when adding DLL directories (#2626). +- get_data_window is fixed for the case where the nodata value is nan (#2629). +- Ensure that GTiff, not COG, driver is used by default for TIFFs (#2634). + +1.3.3 (2022-10-19) +------------------ + +Packaging: + +The rasterio._loading module, which supports DLL loading on Windows, +has been moved into __init__.py and is no longer used anywhere else +(#2594). + +Bug fixes: + +- GeoTIFF profiles combining tiled=False and a defined blockysize are now + supported (#2599). +- URLs with // in the query string are now properly parsed (#2603). +- Rasterio's Python file VSI plugin now sets the position of the underlying + stream to 0 on close, resolving #2550. + 1.3.2 (2022-08-19) ------------------ diff -Nru rasterio-1.3.2/ci/gdal-compile.sh rasterio-1.3.4/ci/gdal-compile.sh --- rasterio-1.3.2/ci/gdal-compile.sh 1970-01-01 00:00:00.000000000 +0000 +++ rasterio-1.3.4/ci/gdal-compile.sh 2022-11-16 19:51:17.000000000 +0000 @@ -0,0 +1,33 @@ +#!/bin/bash +# Example usage: +# GDAL_DIR=$PWD/gdal bash gdal_compile.sh 3.6.0rc2 +set -e +pushd . +echo "Building GDAL ($1) from source..." +BUILD_GDAL_DIR=gdal-${1:0:5} +# Download PROJ +if [[ $1 == "git" ]]; then + git clone https://github.com/OSGeo/GDAL.git ${BUILD_GDAL_DIR} +else + curl https://download.osgeo.org/gdal/${1:0:5}/gdal-$1.tar.gz > ${BUILD_GDAL_DIR}.tar.gz + tar zxf ${BUILD_GDAL_DIR}.tar.gz + rm ${BUILD_GDAL_DIR}.tar.gz +fi +cd ${BUILD_GDAL_DIR} +mkdir build +cd build +# build using cmake +cmake .. \ + -DCMAKE_INSTALL_PREFIX=$GDAL_DIR \ + -DBUILD_SHARED_LIBS=ON \ + -DCMAKE_BUILD_TYPE=Release \ + -DOGR_BUILD_OPTIONAL_DRIVERS=OFF \ + -DBUILD_CSHARP_BINDINGS=OFF \ + -DBUILD_PYTHON_BINDINGS=OFF \ + -DBUILD_JAVA_BINDINGS=OFF +cmake --build . -j$(nproc) +cmake --install . +# cleanup +cd ../.. +rm -rf ${BUILD_GDAL_DIR} +popd diff -Nru rasterio-1.3.2/debian/changelog rasterio-1.3.4/debian/changelog --- rasterio-1.3.2/debian/changelog 2022-08-20 16:00:00.000000000 +0000 +++ rasterio-1.3.4/debian/changelog 2022-12-05 08:00:00.000000000 +0000 @@ -1,8 +1,43 @@ -rasterio (1.3.2-2~jammy0) jammy; urgency=medium +rasterio (1.3.4-1~jammy0) jammy; urgency=medium * No change rebuild for Jammy. - -- Angelos Tzotsos Sat, 20 Aug 2022 19:00:00 +0300 + -- Angelos Tzotsos Mon, 05 Dec 2022 10:00:00 +0200 + +rasterio (1.3.4-1) unstable; urgency=medium + + * Team upload. + * New upstream release. + * Drop GDAL 3.6.0 patch, fixed upstream. + * Ignore test_warp.py, requires network. + * Add patch to fix spelling errors. + + -- Bas Couwenberg Thu, 17 Nov 2022 05:29:22 +0100 + +rasterio (1.3.3-2) unstable; urgency=medium + + * Team upload. + * Add patch to fix FTBFS with GDAL 3.6.0. + (closes: #1023480) + + -- Bas Couwenberg Sun, 06 Nov 2022 09:52:17 +0100 + +rasterio (1.3.3-1) unstable; urgency=medium + + * Team upload. + * New upstream release. + * Use pybuild-plugin-pyproject instead of python3-setuptools. + * Drop proj-9.1.0.patch, fixed upstream. + + -- Bas Couwenberg Thu, 20 Oct 2022 05:25:50 +0200 + +rasterio (1.3.2-3) unstable; urgency=medium + + * Team upload. + * Add patch to fix FTBFS with PROJ 9.1.0. + (closes: #1020074) + + -- Bas Couwenberg Sun, 18 Sep 2022 09:14:30 +0200 rasterio (1.3.2-2) unstable; urgency=medium diff -Nru rasterio-1.3.2/debian/control rasterio-1.3.4/debian/control --- rasterio-1.3.2/debian/control 2022-07-06 03:18:34.000000000 +0000 +++ rasterio-1.3.4/debian/control 2022-11-17 04:29:22.000000000 +0000 @@ -8,6 +8,7 @@ libgdal-dev, gdal-bin, cython3, + pybuild-plugin-pyproject, python3-affine (>= 1.3.0), python3-all, python3-all-dev, diff -Nru rasterio-1.3.2/debian/patches/series rasterio-1.3.4/debian/patches/series --- rasterio-1.3.2/debian/patches/series 2022-07-06 03:40:49.000000000 +0000 +++ rasterio-1.3.4/debian/patches/series 2022-11-17 04:29:22.000000000 +0000 @@ -1 +1,2 @@ 0001-Rename-rio-to-rasterio-Closes-788463.patch +spelling-errors.patch diff -Nru rasterio-1.3.2/debian/patches/spelling-errors.patch rasterio-1.3.4/debian/patches/spelling-errors.patch --- rasterio-1.3.2/debian/patches/spelling-errors.patch 1970-01-01 00:00:00.000000000 +0000 +++ rasterio-1.3.4/debian/patches/spelling-errors.patch 2022-11-17 04:29:22.000000000 +0000 @@ -0,0 +1,25 @@ +Description: Fix spelling errors. + * Unkown -> Unknown +Author: Bas Couwenberg +Forwarded: https://github.com/rasterio/rasterio/pull/2659 + +--- a/rasterio/_err.pyx ++++ b/rasterio/_err.pyx +@@ -220,7 +220,7 @@ cdef void *exc_wrap_pointer(void *ptr) e + if exc: + raise exc + raise SystemError( +- f"Unkown GDAL Error. To debug: {_GDAL_DEBUG_DOCS}" ++ f"Unknown GDAL Error. To debug: {_GDAL_DEBUG_DOCS}" + ) + CPLErrorReset() + return ptr +@@ -237,7 +237,7 @@ cdef VSILFILE *exc_wrap_vsilfile(VSILFIL + if exc: + raise exc + raise SystemError( +- f"Unkown GDAL Error. To debug: {_GDAL_DEBUG_DOCS}" ++ f"Unknown GDAL Error. To debug: {_GDAL_DEBUG_DOCS}" + ) + CPLErrorReset() + return vsifile diff -Nru rasterio-1.3.2/debian/rules rasterio-1.3.4/debian/rules --- rasterio-1.3.2/debian/rules 2022-08-20 04:48:31.000000000 +0000 +++ rasterio-1.3.4/debian/rules 2022-11-17 04:29:22.000000000 +0000 @@ -34,6 +34,7 @@ --ignore tests/test_rio_stack.py \ --ignore tests/test_rio_warp.py \ --ignore tests/test_session.py \ + --ignore tests/test_warp.py \ --ignore tests/test_warpedvrt.py %: diff -Nru rasterio-1.3.2/.github/workflows/test_gdal_latest.yaml rasterio-1.3.4/.github/workflows/test_gdal_latest.yaml --- rasterio-1.3.2/.github/workflows/test_gdal_latest.yaml 1970-01-01 00:00:00.000000000 +0000 +++ rasterio-1.3.4/.github/workflows/test_gdal_latest.yaml 2022-11-16 19:51:17.000000000 +0000 @@ -0,0 +1,84 @@ +name: Test GDAL Latest + +on: + push: + branches: [ main, 'maint-*' ] + schedule: + - cron: '0 0 * * 0' + pull_request: # also build on PRs touching this file + paths: + - ".github/workflows/test_gdal_latest.yaml" + - "ci/gdal-compile.sh" + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} + cancel-in-progress: true + +jobs: + test_gdal_latest: + name: GDAL Latest + runs-on: ubuntu-latest + container: osgeo/proj:9.1.0 + env: + GDAL_DIR: ${{ github.workspace }}/gdal_install + GDAL_DATA: ${{ github.workspace }}/gdal_install/share/gdal + LD_LIBRARY_PATH: "${{ github.workspace }}/gdal_install/lib/:${LD_LIBRARY_PATH}" + steps: + - uses: actions/checkout@v3 + - name: Update + run: | + apt-get update + apt-get -y install software-properties-common + add-apt-repository -y ppa:deadsnakes/ppa + apt-get update + + - name: Set up Python + run: | + apt-get install -y --no-install-recommends \ + python3.10 \ + python3.10-dev \ + python3.10-venv \ + python3-pip \ + g++ + + - name: Install GDAL + shell: bash + run: | + apt-get update + apt-get install -qq \ + libcurl4-gnutls-dev \ + libgeos-dev \ + libjpeg-dev \ + libnetcdf-dev \ + libhdf4-alt-dev \ + libhdf5-serial-dev \ + libssl-dev \ + libsqlite3-dev \ + libexpat-dev \ + libxerces-c-dev \ + libpng-dev \ + libopenjp2-7-dev \ + libzstd-dev \ + libwebp-dev \ + cmake \ + curl \ + git + bash ci/gdal-compile.sh git + + - name: Install dependencies + run: | + export PATH="${GDAL_DIR}/bin/:${PATH}" + python3.10 -m venv testenv + . testenv/bin/activate + python -m pip install --upgrade pip + python -m pip wheel -r requirements-dev.txt + python -m pip install -r requirements-dev.txt + python setup.py clean + python -m pip install --no-deps --force-reinstall --no-use-pep517 -e .[test] + + - name: Test + shell: bash + run: | + export PATH="${GDAL_DIR}/bin/:${PATH}" + . testenv/bin/activate + python -m pytest -v -m "not wheel" -rxXs --cov rasterio --cov-report term-missing diff -Nru rasterio-1.3.2/.github/workflows/tests.yaml rasterio-1.3.4/.github/workflows/tests.yaml --- rasterio-1.3.2/.github/workflows/tests.yaml 2022-08-19 15:45:01.000000000 +0000 +++ rasterio-1.3.4/.github/workflows/tests.yaml 2022-11-16 19:51:17.000000000 +0000 @@ -37,7 +37,7 @@ fail-fast: false matrix: python-version: ['3.9', '3.10'] - gdal-version: ['3.5.0', '3.4.3'] + gdal-version: ['3.5.2', '3.4.3'] include: - python-version: '3.8' gdal-version: '3.3.3' diff -Nru rasterio-1.3.2/.gitignore rasterio-1.3.4/.gitignore --- rasterio-1.3.2/.gitignore 2022-08-19 15:45:01.000000000 +0000 +++ rasterio-1.3.4/.gitignore 2022-11-16 19:51:17.000000000 +0000 @@ -88,3 +88,4 @@ .ipynb_checkpoints .pytest_cache *.ipynb +mprofile*.dat diff -Nru rasterio-1.3.2/pyproject.toml rasterio-1.3.4/pyproject.toml --- rasterio-1.3.2/pyproject.toml 2022-08-19 15:45:01.000000000 +0000 +++ rasterio-1.3.4/pyproject.toml 2022-11-16 19:51:17.000000000 +0000 @@ -1,5 +1,5 @@ [build-system] -requires = ["setuptools", "wheel", "cython~=0.29.24", "oldest-supported-numpy"] +requires = ["setuptools", "wheel", "cython>=0.29.29", "oldest-supported-numpy"] [tool.pytest.ini_options] markers = [ diff -Nru rasterio-1.3.2/rasterio/_base.pyx rasterio-1.3.4/rasterio/_base.pyx --- rasterio-1.3.2/rasterio/_base.pyx 2022-08-19 15:45:01.000000000 +0000 +++ rasterio-1.3.4/rasterio/_base.pyx 2022-11-16 19:51:17.000000000 +0000 @@ -148,6 +148,11 @@ for extension in extensions.split(): driver_extensions[extension] = drivername + + # ensure default driver for tif to be GTiff instead of COG + driver_extensions.update( + {'tif': 'GTiff', 'tiff': 'GTiff'} + ) return driver_extensions @@ -1023,7 +1028,7 @@ blockysize=self.block_shapes[0][0], tiled=True) else: - m.update(tiled=False) + m.update(blockysize=self.block_shapes[0][0], tiled=False) if self.compression: m['compress'] = self.compression.name if self.interleaving: diff -Nru rasterio-1.3.2/rasterio/drivers.py rasterio-1.3.4/rasterio/drivers.py --- rasterio-1.3.2/rasterio/drivers.py 2022-08-19 15:45:01.000000000 +0000 +++ rasterio-1.3.4/rasterio/drivers.py 2022-11-16 19:51:17.000000000 +0000 @@ -11,10 +11,8 @@ """ import os -import rasterio._loading -with rasterio._loading.add_gdal_dll_directories(): - from rasterio._base import _raster_driver_extensions - from rasterio.env import GDALVersion, ensure_env +from rasterio._base import _raster_driver_extensions +from rasterio.env import GDALVersion, ensure_env # Methods like `rasterio.open()` may use this blacklist to preempt # combinations of drivers and file modes. diff -Nru rasterio-1.3.2/rasterio/env.py rasterio-1.3.4/rasterio/env.py --- rasterio-1.3.2/rasterio/env.py 2022-08-19 15:45:01.000000000 +0000 +++ rasterio-1.3.4/rasterio/env.py 2022-11-16 19:51:17.000000000 +0000 @@ -11,15 +11,17 @@ import attr -import rasterio._loading -with rasterio._loading.add_gdal_dll_directories(): - from rasterio._env import ( - GDALEnv, get_gdal_config, set_gdal_config, - GDALDataFinder, PROJDataFinder, set_proj_data_search_path) - from rasterio._version import gdal_version - from rasterio.errors import ( - EnvError, GDALVersionError, RasterioDeprecationWarning) - from rasterio.session import Session, DummySession +from rasterio._env import ( + GDALEnv, + get_gdal_config, + set_gdal_config, + GDALDataFinder, + PROJDataFinder, + set_proj_data_search_path, +) +from rasterio._version import gdal_version +from rasterio.errors import EnvError, GDALVersionError, RasterioDeprecationWarning +from rasterio.session import Session, DummySession class ThreadEnv(threading.local): diff -Nru rasterio-1.3.2/rasterio/_err.pyx rasterio-1.3.4/rasterio/_err.pyx --- rasterio-1.3.2/rasterio/_err.pyx 2022-08-19 15:45:01.000000000 +0000 +++ rasterio-1.3.4/rasterio/_err.pyx 2022-11-16 19:51:17.000000000 +0000 @@ -10,6 +10,10 @@ log = logging.getLogger(__name__) +_GDAL_DEBUG_DOCS = ( + "https://rasterio.readthedocs.io/en/latest/topics/errors.html" + "#debugging-internal-gdal-functions" +) class CPLE_BaseError(Exception): """Base CPL error class @@ -215,6 +219,9 @@ exc = exc_check() if exc: raise exc + raise SystemError( + f"Unkown GDAL Error. To debug: {_GDAL_DEBUG_DOCS}" + ) CPLErrorReset() return ptr @@ -229,5 +236,8 @@ exc = exc_check() if exc: raise exc + raise SystemError( + f"Unkown GDAL Error. To debug: {_GDAL_DEBUG_DOCS}" + ) CPLErrorReset() return vsifile diff -Nru rasterio-1.3.2/rasterio/features.py rasterio-1.3.4/rasterio/features.py --- rasterio-1.3.2/rasterio/features.py 2022-08-19 15:45:01.000000000 +0000 +++ rasterio-1.3.4/rasterio/features.py 2022-11-16 19:51:17.000000000 +0000 @@ -7,20 +7,22 @@ import numpy as np -import rasterio._loading - -with rasterio._loading.add_gdal_dll_directories(): - import rasterio - from rasterio.dtypes import validate_dtype, can_cast_dtype, get_minimum_dtype, _getnpdtype - from rasterio.enums import MergeAlg - from rasterio.env import ensure_env, GDALVersion - from rasterio.errors import ShapeSkipWarning - from rasterio._features import _shapes, _sieve, _rasterize, _bounds - from rasterio import warp - from rasterio.rio.helpers import coords - from rasterio.transform import Affine - from rasterio.transform import IDENTITY, guard_transform, rowcol - from rasterio.windows import Window +import rasterio +from rasterio.dtypes import ( + validate_dtype, + can_cast_dtype, + get_minimum_dtype, + _getnpdtype, +) +from rasterio.enums import MergeAlg +from rasterio.env import ensure_env, GDALVersion +from rasterio.errors import ShapeSkipWarning +from rasterio._features import _shapes, _sieve, _rasterize, _bounds +from rasterio import warp +from rasterio.rio.helpers import coords +from rasterio.transform import Affine +from rasterio.transform import IDENTITY, guard_transform, rowcol +from rasterio.windows import Window log = logging.getLogger(__name__) diff -Nru rasterio-1.3.2/rasterio/_filepath.pyx rasterio-1.3.4/rasterio/_filepath.pyx --- rasterio-1.3.2/rasterio/_filepath.pyx 2022-08-19 15:45:01.000000000 +0000 +++ rasterio-1.3.4/rasterio/_filepath.pyx 2022-11-16 19:51:17.000000000 +0000 @@ -130,7 +130,7 @@ cdef vsi_l_offset filepath_tell(void *pFile) with gil: cdef object file_wrapper = pFile cdef object file_obj = file_wrapper._file_obj - cdef int pos = file_obj.tell() + cdef long pos = file_obj.tell() return pos @@ -155,7 +155,9 @@ cdef int filepath_close(void *pFile) except -1 with gil: # Optional cdef object file_wrapper = pFile - del _FILESYSTEM_INFO[file_wrapper._filepath_path] + cdef object file_obj = file_wrapper._file_obj + file_obj.seek(0) + _ = _FILESYSTEM_INFO.pop(file_wrapper._filepath_path, None) return 0 diff -Nru rasterio-1.3.2/rasterio/fill.py rasterio-1.3.4/rasterio/fill.py --- rasterio-1.3.2/rasterio/fill.py 2022-08-19 15:45:01.000000000 +0000 +++ rasterio-1.3.4/rasterio/fill.py 2022-11-16 19:51:17.000000000 +0000 @@ -1,15 +1,12 @@ """Fill holes in raster dataset by interpolation from the edges.""" -import rasterio._loading -with rasterio._loading.add_gdal_dll_directories(): - - import rasterio - from rasterio._fill import _fillnodata - from rasterio.env import ensure_env - from rasterio import dtypes - from numpy.ma import MaskedArray +import rasterio +from rasterio._fill import _fillnodata +from rasterio.env import ensure_env +from rasterio import dtypes + @ensure_env def fillnodata( diff -Nru rasterio-1.3.2/rasterio/gdal.pxi rasterio-1.3.4/rasterio/gdal.pxi --- rasterio-1.3.2/rasterio/gdal.pxi 2022-08-19 15:45:01.000000000 +0000 +++ rasterio-1.3.4/rasterio/gdal.pxi 2022-11-16 19:51:17.000000000 +0000 @@ -65,7 +65,7 @@ cdef extern from "cpl_vsi.h" nogil: - ctypedef int vsi_l_offset + ctypedef unsigned long long vsi_l_offset ctypedef FILE VSILFILE ctypedef stat VSIStatBufL ctypedef enum VSIRangeStatus: diff -Nru rasterio-1.3.2/rasterio/__init__.py rasterio-1.3.4/rasterio/__init__.py --- rasterio-1.3.2/rasterio/__init__.py 2022-08-19 15:45:01.000000000 +0000 +++ rasterio-1.3.4/rasterio/__init__.py 2022-11-16 19:51:17.000000000 +0000 @@ -1,61 +1,87 @@ """Rasterio""" from collections import namedtuple -from contextlib import ExitStack +import glob import logging from logging import NullHandler import os +import platform +import sys import warnings -import rasterio._loading -with rasterio._loading.add_gdal_dll_directories(): - from rasterio._show_versions import show_versions - from rasterio._version import gdal_version, get_geos_version, get_proj_version - from rasterio.crs import CRS - from rasterio.drivers import driver_from_extension, is_blacklisted - from rasterio.dtypes import ( - bool_, - ubyte, - sbyte, - uint8, - int8, - uint16, - int16, - uint32, - int32, - int64, - uint64, - float32, - float64, - complex_, - check_dtype, - complex_int16, - ) - from rasterio.env import ensure_env_with_credentials, Env, env_ctx_if_needed - from rasterio.errors import RasterioIOError, DriverCapabilityError, RasterioDeprecationWarning - from rasterio.io import ( - DatasetReader, get_writer_for_path, get_writer_for_driver, MemoryFile) - from rasterio.profiles import default_gtiff_profile - from rasterio.transform import Affine, guard_transform - from rasterio._path import _parse_path - - # These modules are imported from the Cython extensions, but are also import - # here to help tools like cx_Freeze find them automatically - import rasterio._err - import rasterio.coords - import rasterio.enums - import rasterio._path - - try: - from rasterio.io import FilePath - have_vsi_plugin = True - except ImportError: - class FilePath: - pass - have_vsi_plugin = False +# On Windows we must explicitly register the directories that contain +# the GDAL and supporting DLLs starting with Python 3.8. Presently, we +# support the rasterio-wheels location or directories on the system's +# executable path. +if platform.system() == "Windows": + _whl_dir = os.path.join(os.path.dirname(__file__), ".libs") + if os.path.exists(_whl_dir): + os.add_dll_directory(_whl_dir) + else: + if "PATH" in os.environ: + for p in os.environ["PATH"].split(os.pathsep): + if p and glob.glob(os.path.join(p, "gdal*.dll")): + os.add_dll_directory(p) + + +from rasterio._show_versions import show_versions +from rasterio._version import gdal_version, get_geos_version, get_proj_version +from rasterio.crs import CRS +from rasterio.drivers import driver_from_extension, is_blacklisted +from rasterio.dtypes import ( + bool_, + ubyte, + sbyte, + uint8, + int8, + uint16, + int16, + uint32, + int32, + int64, + uint64, + float32, + float64, + complex_, + check_dtype, + complex_int16, +) +from rasterio.env import ensure_env_with_credentials, Env +from rasterio.errors import ( + RasterioIOError, + DriverCapabilityError, + RasterioDeprecationWarning, +) +from rasterio.io import ( + DatasetReader, + get_writer_for_path, + get_writer_for_driver, + MemoryFile, +) +from rasterio.profiles import default_gtiff_profile +from rasterio.transform import Affine, guard_transform +from rasterio._path import _parse_path + +# These modules are imported from the Cython extensions, but are also import +# here to help tools like cx_Freeze find them automatically +import rasterio._err +import rasterio.coords +import rasterio.enums +import rasterio._path + +try: + from rasterio.io import FilePath + + have_vsi_plugin = True +except ImportError: + + class FilePath: + pass + + have_vsi_plugin = False __all__ = ['band', 'open', 'pad', 'Env', 'CRS'] -__version__ = "1.3.2" +__version__ = "1.3.4" __gdal_version__ = gdal_version() __proj_version__ = ".".join([str(version) for version in get_proj_version()]) __geos_version__ = ".".join([str(version) for version in get_geos_version()]) @@ -68,6 +94,7 @@ log = logging.getLogger(__name__) log.addHandler(NullHandler()) + # Remove this in 1.4.0 (see comment on gh-2423). def parse_path(path): warnings.warn( diff -Nru rasterio-1.3.2/rasterio/io.py rasterio-1.3.4/rasterio/io.py --- rasterio-1.3.2/rasterio/io.py 2022-08-19 15:45:01.000000000 +0000 +++ rasterio-1.3.4/rasterio/io.py 2022-11-16 19:51:17.000000000 +0000 @@ -5,21 +5,22 @@ import logging -import rasterio._loading -with rasterio._loading.add_gdal_dll_directories(): - from rasterio._base import ( - get_dataset_driver, driver_can_create, driver_can_create_copy) - from rasterio._io import ( - DatasetReaderBase, DatasetWriterBase, BufferedDatasetWriterBase, - MemoryFileBase) - from rasterio.windows import WindowMethodsMixin - from rasterio.env import ensure_env - from rasterio.transform import TransformMethodsMixin - from rasterio._path import _UnparsedPath - try: - from rasterio._filepath import FilePathBase - except ImportError: - FilePathBase = object +from rasterio._base import get_dataset_driver, driver_can_create, driver_can_create_copy +from rasterio._io import ( + DatasetReaderBase, + DatasetWriterBase, + BufferedDatasetWriterBase, + MemoryFileBase, +) +from rasterio.windows import WindowMethodsMixin +from rasterio.env import ensure_env +from rasterio.transform import TransformMethodsMixin +from rasterio._path import _UnparsedPath + +try: + from rasterio._filepath import FilePathBase +except ImportError: + FilePathBase = object log = logging.getLogger(__name__) diff -Nru rasterio-1.3.2/rasterio/_io.pyx rasterio-1.3.4/rasterio/_io.pyx --- rasterio-1.3.2/rasterio/_io.pyx 2022-08-19 15:45:01.000000000 +0000 +++ rasterio-1.3.4/rasterio/_io.pyx 2022-11-16 19:51:17.000000000 +0000 @@ -356,7 +356,7 @@ for k, v in kwargs.items(): if k.lower() in ['affine']: continue - elif k in ['BLOCKXSIZE', 'BLOCKYSIZE'] and not tiled: + elif k in ['BLOCKXSIZE'] and not tiled: continue # Special cases for enums and tuples. diff -Nru rasterio-1.3.2/rasterio/_loading.py rasterio-1.3.4/rasterio/_loading.py --- rasterio-1.3.2/rasterio/_loading.py 2022-08-19 15:45:01.000000000 +0000 +++ rasterio-1.3.4/rasterio/_loading.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -import glob -import os -import logging -import contextlib -import platform -import sys - -log = logging.getLogger(__name__) -log.addHandler(logging.NullHandler()) - -# With Python >= 3.8 on Windows directories in PATH are not automatically -# searched for DLL dependencies and must be added manually with -# os.add_dll_directory. -# see https://github.com/Toblerity/Fiona/issues/851 - -@contextlib.contextmanager -def add_gdal_dll_directories(): - dll_dirs = [] - if platform.system() == 'Windows' and sys.version_info >= (3, 8): - dll_directory = os.path.join(os.path.dirname(__file__), '.libs') - if os.path.exists(dll_directory): - dll_dirs.append(os.add_dll_directory(dll_directory)) - else: - if 'PATH' in os.environ: - for p in os.environ['PATH'].split(os.pathsep): - if glob.glob(os.path.join(p, 'gdal*.dll')): - os.add_dll_directory(p) - try: - yield None - finally: - for dll_dir in dll_dirs: - dll_dir.close() diff -Nru rasterio-1.3.2/rasterio/mask.py rasterio-1.3.4/rasterio/mask.py --- rasterio-1.3.2/rasterio/mask.py 2022-08-19 15:45:01.000000000 +0000 +++ rasterio-1.3.4/rasterio/mask.py 2022-11-16 19:51:17.000000000 +0000 @@ -5,10 +5,8 @@ import numpy -import rasterio._loading -with rasterio._loading.add_gdal_dll_directories(): - from rasterio.errors import WindowError - from rasterio.features import geometry_mask, geometry_window +from rasterio.errors import WindowError +from rasterio.features import geometry_mask, geometry_window logger = logging.getLogger(__name__) diff -Nru rasterio-1.3.2/rasterio/merge.py rasterio-1.3.4/rasterio/merge.py --- rasterio-1.3.2/rasterio/merge.py 2022-08-19 15:45:01.000000000 +0000 +++ rasterio-1.3.4/rasterio/merge.py 2022-11-16 19:51:17.000000000 +0000 @@ -9,15 +9,12 @@ import numpy as np -import rasterio._loading - -with rasterio._loading.add_gdal_dll_directories(): - import rasterio - from rasterio.coords import disjoint_bounds - from rasterio.enums import Resampling - from rasterio.errors import RasterioDeprecationWarning - from rasterio import windows - from rasterio.transform import Affine +import rasterio +from rasterio.coords import disjoint_bounds +from rasterio.enums import Resampling +from rasterio.errors import RasterioDeprecationWarning +from rasterio import windows +from rasterio.transform import Affine logger = logging.getLogger(__name__) diff -Nru rasterio-1.3.2/rasterio/_path.py rasterio-1.3.4/rasterio/_path.py --- rasterio-1.3.2/rasterio/_path.py 2022-08-19 15:45:01.000000000 +0000 +++ rasterio-1.3.4/rasterio/_path.py 2022-11-16 19:51:17.000000000 +0000 @@ -64,7 +64,7 @@ @classmethod def from_uri(cls, uri): parts = urlparse(uri) - path = parts.path + path = pathlib.Path(parts.path).as_posix() if parts.path else parts.path scheme = parts.scheme or None if parts.query: @@ -76,7 +76,7 @@ parts = path.split('!') path = parts.pop() if parts else None archive = parts.pop() if parts else None - return _ParsedPath(pathlib.Path(path).as_posix(), archive, scheme) + return _ParsedPath(path, archive, scheme) @property def name(self): diff -Nru rasterio-1.3.2/rasterio/plot.py rasterio-1.3.4/rasterio/plot.py --- rasterio-1.3.2/rasterio/plot.py 2022-08-19 15:45:01.000000000 +0000 +++ rasterio-1.3.4/rasterio/plot.py 2022-11-16 19:51:17.000000000 +0000 @@ -12,11 +12,9 @@ import numpy as np -import rasterio._loading -with rasterio._loading.add_gdal_dll_directories(): - import rasterio - from rasterio.io import DatasetReader - from rasterio.transform import guard_transform +import rasterio +from rasterio.io import DatasetReader +from rasterio.transform import guard_transform logger = logging.getLogger(__name__) diff -Nru rasterio-1.3.2/rasterio/sample.py rasterio-1.3.4/rasterio/sample.py --- rasterio-1.3.2/rasterio/sample.py 2022-08-19 15:45:01.000000000 +0000 +++ rasterio-1.3.4/rasterio/sample.py 2022-11-16 19:51:17.000000000 +0000 @@ -1,14 +1,13 @@ # Workaround for issue #378. A pure Python generator. +from itertools import zip_longest + import numpy as np -import rasterio._loading -with rasterio._loading.add_gdal_dll_directories(): - from rasterio.enums import MaskFlags - from rasterio.windows import Window - from rasterio.transform import rowcol +from rasterio.enums import MaskFlags +from rasterio.windows import Window +from rasterio.transform import rowcol -from itertools import zip_longest def _grouper(iterable, n, fillvalue=None): "Collect data into non-overlapping fixed-length chunks or blocks" diff -Nru rasterio-1.3.2/rasterio/session.py rasterio-1.3.4/rasterio/session.py --- rasterio-1.3.2/rasterio/session.py 2022-08-19 15:45:01.000000000 +0000 +++ rasterio-1.3.4/rasterio/session.py 2022-11-16 19:51:17.000000000 +0000 @@ -3,9 +3,7 @@ import logging import os -import rasterio._loading -with rasterio._loading.add_gdal_dll_directories(): - from rasterio._path import _parse_path, _UnparsedPath +from rasterio._path import _parse_path, _UnparsedPath log = logging.getLogger(__name__) @@ -565,7 +563,8 @@ """ self.unsigned = bool(os.getenv("AZURE_NO_SIGN_REQUEST", azure_unsigned)) - self.storage_account = os.getenv("AZURE_STORAGE_ACCOUNT", azure_storage_account) + self.storage_account = azure_storage_account or os.getenv("AZURE_STORAGE_ACCOUNT") + self.storage_access_key = azure_storage_access_key or os.getenv("AZURE_STORAGE_ACCESS_KEY") if azure_storage_connection_string: self._creds = { @@ -574,7 +573,7 @@ elif not self.unsigned: self._creds = { "azure_storage_account": self.storage_account, - "azure_storage_access_key": azure_storage_access_key + "azure_storage_access_key": self.storage_access_key } else: self._creds = { diff -Nru rasterio-1.3.2/rasterio/tools.py rasterio-1.3.4/rasterio/tools.py --- rasterio-1.3.2/rasterio/tools.py 2022-08-19 15:45:01.000000000 +0000 +++ rasterio-1.3.4/rasterio/tools.py 2022-11-16 19:51:17.000000000 +0000 @@ -6,10 +6,8 @@ import json -import rasterio._loading -with rasterio._loading.add_gdal_dll_directories(): - import rasterio - from rasterio.features import dataset_features +import rasterio +from rasterio.features import dataset_features class JSONSequenceTool: diff -Nru rasterio-1.3.2/rasterio/transform.py rasterio-1.3.4/rasterio/transform.py --- rasterio-1.3.2/rasterio/transform.py 2022-08-19 15:45:01.000000000 +0000 +++ rasterio-1.3.4/rasterio/transform.py 2022-11-16 19:51:17.000000000 +0000 @@ -6,22 +6,21 @@ import math import numpy as np import sys +import warnings from affine import Affine -import rasterio._loading -with rasterio._loading.add_gdal_dll_directories(): - import rasterio - from rasterio.env import env_ctx_if_needed - from rasterio._transform import ( - _transform_from_gcps, - RPCTransformerBase, - GCPTransformerBase - ) - from rasterio.enums import TransformDirection, TransformMethod - from rasterio.control import GroundControlPoint - from rasterio.rpc import RPC - from rasterio.errors import TransformError, RasterioDeprecationWarning +import rasterio +from rasterio.env import env_ctx_if_needed +from rasterio._transform import ( + _transform_from_gcps, + RPCTransformerBase, + GCPTransformerBase, +) +from rasterio.enums import TransformDirection, TransformMethod +from rasterio.control import GroundControlPoint +from rasterio.rpc import RPC +from rasterio.errors import TransformError, RasterioDeprecationWarning IDENTITY = Affine.identity() GDAL_IDENTITY = IDENTITY.to_gdal() @@ -437,22 +436,22 @@ # shift input coordinates according to offset T = IDENTITY.translation(coff, roff) - temp_rows = [] - temp_cols = [] + offset_rows = [] + offset_cols = [] try: - for pt in zip(cols, rows): - y, x = T * pt - temp_rows.append(y) - temp_cols.append(x) + for colrow in zip(cols, rows): + offset_col, offset_row = T * colrow + offset_rows.append(offset_row) + offset_cols.append(offset_col) - new_ys, new_xs = self._transform( - temp_rows, temp_cols, zs, transform_direction=TransformDirection.forward + new_xs, new_ys = self._transform( + offset_cols, offset_rows, zs, transform_direction=TransformDirection.forward ) - if len(new_ys) == 1 and not AS_ARR: - return (new_ys[0], new_xs[0]) + if len(new_xs) == 1 and not AS_ARR: + return (new_xs[0], new_ys[0]) else: - return (new_ys, new_xs) + return (new_xs, new_ys) except TypeError: raise TransformError("Invalid inputs") diff -Nru rasterio-1.3.2/rasterio/vrt.py rasterio-1.3.4/rasterio/vrt.py --- rasterio-1.3.2/rasterio/vrt.py 2022-08-19 15:45:01.000000000 +0000 +++ rasterio-1.3.4/rasterio/vrt.py 2022-11-16 19:51:17.000000000 +0000 @@ -2,15 +2,13 @@ import xml.etree.ElementTree as ET -import rasterio._loading -with rasterio._loading.add_gdal_dll_directories(): - import rasterio - from rasterio._warp import WarpedVRTReaderBase - from rasterio.dtypes import _gdal_typename - from rasterio.enums import MaskFlags - from rasterio._path import _parse_path - from rasterio.transform import TransformMethodsMixin - from rasterio.windows import WindowMethodsMixin +import rasterio +from rasterio._warp import WarpedVRTReaderBase +from rasterio.dtypes import _gdal_typename +from rasterio.enums import MaskFlags +from rasterio._path import _parse_path +from rasterio.transform import TransformMethodsMixin +from rasterio.windows import WindowMethodsMixin class WarpedVRT(WarpedVRTReaderBase, WindowMethodsMixin, diff -Nru rasterio-1.3.2/rasterio/warp.py rasterio-1.3.4/rasterio/warp.py --- rasterio-1.3.2/rasterio/warp.py 2022-08-19 15:45:01.000000000 +0000 +++ rasterio-1.3.4/rasterio/warp.py 2022-11-16 19:51:17.000000000 +0000 @@ -5,23 +5,21 @@ from affine import Affine import numpy as np -import rasterio._loading -with rasterio._loading.add_gdal_dll_directories(): - import rasterio +import rasterio - from rasterio._base import _transform - from rasterio.crs import CRS - from rasterio.enums import Resampling - from rasterio.env import ensure_env, require_gdal_version - from rasterio.errors import TransformError, RPCError - from rasterio.transform import array_bounds - from rasterio._warp import ( - _calculate_default_transform, - _reproject, - _transform_bounds, - _transform_geom, - SUPPORTED_RESAMPLING - ) +from rasterio._base import _transform +from rasterio.crs import CRS +from rasterio.enums import Resampling +from rasterio.env import ensure_env, require_gdal_version +from rasterio.errors import TransformError, RPCError +from rasterio.transform import array_bounds +from rasterio._warp import ( + _calculate_default_transform, + _reproject, + _transform_bounds, + _transform_geom, + SUPPORTED_RESAMPLING, +) @ensure_env def transform(src_crs, dst_crs, xs, ys, zs=None): diff -Nru rasterio-1.3.2/rasterio/windows.py rasterio-1.3.4/rasterio/windows.py --- rasterio-1.3.2/rasterio/windows.py 2022-08-19 15:45:01.000000000 +0000 +++ rasterio-1.3.4/rasterio/windows.py 2022-11-16 19:51:17.000000000 +0000 @@ -27,10 +27,8 @@ import attr import numpy as np -import rasterio._loading -with rasterio._loading.add_gdal_dll_directories(): - from rasterio.errors import WindowError, RasterioDeprecationWarning - from rasterio.transform import rowcol, guard_transform +from rasterio.errors import WindowError, RasterioDeprecationWarning +from rasterio.transform import rowcol, guard_transform class WindowMethodsMixin: @@ -162,7 +160,10 @@ # Otherwise retrieve mask from array (if it is masked) # Finally try returning a full window (nodata=None and nothing in arr is masked) if nodata is not None: - arr_mask = arr != nodata + if np.isnan(nodata): + arr_mask = ~np.isnan(arr) + else: + arr_mask = arr != nodata elif np.ma.is_masked(arr): arr_mask = ~np.ma.getmask(arr) else: @@ -182,10 +183,10 @@ v.append((nz.min(), nz.max() + 1)) else: v.append((0, 0)) - + if arr_mask.ndim == 1: v.append((0, 0)) - + return Window.from_slices(*v) diff -Nru rasterio-1.3.2/tests/test_dataset.py rasterio-1.3.4/tests/test_dataset.py --- rasterio-1.3.2/tests/test_dataset.py 2022-08-19 15:45:01.000000000 +0000 +++ rasterio-1.3.4/tests/test_dataset.py 2022-11-16 19:51:17.000000000 +0000 @@ -80,3 +80,25 @@ assert stats.max == 255 assert_almost_equal(stats.mean, 29.947726688477) assert_almost_equal(stats.std, 52.340921626611) + + +@pytest.mark.parametrize("blockysize", [1, 2, 3, 7, 61, 62]) +def test_creation_untiled_blockysize(tmp_path, blockysize): + """Check for fix of gh-2599""" + tmpfile = tmp_path / "test.tif" + with rasterio.open( + tmpfile, + "w", + count=1, + height=61, + width=37, + dtype="uint8", + blockysize=blockysize, + tiled=False, + ) as dataset: + pass + + with rasterio.open(tmpfile) as dataset: + assert not dataset.is_tiled + assert dataset.profile["blockysize"] == min(blockysize, 61) + assert dataset.block_shapes[0][0] == min(blockysize, 61) diff -Nru rasterio-1.3.2/tests/test__env.py rasterio-1.3.4/tests/test__env.py --- rasterio-1.3.2/tests/test__env.py 2022-08-19 15:45:01.000000000 +0000 +++ rasterio-1.3.4/tests/test__env.py 2022-11-16 19:51:17.000000000 +0000 @@ -35,14 +35,13 @@ @pytest.fixture def mock_debian(tmpdir): """A fake Debian multi-install system""" - tmpdir.ensure("share/gdal/2.3/header.dxf") - tmpdir.ensure("share/gdal/2.4/header.dxf") - tmpdir.ensure("share/gdal/3.0/header.dxf") tmpdir.ensure("share/gdal/3.1/header.dxf") tmpdir.ensure("share/gdal/3.2/header.dxf") tmpdir.ensure("share/gdal/3.3/header.dxf") tmpdir.ensure("share/gdal/3.4/header.dxf") tmpdir.ensure("share/gdal/3.5/header.dxf") + tmpdir.ensure("share/gdal/3.6/header.dxf") + tmpdir.ensure(f"share/gdal/{gdal_version.major}.{gdal_version.minor}/header.dxf") tmpdir.ensure("share/proj/epsg") return tmpdir diff -Nru rasterio-1.3.2/tests/test_filepath.py rasterio-1.3.4/tests/test_filepath.py --- rasterio-1.3.2/tests/test_filepath.py 2022-08-19 15:45:01.000000000 +0000 +++ rasterio-1.3.4/tests/test_filepath.py 2022-11-16 19:51:17.000000000 +0000 @@ -159,3 +159,26 @@ tifs = [path_rgb_byte_tif, path_rgb_lzw_byte_tif, path_cogeo_tif, path_alpha_tif] * 4 with ThreadPoolExecutor(max_workers=8) as exe: list(exe.map(_open_geotiff, tifs, timeout=5)) + + +def test_python_file_reuse(): + """Test that we can reuse a Python file, see gh-2550.""" + ascii_raster_string = """ncols 5 + nrows 5 + xllcorner 440720.000000000000 + yllcorner 3750120.000000000000 + cellsize 60.000000000000 + nodata_value -99999 + 107 123 132 115 132 + 115 132 107 123 148 + 115 132 140 132 123 + 148 132 123 123 115 + 132 156 132 140 132 + """ + ascii_raster_io = BytesIO(ascii_raster_string.encode("utf-8")) + + with rasterio.open(ascii_raster_io) as rds: + _ = rds.bounds + + with rasterio.open(ascii_raster_io) as rds: + _ = rds.bounds diff -Nru rasterio-1.3.2/tests/test_path.py rasterio-1.3.4/tests/test_path.py --- rasterio-1.3.2/tests/test_path.py 2022-08-19 15:45:01.000000000 +0000 +++ rasterio-1.3.4/tests/test_path.py 2022-11-16 19:51:17.000000000 +0000 @@ -99,6 +99,14 @@ assert _parse_path('GDAL:filepath:varname').path == 'GDAL:filepath:varname' +def test_parse_http_password(): + """Make sure password unmodified GH2602""" + parsed = _parse_path('https://foo.tif?bar=a//b') + assert parsed.path == 'foo.tif?bar=a//b' + assert parsed.archive is None + assert parsed.scheme == 'https' + + @pytest.mark.skipif(sys.platform == 'win32', reason="Checking behavior on posix, not win32") def test_parse_windows_path(monkeypatch): """Return Windows paths unparsed""" diff -Nru rasterio-1.3.2/tests/test_profile.py rasterio-1.3.4/tests/test_profile.py --- rasterio-1.3.2/tests/test_profile.py 2022-08-19 15:45:01.000000000 +0000 +++ rasterio-1.3.4/tests/test_profile.py 2022-11-16 19:51:17.000000000 +0000 @@ -80,10 +80,10 @@ def test_dataset_profile_property_untiled(data, path_rgb_byte_tif): - """An untiled dataset's profile has no block sizes""" + """An untiled dataset's profile has block y sizes""" with rasterio.open(path_rgb_byte_tif) as src: assert 'blockxsize' not in src.profile - assert 'blockysize' not in src.profile + assert src.profile['blockysize'] == 3 assert src.profile['tiled'] is False diff -Nru rasterio-1.3.2/tests/test_session.py rasterio-1.3.4/tests/test_session.py --- rasterio-1.3.2/tests/test_session.py 2022-08-19 15:45:01.000000000 +0000 +++ rasterio-1.3.4/tests/test_session.py 2022-11-16 19:51:17.000000000 +0000 @@ -282,6 +282,16 @@ assert sesh.get_credential_options()['AZURE_STORAGE_CONNECTION_STRING'] == 'AccountName=myaccount;AccountKey=MY_ACCOUNT_KEY' +def test_session_factory_az_env(monkeypatch): + """Get an AzureSession for az:// paths with environment variables""" + monkeypatch.setenv('AZURE_STORAGE_ACCOUNT', 'foo') + monkeypatch.setenv('AZURE_STORAGE_ACCESS_KEY', 'bar') + sesh = Session.from_path("az://lol/wut") + assert isinstance(sesh, AzureSession) + assert sesh.get_credential_options()['AZURE_STORAGE_ACCOUNT'] == 'foo' + assert sesh.get_credential_options()['AZURE_STORAGE_ACCESS_KEY'] == 'bar' + + def test_azure_no_sign_request(monkeypatch): """If AZURE_NO_SIGN_REQUEST is set do not default to azure_unsigned=False""" monkeypatch.setenv('AZURE_NO_SIGN_REQUEST', 'YES') diff -Nru rasterio-1.3.2/tests/test_warp.py rasterio-1.3.4/tests/test_warp.py --- rasterio-1.3.2/tests/test_warp.py 2022-08-19 15:45:01.000000000 +0000 +++ rasterio-1.3.4/tests/test_warp.py 2022-11-16 19:51:17.000000000 +0000 @@ -1208,7 +1208,7 @@ Resampling.med: [437194], Resampling.q1: [436397], Resampling.q3: [438948], - Resampling.sum: [439118], + Resampling.sum: [439118, 439142], # 439142 for GDAL 3.6+ Resampling.rms: [439385], } @@ -1301,7 +1301,7 @@ Resampling.med: [437194], Resampling.q1: [436397], Resampling.q3: [438948], - Resampling.sum: [439118], + Resampling.sum: [439118, 439142], # 439142 for GDAL 3.6+ Resampling.rms: [439385], } @@ -1966,12 +1966,11 @@ import multiprocessing import http.server - PORT = 8000 Handler = functools.partial(RangeRequestErrorHandler, directory=str(data)) - httpd = http.server.HTTPServer(("", PORT), Handler) + httpd = http.server.HTTPServer(("", 0), Handler) p = multiprocessing.Process(target=httpd.serve_forever) p.start() - yield + yield f'{httpd.server_name}:{httpd.server_port}' p.terminate() p.join() @@ -1984,7 +1983,7 @@ """Propagate errors up from ChunkAndWarpMulti and check for a retry.""" with rasterio.open( - "/vsicurl?max_retry=1&retry_delay=.1&url=http://localhost:8000/RGB.byte.tif" + f"/vsicurl?max_retry=1&retry_delay=.1&url=http://{http_error_server}/RGB.byte.tif" ) as src: out = np.zeros((src.count, src.height, src.width), dtype="uint8") @@ -2097,7 +2096,7 @@ @pytest.mark.skipif( - not gdal_version.at_least('3.4'), + not gdal_version.at_least('3.4') or gdal_version.at_least("3.5"), reason="Requires GDAL 3.4.x") def test_issue2353bis(caplog): """Errors left by a successful transformation are cleaned up.""" diff -Nru rasterio-1.3.2/tests/test_windows.py rasterio-1.3.4/tests/test_windows.py --- rasterio-1.3.2/tests/test_windows.py 2022-08-19 15:45:01.000000000 +0000 +++ rasterio-1.3.4/tests/test_windows.py 2022-11-16 19:51:17.000000000 +0000 @@ -508,6 +508,14 @@ assert window == Window.from_slices((1, 3), (0, 3)) +def test_data_window_nodata_nan(): + """Get window of arr with nodata.""" + arr = np.ones((3, 3)) + arr[0, :] = np.nan + window = get_data_window(arr, nodata=np.nan) + assert window == Window.from_slices((1, 3), (0, 3)) + + def test_data_window_novalid(): """Get window of arr with nodata.""" arr = np.ones((3, 3))