Repository navigation
feat: csv shifting #149
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
feat: csv shifting #149
Changes from all commits
Commits
Show all changes
73 commits
Select commit
Hold shift + click to select a range
69c6b65
renamed the parameter for clarity
peterlavalle-nhs ba6742d
always check sheets we're checking (for hidden dates et al)
peterlavalle-nhs ff2f4a2
detects the problem
peterlavalle-nhs 1789a14
more detail for the error message
peterlavalle-nhs 920b301
validates what it should
peterlavalle-nhs 0547569
fixes ignores to skip temp xlsx files
peterlavalle-nhs 34469d5
passes all tests again
peterlavalle-nhs 45ab14d
checks for padded cell values
peterlavalle-nhs 5250972
updates it to handle ignored values with spaces around them
peterlavalle-nhs d727465
Update log message and comments for clarity
g-pechorin 592c130
might do the dates
peterlavalle-nhs 32bc10c
Merge remote-tracking branch 'origin/shift_ignore' into shift_ignore
peterlavalle-nhs 4b4479a
more corrections
peterlavalle-nhs 19ff976
raises a specific error for missing patient columns
peterlavalle-nhs af53890
(WIP) need to digest/adapt the patient_id loading
peterlavalle-nhs 3fa2186
updates the rest of the date shift
peterlavalle-nhs 38ece50
improved function and comments
peterlavalle-nhs 7247526
uses the new exception
peterlavalle-nhs db26a0c
changes to allow pip to access book_page
peterlavalle-nhs 65de773
small logging messages
peterlavalle-nhs f470909
Merge remote-tracking branch 'origin/book_page' into book_page
peterlavalle-nhs 77245b8
more logging
peterlavalle-nhs 9e98b1e
log during id generation
peterlavalle-nhs dc1b873
remove the pd call
peterlavalle-nhs 651c457
restored it - it wasn't the problem
peterlavalle-nhs 57e1bd2
ignore the coverage database
peterlavalle-nhs 117a386
removes duplicate parameters from _inplace
peterlavalle-nhs 3fc3d9d
update docs (oops)
peterlavalle-nhs 68309d8
removes duplicate parameters from _inplace
peterlavalle-nhs 700a568
update docs (oops)
peterlavalle-nhs f3dcf66
Merge branch 'shift_ignore' into shift_ignore_yaml
peterlavalle-nhs 83c87ef
shift ignore reading from YAML
peterlavalle-nhs 5091e8e
detects old (bad) configs
peterlavalle-nhs 9441cf4
don't count tests/ when checking coverage
peterlavalle-nhs be338b1
debug logging for the ignores
peterlavalle-nhs 4215f13
tests all pass with the new yaml file approach
peterlavalle-nhs 6e70a83
Merge branch 'shift_ignore' into book_page
peterlavalle-nhs de2be87
just-enough to see if it helps
peterlavalle-nhs 1451435
test/uv updates
peterlavalle-nhs 184230e
Merge branch 'book_page' into book_stream
peterlavalle-nhs 77b5476
pointed to the live copy
peterlavalle-nhs cdc970d
WIP 93/111 tests pass
peterlavalle-nhs 817acb3
implements "row is blank" test and skipping
peterlavalle-nhs e15626d
"cheats" and switches the ambiguous date to iso8061
peterlavalle-nhs 9266d43
corrected overlap detection and testing
peterlavalle-nhs 8e04437
fixes missing patient id column detection
peterlavalle-nhs 1206f2d
added comments and checks for "skip holes"
peterlavalle-nhs 357067c
Merge remote-tracking branch 'origin/main' into book_page
peterlavalle-nhs 7801176
corrected the result of a rename
peterlavalle-nhs bc74743
fix again
peterlavalle-nhs a17e990
allow header default to 0 in patient page, and, allow date values in …
peterlavalle-nhs 17de1f4
refactored the existing functions (as is) into separate files
peterlavalle-nhs 4a5e407
brings book_page (and tests) into the project
peterlavalle-nhs 8dd5540
raise different exception
peterlavalle-nhs cde02e7
refactors the shift_delta generation to be simpler and move checking …
peterlavalle-nhs 7266555
try to separate the sheet/row checks to be a standalone thing
peterlavalle-nhs bca28c5
refactored the loop control and parameter lookups into a scanner class
peterlavalle-nhs 1fc05bf
extracts the ignore rules to a subroutine
peterlavalle-nhs 7f75ba7
idea for how to fixit
peterlavalle-nhs 0f06412
more cleanup
peterlavalle-nhs 93da71d
comments and removed a redundant check
peterlavalle-nhs fe70510
"orchestration" changes
peterlavalle-nhs e15b3c5
csv and excel workbooks now both try to parse dates to be consistent …
peterlavalle-nhs 54d8c3e
adds the hidden-date bypass to book_page
peterlavalle-nhs 09e2e8a
always allow "NULL" in date columns
peterlavalle-nhs a4eb73b
option to skip dating date
peterlavalle-nhs c7d8776
add "skip" to sheet/page types
peterlavalle-nhs c17e023
cut out normalise in a different way
peterlavalle-nhs a17deb2
renamed and documented the bypasses
peterlavalle-nhs c623097
raise exceptions on abstract invocation
peterlavalle-nhs 24bd638
Potential fix for pull request finding 'CodeQL / Clear-text logging o…
g-pechorin 780682a
renamed self to self
peterlavalle-nhs 10c96df
Merge remote-tracking branch 'origin/book_page' into book_page
peterlavalle-nhs 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
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,13 @@ | ||
| from nuh_helper.book_page.book import BasePage, BaseWorkBook, normalize_row | ||
| from nuh_helper.book_page.csv_book import CSVWorkBook | ||
| from nuh_helper.book_page.generic import book_open | ||
| from nuh_helper.book_page.xlsx_book import XLSXWorkBook | ||
|
|
||
| __all__ = [ # noqa: PLE0604 | ||
| CSVWorkBook, | ||
| XLSXWorkBook, | ||
| BaseWorkBook, | ||
| BasePage, | ||
| book_open, | ||
| normalize_row, | ||
| ] | ||
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,138 @@ | ||
| from abc import ABC, abstractmethod | ||
| from collections.abc import Generator as gen | ||
| from collections.abc import Iterable as iterator | ||
| from datetime import date, datetime | ||
| from functools import cached_property | ||
| from pathlib import Path | ||
|
|
||
| cell_val_t = None | str | date | datetime | ||
| row_val_t = list[cell_val_t] | ||
|
|
||
|
|
||
| class BasePage(ABC): | ||
| def __init__(self, name: str, page: object) -> None: | ||
| self._name = name | ||
| self._page = page | ||
|
|
||
| @abstractmethod | ||
| def _stream_rows_impl(self) -> gen[tuple[int, row_val_t]]: | ||
| """performs the workbook specific yield/write of the row data""" | ||
| raise NotImplementedError() | ||
|
|
||
| def stream_rows(self) -> gen[tuple[int, row_val_t]]: | ||
| """public method for reading a RO stream of rows from a specific page""" | ||
|
|
||
| for row_idx, row_data in self._stream_rows_impl(): | ||
| if BaseWorkBook.normalize_values: | ||
| for raw_idx, raw_val in enumerate(row_data): | ||
| row_data[raw_idx] = normalize_val(raw_val) | ||
|
|
||
| yield row_idx, row_data | ||
|
|
||
| @cached_property | ||
| def name(self) -> str: | ||
| return self._name | ||
|
|
||
|
|
||
| class BaseWorkBook(ABC): | ||
| normalize_values: bool = True | ||
|
|
||
| def __contains__(self, name: str) -> bool: | ||
| return name in self.keys() | ||
|
|
||
| @abstractmethod | ||
| def __getitem__(self, name: str) -> gen[BasePage]: | ||
| raise NotImplementedError() | ||
|
|
||
| @abstractmethod | ||
| def keys(self) -> iterator[str]: | ||
| raise NotImplementedError() | ||
|
|
||
| @abstractmethod | ||
| def _stream_copy_impl(self, into: Path) -> gen[tuple[str, int, row_val_t]]: | ||
| """performs the workbook specific yield/write of the row data""" | ||
| raise NotImplementedError() | ||
|
|
||
| def stream_copy( | ||
| self, | ||
| into: str | Path, | ||
| date_format: None | str = None, | ||
| time_format: None | str = None, | ||
| ) -> gen[tuple[str, int, row_val_t]]: | ||
| """public method for copying a stream of rows between two workbooks""" | ||
|
|
||
| into = (into if isinstance(into, Path) else Path(into)).absolute() | ||
|
|
||
| time_format = ( | ||
| time_format | ||
| if time_format | ||
| else (date_format if date_format else "%Y-%m-%d %H:%M:%S") | ||
| ) | ||
| date_format = date_format if date_format else "%Y-%m-%d" | ||
|
|
||
| for page_name, row_idx, row_data in self._stream_copy_impl(into): | ||
| yield page_name, row_idx, row_data | ||
| if BaseWorkBook.normalize_values: | ||
| for raw_idx, raw_val in enumerate(row_data): | ||
| if isinstance(raw_val, date): | ||
| row_data[raw_idx] = raw_val.strftime(date_format) | ||
| elif isinstance(raw_val, datetime): | ||
| row_data[raw_idx] = raw_val.strftime(time_format) | ||
|
|
||
| def __iter__(self) -> gen[BasePage]: | ||
| for name in self.keys(): | ||
| with self[name] as page: | ||
| yield page | ||
|
|
||
|
|
||
| def normalize_val(src: object) -> object: | ||
| """parse to a datetime, .strip(), turn "" into None, retain bool""" | ||
|
|
||
| if ( | ||
| isinstance(src, (bool | float | int | datetime | date)) | ||
| or not BaseWorkBook.normalize_values | ||
| ): | ||
| return src | ||
|
|
||
| if isinstance(src, str): | ||
| src = src.strip() | ||
|
|
||
| if not src: | ||
| return None | ||
|
|
||
| if isinstance(src, str): | ||
| # Try a handful of common formats, including YYYY-DD-MM found in some feeds | ||
| for fmt in ("%Y-%m-%d", "%Y-%d-%m", "%d-%m-%Y", "%m-%d-%Y"): | ||
| try: | ||
| return datetime.strptime(src, fmt) | ||
| except (TypeError, ValueError): | ||
| # If parsing with this specific format fails, silently try next format. | ||
| pass | ||
|
|
||
| # Fallback: try ISO 8601 parsing (handles many ambiguous/edge cases) | ||
| try: | ||
| return datetime.fromisoformat(src) | ||
| except (TypeError, ValueError): | ||
| pass | ||
|
|
||
| # Last resort: try a few more relaxed formats | ||
| for fmt in ( | ||
| "%Y/%m/%d", | ||
| "%d/%m/%Y", | ||
| "%m/%d/%Y", | ||
| "%Y-%m-%dT%H:%M:%S", | ||
| "%Y-%m-%d %H:%M:%S", | ||
| ): | ||
| try: | ||
| return datetime.strptime(src, fmt) | ||
| except (TypeError, ValueError): | ||
| pass | ||
|
|
||
| return src | ||
|
|
||
|
|
||
| def normalize_row(row: list[str]) -> list[str]: | ||
| """modifies (and returns) the passed array to drop extra whitespace and replace | ||
| fully blank entries with None. doesn't touch non-strings""" | ||
|
|
||
| return [normalize_val(val) for val in row] |
Oops, something went wrong.
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.