| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
There was a problem hiding this comment.
This PR reorganizes the DataPusher Plus codebase from a monolithic jobs.py file (1624 lines) into a modular pipeline architecture with distinct stages. The refactoring separates concerns into individual stage classes (Download, FormatConverter, Validation, Analysis, Database, Indexing, Formula, Metadata), each with a single well-defined responsibility. The original monolithic implementation is preserved in jobs_legacy.py for reference, while jobs.py now serves as a backward compatibility wrapper.
Key Changes:
Copilot reviewed 16 out of 16 changed files in this pull request and generated 17 comments.
Show a summary per file| File | Description |
|---|---|
| ckanext/datapusher_plus/jobs_legacy.py | Preserved copy of original monolithic implementation for reference |
| ckanext/datapusher_plus/jobs.py | Backward compatibility wrapper that re-exports refactored functions |
| ckanext/datapusher_plus/jobs/__init__.py | Module initialization with exports |
| ckanext/datapusher_plus/jobs/pipeline.py | Main pipeline orchestration and execution logic |
| ckanext/datapusher_plus/jobs/context.py | ProcessingContext dataclass for shared state management |
| ckanext/datapusher_plus/jobs/stages/base.py | Abstract base class for all pipeline stages |
| ckanext/datapusher_plus/jobs/stages/download.py | Download stage implementation |
| ckanext/datapusher_plus/jobs/stages/format_converter.py | Format conversion stage implementation |
| ckanext/datapusher_plus/jobs/stages/validation.py | CSV validation and deduplication stage |
| ckanext/datapusher_plus/jobs/stages/analysis.py | Type inference and statistics stage |
| ckanext/datapusher_plus/jobs/stages/database.py | PostgreSQL COPY operations stage |
| ckanext/datapusher_plus/jobs/stages/indexing.py | Automatic index creation stage |
| ckanext/datapusher_plus/jobs/stages/formula.py | DRUF Jinja2 formula processing stage |
| ckanext/datapusher_plus/jobs/stages/metadata.py | Resource metadata updates and aliasing stage |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Sorry, something went wrong.
| ) | ||
| sortcheck_json = json.loads(str(stdout_content)) | ||
| except (json.JSONDecodeError, AttributeError) as e: | ||
| raise utils.JobError(f"Failed to parse sortcheck JSONoutput: {e}") |
There was a problem hiding this comment.
Corrected spelling of 'JSONoutput' to 'JSON output' (should have space).
| raise utils.JobError(f"Failed to parse sortcheck JSONoutput: {e}") | |
| raise utils.JobError(f"Failed to parse sortcheck JSON output: {e}") |
Sorry, something went wrong.
| f'"{len(unsafe_headers)} unsafe" header names found ' | ||
| f"({unsafe_headers}). Sanitizing...\"" |
There was a problem hiding this comment.
Mismatched quotation marks - the log message starts with a single quote but ends with escaped double quote followed by single quote. Should be consistent: f'"{len(unsafe_headers)} unsafe" header names found ({unsafe_headers}). Sanitizing...'
| f'"{len(unsafe_headers)} unsafe" header names found ' | |
| f"({unsafe_headers}). Sanitizing...\"" | |
| f"{len(unsafe_headers)} unsafe header names found " | |
| f"({unsafe_headers}). Sanitizing..." |
Sorry, something went wrong.
| context = stage(context) | ||
|
|
||
| # If stage returns None, stop pipeline | ||
| if context is None: | ||
| context.logger.info(f"Pipeline stopped after stage: {stage.name}") |
There was a problem hiding this comment.
Attempting to access context.logger after context is None will cause an AttributeError. When a stage returns None, the context is None and cannot be accessed. The logger should be accessed before the None check or stored separately.
| context = stage(context) | |
| # If stage returns None, stop pipeline | |
| if context is None: | |
| context.logger.info(f"Pipeline stopped after stage: {stage.name}") | |
| logger = context.logger | |
| context = stage(context) | |
| # If stage returns None, stop pipeline | |
| if context is None: | |
| logger.info(f"Pipeline stopped after stage: {stage.name}") |
Sorry, something went wrong.
| ) | ||
|
|
||
| # Process resource suggestion formulae | ||
| package = self._process_resource_suggestions( |
There was a problem hiding this comment.
Variable package is not used.
| package = self._process_resource_suggestions( | |
| self._process_resource_suggestions( |
Sorry, something went wrong.
| else: | ||
| qsv_input_utf_8_encoded_csv = tmp | ||
| try: | ||
| qsv.input(tmp, trim_headers=True, output_file=qsv_input_csv) |
There was a problem hiding this comment.
Variable qsv_input_utf_8_encoded_csv is not used.
| qsv.input(tmp, trim_headers=True, output_file=qsv_input_csv) | |
| qsv.input(qsv_input_utf_8_encoded_csv, trim_headers=True, output_file=qsv_input_csv) |
Sorry, something went wrong.
| f"Resource too large to download: {DataSize(int(cl)):.2MB} " | ||
| f"> max ({DataSize(int(max_content_length)):.2MB})." | ||
| ) | ||
| except ValueError: |
There was a problem hiding this comment.
'except' clause does nothing but pass and there is no explanatory comment.
| except ValueError: | |
| except ValueError: | |
| # If content-length header is missing or malformed, skip size check and proceed. |
Sorry, something went wrong.
| raise utils.JobError( | ||
| f"Resource too large to download: {DataSize(int(cl)):.2MB} > max ({DataSize(int(max_content_length)):.2MB})." | ||
| ) | ||
| except ValueError: |
There was a problem hiding this comment.
'except' clause does nothing but pass and there is no explanatory comment.
| except ValueError: | |
| except ValueError: | |
| # If content-length header is missing or malformed, ignore and proceed as file size is unknown. |
Sorry, something went wrong.
| # to truncate overly long strings from causing issues with | ||
| # Python's CSV reader and Postgres's limits with the COPY command | ||
| if spatial_format_flag: | ||
| env = os.environ.copy() |
There was a problem hiding this comment.
This statement is unreachable.
Sorry, something went wrong.
| f = open(qsv_input_utf_8_encoded_csv, "wb") | ||
| f.write(cmd.stdout) | ||
| f.close() |
There was a problem hiding this comment.
File may not be closed if this operation raises an exception.
| f = open(qsv_input_utf_8_encoded_csv, "wb") | |
| f.write(cmd.stdout) | |
| f.close() | |
| with open(qsv_input_utf_8_encoded_csv, "wb") as f: | |
| f.write(cmd.stdout) |
Sorry, something went wrong.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
| Back | FazBrowse Home | New Git URL |
With this PR we are reorganizing the project structure into different directories for better separation of concerns
Each pipeline stage has a single, well-defined responsibility: