-
Notifications
You must be signed in to change notification settings - Fork 2
feat: add decorator to check if las file is written correctly #194
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
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| """Check that LAS/LAZ files can be read by PDAL. | ||
|
|
||
| Provides a one-shot check, a retry variant (for files still being written), and a | ||
| decorator that validates an output path after a wrapped function returns. | ||
| """ | ||
|
|
||
| import functools | ||
| import inspect | ||
| import os | ||
| import time | ||
|
|
||
| import pdal | ||
|
|
||
|
|
||
| def check_pdal_can_open_file(filepath: str) -> bool: | ||
| try: | ||
| if not os.path.exists(filepath): | ||
| raise FileNotFoundError(f"File {filepath} does not exist.") | ||
| pipeline = pdal.Reader.las(filename=filepath).pipeline() | ||
| pipeline.execute() | ||
| return True | ||
| except RuntimeError as e: | ||
| if e.__str__().startswith("readers.las:"): | ||
| print(f"Pdal could not read {filepath} due to error: {e}") | ||
| return False | ||
| else: | ||
| raise e | ||
|
|
||
|
|
||
| def check_pdal_can_open_file_with_retry(filepath: str, delay: int) -> bool: | ||
| if check_pdal_can_open_file(filepath): | ||
| return True | ||
| else: | ||
| print(f"New attempt in {delay} seconds.") | ||
| time.sleep(delay) | ||
| return check_pdal_can_open_file(filepath) | ||
|
|
||
|
|
||
| def check_pdal_can_open_file_with_retry_decorator(delay: int, filepath: str | None = None): | ||
| def decorator(fn): | ||
| sig = inspect.signature(fn) | ||
|
|
||
| # Extract the LAS path from the wrapped call: bind args/kwargs to the | ||
| # function signature, apply defaults if needed, then return the parameter | ||
| # named by `filepath` (e.g. "output_file" or the first positional arg). | ||
| def resolve_filepath(*args, **kwargs) -> str: | ||
| bound = sig.bind_partial(*args, **kwargs) | ||
| if filepath not in bound.arguments: | ||
| bound.apply_defaults() | ||
| return str(bound.arguments[filepath]) | ||
|
|
||
| @functools.wraps(fn) | ||
| def wrapper(*args, **kwargs): | ||
| result = fn(*args, **kwargs) | ||
| resolved_filepath = resolve_filepath(*args, **kwargs) | ||
| if not check_pdal_can_open_file_with_retry(resolved_filepath, delay): | ||
| raise RuntimeError(f"Pdal could not read {resolved_filepath} after retry.") | ||
| return result | ||
|
|
||
| return wrapper | ||
|
|
||
| return decorator | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
Binary file not shown.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| """Check if a LAS file is written correcty and can be opened by PDAL""" | ||
|
|
||
| import os | ||
| import shutil | ||
|
|
||
| import pytest | ||
|
|
||
| from pdaltools.check_las import ( | ||
| check_pdal_can_open_file, | ||
| check_pdal_can_open_file_with_retry, | ||
| check_pdal_can_open_file_with_retry_decorator, | ||
| ) | ||
|
|
||
| TEST_PATH = os.path.dirname(os.path.abspath(__file__)) | ||
| INPUT_DIR = os.path.join(TEST_PATH, "data/check_las") | ||
|
|
||
|
|
||
| def test_check_pdal_can_open_file(): | ||
| filepath = os.path.join(INPUT_DIR, "Semis_2022_0906_6665_LA93_IGN69_ok.laz") | ||
| assert check_pdal_can_open_file(filepath) | ||
|
|
||
|
|
||
| def test_check_pdal_can_open_file_nok(): | ||
| filepath = os.path.join(INPUT_DIR, "Semis_2022_0906_6665_LA93_IGN69_nok.laz") | ||
| assert not check_pdal_can_open_file(filepath) | ||
|
|
||
|
|
||
| def test_check_pdal_can_open_file_with_retry(): | ||
| filepath = os.path.join(INPUT_DIR, "Semis_2022_0906_6665_LA93_IGN69_ok.laz") | ||
| assert check_pdal_can_open_file_with_retry(filepath, 1) | ||
|
|
||
|
|
||
| def test_check_pdal_can_open_file_with_retry_nok(): | ||
| filepath = os.path.join(INPUT_DIR, "Semis_2022_0906_6665_LA93_IGN69_nok.laz") | ||
| assert not check_pdal_can_open_file_with_retry(filepath, 1) | ||
|
|
||
|
|
||
| @check_pdal_can_open_file_with_retry_decorator(delay=0, filepath="filepath") # or mock time.sleep | ||
| def echo(filepath): | ||
| return filepath | ||
|
|
||
|
|
||
| def test_decorator_passes_through_on_ok(): | ||
| filepath = os.path.join(INPUT_DIR, "Semis_2022_0906_6665_LA93_IGN69_ok.laz") | ||
| assert echo(filepath) == filepath | ||
|
|
||
|
|
||
| def test_decorator_raises_on_nok(): | ||
| filepath = os.path.join(INPUT_DIR, "Semis_2022_0906_6665_LA93_IGN69_nok.laz") | ||
| with pytest.raises(RuntimeError): | ||
| echo(filepath) | ||
|
|
||
|
|
||
| @check_pdal_can_open_file_with_retry_decorator(delay=0, filepath="output_file") | ||
| def copy_las(input_file, output_file): | ||
| shutil.copy(input_file, output_file) | ||
|
|
||
|
|
||
| def test_decorator_post_write_passes_on_ok(tmp_path): | ||
| input_file = os.path.join(INPUT_DIR, "Semis_2022_0906_6665_LA93_IGN69_ok.laz") | ||
| output_file = tmp_path / "output.laz" | ||
| copy_las(input_file, output_file) | ||
| print(output_file) | ||
| assert output_file.is_file() | ||
|
|
||
|
|
||
| def test_decorator_post_write_raises_on_nok(tmp_path): | ||
| input_file = os.path.join(INPUT_DIR, "Semis_2022_0906_6665_LA93_IGN69_nok.laz") | ||
| output_file = tmp_path / "output.laz" | ||
| with pytest.raises(RuntimeError): | ||
| copy_las(input_file, output_file) |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.