Skip to content

Commit e572054

Browse files
merge develop into feature branch
2 parents 8d0117b + e0c01e9 commit e572054

6 files changed

Lines changed: 135 additions & 16 deletions

File tree

.github/workflows/run_tests.yml

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,25 @@ on:
1010
secrets:
1111
codecov_token:
1212
required: true
13+
EARTHDATA_USERNAME:
14+
description: 'NASA Earthdata username'
15+
required: true
16+
EARTHDATA_PASSWORD:
17+
description: 'NASA Earthdata password'
18+
required: true
1319
workflow_dispatch:
1420

1521
jobs:
1622
build_and_test:
1723
runs-on: ubuntu-latest
1824
strategy:
1925
matrix:
20-
python-version: [ '3.10', '3.11', '3.12', '3.13' ]
26+
python-version: [ '3.11', '3.12', '3.13', '3.14' ]
2127

2228
name: Python ${{ matrix.python-version }} tests
2329
steps:
2430
- name: Checkout repository with LFS
2531
uses: actions/checkout@v5
26-
with:
27-
lfs: 'true'
2832

2933
- name: Set up Python
3034
uses: actions/setup-python@v5
@@ -42,12 +46,27 @@ jobs:
4246
- name: Run linting
4347
run: uv run ruff check ncompare
4448

45-
- name: Run tests and collect coverage
49+
- name: Run unit tests with coverage
50+
run: |
51+
uv run pytest --python ${{ matrix.python-version }} -v -m "not integration" --cov=ncompare --cov-report=
52+
53+
- name: Run integration tests with coverage
54+
env:
55+
EARTHDATA_USERNAME: ${{ secrets.EARTHDATA_USERNAME }}
56+
EARTHDATA_PASSWORD: ${{ secrets.EARTHDATA_PASSWORD }}
57+
run: |
58+
uv run pytest --python ${{ matrix.python-version }} -v -m integration --cov=ncompare --cov-append --cov-report=
59+
60+
- name: Generate combined coverage report
4661
run: |
47-
uv run pytest --cov=ncompare --cov-report=xml:build/reports/coverage${{ matrix.python-version }}.xml
62+
uv run coverage xml -o build/reports/coverage${{ matrix.python-version }}.xml
63+
uv run coverage report
4864
4965
- name: Upload coverage reports to Codecov
5066
uses: codecov/codecov-action@v5
5167
with:
5268
token: ${{ secrets.CODECOV_TOKEN }}
69+
files: build/reports/coverage${{ matrix.python-version }}.xml
70+
flags: python-${{ matrix.python-version }}
71+
name: python-${{ matrix.python-version }}
5372
verbose: true

.pre-commit-config.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ ci:
55
autofix_prs: false # Comment "pre-commit.ci autofix" on a PR to trigger
66

77
default_language_version:
8-
python: python3.10
8+
python: python3.11
99

1010
repos:
1111
- repo: https://github.com/gitleaks/gitleaks
12-
rev: v8.28.0
12+
rev: v8.30.0
1313
hooks:
1414
- id: gitleaks
1515

@@ -41,14 +41,14 @@ repos:
4141
exclude_types: ["jupyter", "text"]
4242

4343
- repo: https://github.com/astral-sh/ruff-pre-commit
44-
rev: v0.13.3
44+
rev: v0.14.10
4545
hooks:
4646
- id: ruff
4747
args: ["--fix", "--exit-non-zero-on-fix"]
4848
- id: ruff-format
4949

5050
- repo: https://github.com/pre-commit/mirrors-mypy
51-
rev: v1.18.2
51+
rev: v1.19.1
5252
hooks:
5353
- id: mypy
5454

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010

1111
- update the default python version from 3.9 to 3.10 ([#323](https://github.com/nasa/stitchee/pull/323))([**@danielfromearth**](https://github.com/danielfromearth))
1212
- Implement uv dependency management and versioning with bump-my-version ([#???](https://github.com/nasa/stitchee/issues/???))([**@danielfromearth**](https://github.com/danielfromearth))
13+
- Download ICESat-2 ATL06 granules for integration testing instead of using git lfs ([#327](https://github.com/nasa/stitchee/pull/327))([**@danielfromearth**](https://github.com/danielfromearth))
1314

1415
## [1.13.1] - 2025-01-08
1516

pyproject.toml

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ build-backend = "hatchling.build"
44

55
[project]
66
name = "ncompare"
7-
version = "1.14.0a26"
7+
version = "1.14.0a27"
88
description = "Compare the structure of two NetCDF files at the command line"
99
authors = [
1010
{ name = "Daniel Kaufman", email = "daniel.kaufman@nasa.gov" }
1111
]
1212
readme = "README.md"
13-
requires-python = ">=3.10,<4"
13+
requires-python = ">=3.11,<4"
1414
repository = "https://github.com/nasa/ncompare"
1515
license = "Apache-2.0"
1616
classifiers = [
@@ -19,10 +19,10 @@ classifiers = [
1919
"Operating System :: Microsoft :: Windows",
2020
"Operating System :: MacOS",
2121
"Operating System :: POSIX :: Linux",
22-
"Programming Language :: Python :: 3.10",
2322
"Programming Language :: Python :: 3.11",
2423
"Programming Language :: Python :: 3.12",
2524
"Programming Language :: Python :: 3.13",
25+
"Programming Language :: Python :: 3.14",
2626
"Topic :: Software Development :: Libraries :: Python Modules",
2727
]
2828
dependencies = [
@@ -52,6 +52,15 @@ dev = [
5252
"mkdocs-material>=9.5.12"
5353
]
5454

55+
[tool.pytest.ini_options]
56+
markers = [
57+
"integration: marks tests as integration tests (downloads data, requires auth)",
58+
"slow: marks tests as slow running",
59+
]
60+
# Skip integration tests by default
61+
addopts = "-v -m 'not integration'"
62+
testpaths = ["tests"]
63+
5564
[[tool.mypy.overrides]]
5665
module = [
5766
"colorama.*",
@@ -70,7 +79,7 @@ exclude = [
7079
]
7180
# Allow lines to be as long as 100.
7281
line-length = 100
73-
target-version = "py310"
82+
target-version = "py311"
7483

7584
[tool.ruff.lint]
7685
# E402: module level import not at top of file

tests/conftest.py

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@
2323
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2424
# See the License for the specific language governing permissions and limitations under the License.
2525

26+
import os
2627
from pathlib import Path
2728

29+
import earthaccess
2830
import netCDF4 as nC
2931
import numpy as np
3032
import pytest
@@ -33,6 +35,89 @@
3335
from ncompare.printing import Outputter
3436

3537

38+
@pytest.fixture(scope="session")
39+
def icesat2_cache_dir():
40+
"""Persistent cache directory for ICESat-2 test data."""
41+
cache_dir = Path.home() / ".cache" / "icesat2_test_data"
42+
cache_dir.mkdir(parents=True, exist_ok=True)
43+
return cache_dir
44+
45+
46+
@pytest.fixture(scope="session")
47+
def earthdata_auth():
48+
"""
49+
Authenticate with NASA Earthdata.
50+
Uses credentials from environment variables or .netrc file.
51+
"""
52+
# Check for environment variables (used in CI)
53+
username = os.getenv("EARTHDATA_USERNAME")
54+
password = os.getenv("EARTHDATA_PASSWORD")
55+
56+
if username and password:
57+
earthaccess.login(strategy="environment")
58+
else:
59+
# Use .netrc or prompt for local testing
60+
earthaccess.login()
61+
62+
return True
63+
64+
65+
@pytest.fixture(scope="session")
66+
def icesat2_atl06_granule_1(icesat2_cache_dir, earthdata_auth):
67+
"""
68+
Download or use cached ICESat-2 ATL06 granule #1 for comparison tests.
69+
Temporal range: 2023-08-16 16:16:15 to 2023-08-16 16:25:00
70+
"""
71+
# Check if already cached
72+
cached_files = list(icesat2_cache_dir.glob("ATL06_20230816161508_*.h5"))
73+
if cached_files:
74+
return str(cached_files[0])
75+
76+
# Download if not cached
77+
results = earthaccess.search_data(
78+
short_name="ATL06", temporal=("2023-08-16 16:16:15", "2023-08-16 16:25:00"), count=1
79+
)
80+
81+
if not results:
82+
pytest.skip("ICESat-2 granule #1 not found for test")
83+
84+
# Download the data
85+
files = earthaccess.download(results, str(icesat2_cache_dir))
86+
87+
if not files:
88+
pytest.skip("Failed to download ICESat-2 granule #1")
89+
90+
return files[0]
91+
92+
93+
@pytest.fixture(scope="session")
94+
def icesat2_atl06_granule_2(icesat2_cache_dir, earthdata_auth):
95+
"""
96+
Download or use cached ICESat-2 ATL06 granule #2 for comparison tests.
97+
Temporal range: 2023-08-16 23:46:00 to 2023-08-16 23:48:00
98+
"""
99+
# Check if already cached
100+
cached_files = list(icesat2_cache_dir.glob("ATL06_20230816234629_*.h5"))
101+
if cached_files:
102+
return str(cached_files[0])
103+
104+
# Download if not cached
105+
results = earthaccess.search_data(
106+
short_name="ATL06", temporal=("2023-08-16 23:46:00", "2023-08-16 23:48:00"), count=1
107+
)
108+
109+
if not results:
110+
pytest.skip("ICESat-2 granule #2 not found for test")
111+
112+
# Download the data
113+
files = earthaccess.download(results, str(icesat2_cache_dir))
114+
115+
if not files:
116+
pytest.skip("Failed to download ICESat-2 granule #2")
117+
118+
return files[0]
119+
120+
36121
@pytest.fixture(scope="session")
37122
def temp_data_dir(tmpdir_factory) -> Path:
38123
return Path(tmpdir_factory.mktemp("data"))

tests/test_core.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,18 +74,23 @@ def test_zero_for_comparison_with_no_differences(ds_3dims_3vars_4coords_1subgrou
7474
assert compare(ds_3dims_3vars_4coords_1subgroup, ds_3dims_3vars_4coords_1subgroup) == 0
7575

7676

77-
def test_icesat(temp_data_dir):
77+
@pytest.mark.integration
78+
def test_icesat(temp_data_dir, icesat2_atl06_granule_1, icesat2_atl06_granule_2):
7879
# Compare the `ncompare` output when testing ICESat
7980
out_path = temp_data_dir / "output_file_icesat-2-atl06.txt"
8081

8182
num_differences = compare(
82-
data_for_tests_dir / "icesat-2-ATL06" / "ATL06_20230816161508_08782002_006_02.h5",
83-
data_for_tests_dir / "icesat-2-ATL06" / "ATL06_20230816234629_08822013_006_01.h5",
83+
icesat2_atl06_granule_1,
84+
icesat2_atl06_granule_2,
8485
show_chunks=True,
8586
show_attributes=True,
8687
file_text=str(out_path),
8788
)
8889

90+
# Verify that differences were found and output was written
91+
assert num_differences > 0, "Expected to find differences between granules"
92+
assert out_path.exists(), "Output file was not created"
93+
8994
assert num_differences == 5280
9095

9196

0 commit comments

Comments
 (0)