Skip to content

Commit

Permalink
🚨 Setup CI to run linting using cargo clippy (#22)
Browse files Browse the repository at this point in the history
* 👷 Setup CI to run linting using cargo clippy

Run `cargo clippy --all-targets --all-features` on Continuous Integration on every Pull Request and push to main. Adapted from https://doc.rust-lang.org/stable/clippy/continuous_integration/github_actions.html

* 🚨 Fix error: useless conversion to the same type

* ✏️ Fix typo with missing backtick

* 🚨 Rename PyCogReader's `to_numpy` to `as_numpy`

Fixes `error: methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference`. Xref https://rust-lang.github.io/rust-clippy/master/index.html#wrong_self_convention

* 🚨 Fix needless_lifetimes

Xref https://rust-lang.github.io/rust-clippy/stable/index.html#/needless_lifetimes

* 🚨 Allow clippy::type_complexity on xy_coords

Silence `error: very complex type used. Consider factoring parts into `type` definitions`. Xref https://rust-lang.github.io/rust-clippy/stable/index.html#/type_complexity

* 🚚 More to_numpy to as_numpy renames

Missed a few more method renames of `to_numpy` to `as_numpy` in commit ef4cc71.
weiji14 authored Jan 3, 2025
1 parent d5e3b6c commit ee77d4f
Showing 5 changed files with 43 additions and 15 deletions.
29 changes: 29 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Run linters
#
# Lint Rust code using cargo clippy. Apply static analysis rules to catch common
# mistakes and improves code style.

name: Lint

on:
push:
branches: ["main"]
pull_request:
types: [opened, reopened, synchronize]
branches: ["main"]

# Make sure CI fails on all warnings, including Clippy lints
env:
CARGO_TERM_COLOR: always
RUSTFLAGS: "-Dwarnings"

jobs:
clippy_check:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Run Clippy
run: cargo clippy --all-targets --all-features
2 changes: 1 addition & 1 deletion python/cog3pio/xarray_backend.py
Original file line number Diff line number Diff line change
@@ -31,7 +31,7 @@ def open_dataset(
) -> xr.Dataset:
reader = CogReader(path=filename_or_obj)

array: np.ndarray = reader.to_numpy()
array: np.ndarray = reader.as_numpy()
x_coords, y_coords = reader.xy_coords()

channels, height, width = array.shape
8 changes: 4 additions & 4 deletions python/tests/test_io_geotiff.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
"""
Test I/O on GeoTIFF files.
"""

import os
import tempfile
import urllib.request

import numpy as np
import pytest

from cog3pio import CogReader, read_geotiff


@@ -117,14 +117,14 @@ def test_read_geotiff_unsupported_dtype():
)


def test_CogReader_to_numpy():
def test_CogReader_as_numpy():
"""
Ensure that the CogReader class's `to_numpy` method produces a numpy.ndarray output.
Ensure that the CogReader class's `as_numpy` method produces a numpy.ndarray output.
"""
reader = CogReader(
path="https://github.com/rasterio/rasterio/raw/1.3.9/tests/data/float32.tif"
)
array = reader.to_numpy()
array = reader.as_numpy()
assert array.shape == (1, 2, 3) # band, height, width
np.testing.assert_equal(
actual=array,
12 changes: 5 additions & 7 deletions src/io/geotiff.rs
Original file line number Diff line number Diff line change
@@ -79,11 +79,9 @@ impl<R: Read + Seek> CogReader<R> {
};

// Put image pixel data into an ndarray
let array_data: Array3<T> = Array3::from_shape_vec(
(num_bands, height as usize, width as usize),
image_data.into(),
)
.map_err(|_| TiffFormatError::InconsistentSizesEncountered)?;
let array_data: Array3<T> =
Array3::from_shape_vec((num_bands, height as usize, width as usize), image_data)
.map_err(|_| TiffFormatError::InconsistentSizesEncountered)?;

Ok(array_data)
}
@@ -97,8 +95,8 @@ impl<R: Read + Seek> CogReader<R> {
/// | 1 | | 0 0 1 | | 1 |
/// ```
///
/// where (`x'` and `y'`) are world coordinates, and (`x`, `y) are the pixel's image
/// coordinates. Letters a to f represent:
/// where (`x'` and `y'`) are world coordinates, and (`x`, `y`) are the pixel's
/// image coordinates. Letters a to f represent:
///
/// - `a` - width of a pixel (x-resolution)
/// - `b` - row rotation (typically zero)
7 changes: 4 additions & 3 deletions src/python/adapters.rs
Original file line number Diff line number Diff line change
@@ -60,7 +60,7 @@ impl PyCogReader {
/// -------
/// array : np.ndarray
/// 3D array of shape (band, height, width) containing the GeoTIFF pixel data.
fn to_numpy<'py>(&mut self, py: Python<'py>) -> PyResult<Bound<'py, PyArray3<f32>>> {
fn as_numpy<'py>(&mut self, py: Python<'py>) -> PyResult<Bound<'py, PyArray3<f32>>> {
let array_data: Array3<f32> = self
.inner
.ndarray()
@@ -71,6 +71,7 @@ impl PyCogReader {
}

/// Get x and y coordinates as numpy.ndarray
#[allow(clippy::type_complexity)]
fn xy_coords<'py>(
&mut self,
py: Python<'py>,
@@ -142,7 +143,7 @@ fn read_geotiff_py<'py>(path: &str, py: Python<'py>) -> PyResult<Bound<'py, PyAr
let mut reader = PyCogReader::new(path)?;

// Decode TIFF into numpy ndarray
let array_data = reader.to_numpy(py)?;
let array_data = reader.as_numpy(py)?;

Ok(array_data)
}
@@ -151,7 +152,7 @@ fn read_geotiff_py<'py>(path: &str, py: Python<'py>) -> PyResult<Bound<'py, PyAr
/// the `lib.name` setting in the `Cargo.toml`, else Python will not be able to
/// import the module.
#[pymodule]
fn cog3pio<'py>(_py: Python, m: &Bound<'py, PyModule>) -> PyResult<()> {
fn cog3pio(_py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> {
// Register Python classes
m.add_class::<PyCogReader>()?;
// Register Python functions

0 comments on commit ee77d4f

Please sign in to comment.