Skip to content

Bugfix Downloader handling of trailing empty lines#223

Merged
pnuu merged 6 commits intopytroll:mainfrom
pnuu:bugfix-downloader-skip-empty-lines
Mar 5, 2026
Merged

Bugfix Downloader handling of trailing empty lines#223
pnuu merged 6 commits intopytroll:mainfrom
pnuu:bugfix-downloader-skip-empty-lines

Conversation

@pnuu
Copy link
Member

@pnuu pnuu commented Feb 17, 2026

I noticed that if there are any empty lines after the TLEs in files stored locally and used in forming the final TLE set, the parsing fails. This PR adds error handling for the empty lines.

  • Tests added

@pnuu pnuu requested a review from mraspaud February 17, 2026 14:03
@pnuu pnuu self-assigned this Feb 17, 2026
@pnuu pnuu added the bug label Feb 17, 2026
@codecov
Copy link

codecov bot commented Feb 17, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.48%. Comparing base (c2cbf0c) to head (682f9aa).
⚠️ Report is 10 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #223      +/-   ##
==========================================
+ Coverage   90.46%   90.48%   +0.02%     
==========================================
  Files          19       19              
  Lines        3040     3048       +8     
==========================================
+ Hits         2750     2758       +8     
  Misses        290      290              
Flag Coverage Δ
unittests 90.48% <100.00%> (+0.02%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@coveralls
Copy link

Coverage Status

coverage: 90.347% (-0.08%) from 90.431%
when pulling 0850d63 on pnuu:bugfix-downloader-skip-empty-lines
into cd410a9 on pytroll:main.


def _decode_lines_with_platform_header(fid):
tle = ""
try:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you could use suppress(StopIteration) here.

Sorry is this is a stupid question however:
Where does the StopIteration come from? As I understand it, that error comes if we iterate too much with next, but we want to stop at the second line when there are three, so why the error?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error comes when we start parsing the last, empty, line of

1 ... first TLE line
2 ... second tle line

and then try to get the next line.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for my ignorance on this subject, but isn't that an error case then? If we expect a third line and there isn't one?

Otherwise, all this code kind of feels like another generator abstraction is needed. Like:

def decoded_line_pairs_from_file(fid, platform):
    l0 = l1 = None
    for line in fid:
        line = _decode(line)  # also do the .strip() here maybe?
        if l0 is None:
            l0 = line
            continue
        if l1 is None:
            l1 = line
            if l0 != platform:
                yield l0, l1
                l0 = l1 = None
                continue
        if l0.startswith(deisgnator):
            yield l1, l2
            l0 = l1 = None
        ... something? ...

I don't know. Just a gut reaction to see the StopIteration stuff.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are two valid cases for the TLE:

NOAA-20
1 ...
2 ...

and the same without the NOAA-20 line. So either 3 or 2 lines, out of which only the last two are required.

I see that the original code is bad(tm), but didn't want to go that far to rewrite it, just to stop the files with trailing empty lines crashing the code.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, thanks. I still don't see the failure case though. Maybe I need to try to reproduce this to understand.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I restore the version from this PR and add a print to the except StopIteration block and then run the tests with pytest -s pyorbital/tests/test_tlefile.py I don't see the print in the output.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WTF 😂 This time I even wrote the tests first... And this is how it now fails in production with files having trailing empty lines. Locally I tested with Python 3.13.

I'm travelling tomorrow, so can have another look on thursday.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sanity check:

(polar2grid_py312) davidh@dart:~/repos/git/pyorbital$ git branch 
* bugfix-downloader-skip-empty-lines
...


(polar2grid_py312) davidh@dart:~/repos/git/pyorbital$ git diff --stat main
 pyorbital/tests/test_tlefile.py | 15 +++++++++++----
 pyorbital/tlefile.py            | 34 ++++++++++++++++++++++++++++------
 2 files changed, 39 insertions(+), 10 deletions(-)


(polar2grid_py312) davidh@dart:~/repos/git/pyorbital$ git diff
diff --git a/pyorbital/tlefile.py b/pyorbital/tlefile.py
index 33f7bbf..2c9fd50 100644
--- a/pyorbital/tlefile.py
+++ b/pyorbital/tlefile.py
@@ -433,6 +433,7 @@ def _decode_lines_with_platform_header(fid):
         tle = _merge_tle_from_two_lines(l_1, l_2)
     except StopIteration:
         # There were empty lines at the end of the file
+        print("Stop iter!!!")
         pass
     return tle
 
@@ -448,6 +449,7 @@ def _decode_lines_without_platform_header(fid, l_0, platform, only_first, open_i
                 LOGGER.debug("Found platform %s, ID: %s", platform, SATELLITES[platform])
         except StopIteration:
             # There were empty lines at the end of the file
+            print("Stop iter!!!")
             pass
     return tle
 


(polar2grid_py312) davidh@dart:~/repos/git/pyorbital$ pytest -s pyorbital/tests/test_tlefile.py::TestDownloader::test_read_tle_files
=============================================================================================== test session starts ================================================================================================
platform linux -- Python 3.12.4, pytest-8.3.2, pluggy-1.5.0
rootdir: /home/davidh/repos/git/pyorbital
configfile: pyproject.toml
plugins: lazy-fixtures-1.1.1
collected 4 items                                                                                                                                                                                                  

pyorbital/tests/test_tlefile.py ....

================================================================================================ 4 passed in 0.16s =================================================================================================

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, the actual failure I've been having is when there are two or more empty lines. Test case added.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a check for the empty platform string, so the try/except are not needed. They weren't needed in the other branch anyways..

Copy link
Member

@djhoese djhoese left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice job. Glad it was easier to clean up when the issue was better understood. I feel like the if statements could be rearranged to make more sense but that doesn't have to happen here or now.

Looking at the logic is seems very much like some platform checks and some "which lines do we use" rearranging. There are also log messages and if statements with no else block which seem like there could be some short cuts (early return or something similar). But this PR as-is is pretty obvious how you got from one thing to the other so 👍.

@pnuu pnuu merged commit 255334a into pytroll:main Mar 5, 2026
26 of 27 checks passed
@pnuu pnuu deleted the bugfix-downloader-skip-empty-lines branch March 5, 2026 12:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants