Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add unit tests for gpm_api.io #8

Merged
merged 39 commits into from
Sep 6, 2023
Merged
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
e6bb56e
Unit tests for gpm_api.io.checks, run coverage on pytest
evanjt Jul 19, 2023
5b642a6
Use black, remove bbox check, move bbox test to geospatial test for f…
evanjt Jul 20, 2023
1e79137
Cast np datetime [ns] to [us]
evanjt Jul 20, 2023
8670b55
Add io/directories tests, modify replace() in curl path constructor a…
evanjt Jul 24, 2023
fb0d33a
Mock ftplib, add tests to disk, download, info
evanjt Jul 24, 2023
3542f84
Modify checks to use os.path.sep to cater for Windows paths
evanjt Jul 24, 2023
e60baec
Add type hint exception for Python 3.8
evanjt Jul 24, 2023
4a7e561
Apply sed command to conftest.py for 3.8 type hints
evanjt Jul 24, 2023
c36f2fe
Modify type hints to be compatible with Python 3.8
evanjt Jul 25, 2023
9bac278
Remove type annotation hack for python 3.8
evanjt Jul 25, 2023
4cdf6f3
test _download_files
evanjt Aug 9, 2023
0700e40
Add test for file completeness
evanjt Aug 9, 2023
d5271d1
Add filter tests
evanjt Aug 10, 2023
45686b5
Add filter unit tests
evanjt Aug 10, 2023
827ff64
Merge branch 'ghiggi:main' into add_io_tests
evanjt Aug 11, 2023
6e4eda0
Merge branch 'add_io_tests' of github.com:EPFL-ENAC/gpm_api into add_…
evanjt Aug 11, 2023
db103ff
Update tests to reflect branch changes
evanjt Aug 11, 2023
23b660a
Add io tests: download_files, convert_pps_to_disk_filepaths, flatten_…
evanjt Aug 11, 2023
97997aa
Add pps tests
evanjt Aug 11, 2023
b0be78a
Add data integrity tests and static filepath fixtures
evanjt Aug 16, 2023
1f2b2af
Mock the user configuration function as to user in-memory configurati…
evanjt Aug 16, 2023
86e4aee
Disable check_start_end_time on empty end_time due to testing inconsi…
evanjt Aug 16, 2023
1b75aae
Remove system specific paths
evanjt Aug 16, 2023
a4e3552
Modify path to os library
evanjt Aug 16, 2023
eca5f20
Fix windows paths
evanjt Aug 16, 2023
49b55c7
Replace : character to - for windows path compatibility
evanjt Aug 16, 2023
2549c72
Merge branch 'ghiggi:main' into add_io_tests
evanjt Aug 18, 2023
54c1e81
Add tests to validate future date errors if using None end_time in fi…
evanjt Aug 21, 2023
c0358e5
Update comment, removing TODO
evanjt Aug 21, 2023
21375e7
Update docstring explaining defaults in filter_by_time
evanjt Aug 21, 2023
8827b5e
Remove redundant auth fixtures from conftest, replace with values in …
evanjt Aug 31, 2023
106d18e
Replace ns with seconds
evanjt Aug 31, 2023
36dacd2
Update gpm_api/tests/io/test_download.py
ghiggi Sep 5, 2023
3921c02
Revert to seconds
evanjt Sep 5, 2023
733b76d
Check timezone, throw error if given and is not UTC
evanjt Sep 5, 2023
8cb2d96
When timezone given and UTC, strip tz information. Test case of using…
evanjt Sep 6, 2023
a23b9e1
Add more flatten list cases, add condition to download.flatten_list()…
evanjt Sep 6, 2023
732b8ed
Replace props with info_dict
evanjt Sep 6, 2023
03d7578
Update gpm_api/tests/io/test_checks.py
ghiggi Sep 6, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 10 additions & 31 deletions gpm_api/io/checks.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/usr/bin/env python3

Check notice on line 1 in gpm_api/io/checks.py

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

✅ Getting better: Overall Code Complexity

The mean cyclomatic complexity decreases from 5.76 to 5.31, threshold = 4. This file has many conditional statements (e.g. if, for, while) across its implementation, leading to lower code health. Avoid adding more conditionals.
"""
Created on Sun Aug 14 20:02:18 2022
@author: ghiggi
Expand Down Expand Up @@ -32,7 +32,7 @@
Base directory where the GPM directory is located.
"""
# Check base_dir does not end with /
if base_dir[-1] == "/":
if base_dir[-1] == os.path.sep:
base_dir = base_dir[0:-1]
# Retrieve last folder name
dir_name = os.path.basename(base_dir)
Expand Down Expand Up @@ -157,15 +157,15 @@
if isinstance(time, np.ndarray):
if np.issubdtype(time.dtype, np.datetime64):
if time.size == 1:
time = time.astype("datetime64[s]").tolist()
time = time.astype("datetime64[us]").tolist()
evanjt marked this conversation as resolved.
Show resolved Hide resolved
else:
raise ValueError("Expecting a single timestep!")
else:
raise ValueError("The numpy array does not have a np.datetime64 dtype!")

# If np.datetime64, convert to datetime.datetime
# If np.datetime64, convert to datetime.datetime with microsecond precision
if isinstance(time, np.datetime64):
time = time.astype("datetime64[s]").tolist()
time = time.astype("datetime64[us]").tolist()
evanjt marked this conversation as resolved.
Show resolved Hide resolved
# If datetime.date, convert to datetime.datetime
if not isinstance(time, (datetime.datetime, str)):
time = datetime.datetime(time.year, time.month, time.day, 0, 0, 0)
Expand All @@ -178,11 +178,12 @@


def check_date(date):
if not isinstance(date, (datetime.date, datetime.datetime)):
raise ValueError("date must be a datetime object")
if isinstance(date, datetime.datetime):
date = date.date()
return date
if date is None:
raise ValueError("date cannot be None")

# Use check_time to convert to datetime.datetime
datetime_obj = check_time(date)
return datetime_obj.date()


def check_start_end_time(start_time, end_time):
Expand Down Expand Up @@ -224,26 +225,4 @@
raise ValueError(f"For {product} product, valid scan_modes are {scan_modes}.")

# -------------------------------------------------------------------------.
return scan_mode

Check notice on line 228 in gpm_api/io/checks.py

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

✅ No longer an issue: Complex Method

check_bbox is no longer above the threshold for cyclomatic complexity. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.

Check notice on line 228 in gpm_api/io/checks.py

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

✅ No longer an issue: Complex Conditional

check_bbox no longer has a complex conditional


def check_bbox(bbox):
"""
Check correctness of bounding box.
bbox format: [lon_0, lon_1, lat_0, lat_1]
bbox should be provided with longitude between -180 and 180, and latitude
between -90 and 90.
"""
if bbox is None:
return bbox
# If bbox provided
if not (isinstance(bbox, list) and len(bbox) == 4):
raise ValueError("Provide valid bbox [lon_0, lon_1, lat_0, lat_1]")
if bbox[2] > 90 or bbox[2] < -90 or bbox[3] > 90 or bbox[3] < -90:
raise ValueError("Latitude is defined between -90 and 90")
# Try to be sure that longitude is specified between -180 and 180
if bbox[0] > 180 or bbox[1] > 180:
print("bbox should be provided with longitude between -180 and 180")
bbox[0] = bbox[0] - 180
bbox[1] = bbox[1] - 180
return bbox
2 changes: 0 additions & 2 deletions gpm_api/io/directories.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ def get_disk_dir_pattern(product, product_type, version):
GPM product name. See: gpm_api.available_products()
product_type : str, optional
GPM product type. Either 'RS' (Research) or 'NRT' (Near-Real-Time).
date : datetime.date
Single date for which to retrieve the data.
version : int, optional
GPM version of the data to retrieve if product_type = 'RS'.

Expand Down
3 changes: 1 addition & 2 deletions gpm_api/io/download.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
# -------------------------------------------------------------------------.
# Replace ftps with ftp to make curl work !!!
# - curl expects ftp:// and not ftps://
server_path = server_path.replace("ftps", "ftp", 1)
server_path = server_path.replace("ftps://", "ftp://", 1)
ghiggi marked this conversation as resolved.
Show resolved Hide resolved
# -------------------------------------------------------------------------.
## Define command to run
# Base command: curl -4 --ftp-ssl --user [user name]:[password] -n [url]
Expand Down Expand Up @@ -195,7 +195,7 @@

pbar is a tqdm progress bar.
"""
# TODO: maybe here capture (with -1) if the file does not exists !¨

Check notice on line 198 in gpm_api/io/download.py

View check run for this annotation

codefactor.io / CodeFactor

gpm_api/io/download.py#L198

unresolved comment '# TODO: maybe here capture (with -1) if the file does not exists !�' (C100)
n_futures = len(dict_futures)
status = [1] * n_futures
for future in as_completed(dict_futures.keys()):
Expand Down Expand Up @@ -258,7 +258,6 @@
progress_bar=True,
verbose=False,
):

if transfer_tool == "curl":
list_cmd = [
curl_cmd(src_path, dst_path, username, username)
Expand Down
7 changes: 3 additions & 4 deletions gpm_api/io/filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,11 +234,10 @@ def filter_by_time(filepaths, start_time=None, end_time=None):
----------
filepaths : list
List of filepaths.

start_time : datetime.datetime
Start time
Start time. Will be set to GPM start mission time (1998-01-01) if None.
end_time : datetime.datetime
End time.
End time. Will be set to current time (`datetime.datetime.utcnow()`) if None.

Returns
----------
Expand All @@ -260,7 +259,7 @@ def filter_by_time(filepaths, start_time=None, end_time=None):
if start_time is None:
start_time = datetime.datetime(1998, 1, 1, 0, 0, 0) # GPM start mission
if end_time is None:
end_time = datetime.datetime.now() # Current time
end_time = datetime.datetime.utcnow() # Current time
start_time, end_time = check_start_end_time(start_time, end_time)

# -------------------------------------------------------------------------.
Expand Down
Empty file added gpm_api/tests/__init__.py
Empty file.
Loading