generated from MITLibraries/python-cli-template
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #7 from MITLibraries/HRQB-10-scaffold-task-and-tar…
…get-classes Hrqb 10 scaffold task and target classes
- Loading branch information
Showing
23 changed files
with
700 additions
and
105 deletions.
There are no files selected for viewing
This file contains 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 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
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains 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 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,17 @@ | ||
from hrqb.base.target import HRQBLocalTarget, PandasPickleTarget, QuickbaseTableTarget | ||
from hrqb.base.task import ( | ||
HRQBPipelineTask, | ||
HRQBTask, | ||
PandasPickleTask, | ||
QuickbaseUpsertTask, | ||
) | ||
|
||
__all__ = [ | ||
"HRQBLocalTarget", | ||
"PandasPickleTarget", | ||
"QuickbaseTableTarget", | ||
"HRQBPipelineTask", | ||
"HRQBTask", | ||
"PandasPickleTask", | ||
"QuickbaseUpsertTask", | ||
] |
This file contains 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,40 @@ | ||
"""hrqb.base.target""" | ||
|
||
import json | ||
|
||
import luigi # type: ignore[import-untyped] | ||
import pandas as pd | ||
from luigi.format import MixedUnicodeBytes # type: ignore[import-untyped] | ||
|
||
PandasObject = pd.DataFrame | pd.Series | ||
|
||
|
||
class HRQBLocalTarget(luigi.LocalTarget): | ||
"""Target is local file with path and table name init.""" | ||
|
||
def __init__(self, path: str, table_name: str) -> None: | ||
super().__init__(path, format=MixedUnicodeBytes) | ||
self.path = path | ||
self.table_name = table_name | ||
|
||
|
||
class PandasPickleTarget(HRQBLocalTarget): | ||
"""Target is Pandas object (DataFrame or Series) pickled to disk.""" | ||
|
||
def read(self) -> PandasObject: | ||
return pd.read_pickle(self.path) | ||
|
||
def write(self, panda_object: PandasObject) -> None: | ||
panda_object.to_pickle(self.path) | ||
|
||
|
||
class QuickbaseTableTarget(HRQBLocalTarget): | ||
"""Target is upsert to Quickbase table.""" | ||
|
||
def read(self) -> dict: | ||
with open(self.path) as f: | ||
return json.load(f) | ||
|
||
def write(self, data: dict, indent: bool = True) -> int: # noqa: FBT001, FBT002 | ||
with open(self.path, "w") as f: | ||
return f.write(json.dumps(data, indent=indent)) |
This file contains 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,70 @@ | ||
"""hrqb.base.task""" | ||
|
||
import luigi # type: ignore[import-untyped] | ||
import pandas as pd | ||
|
||
from hrqb.base import PandasPickleTarget, QuickbaseTableTarget | ||
from hrqb.utils import today_date | ||
|
||
|
||
class HRQBTask(luigi.Task): | ||
"""Base Task class for all HRQB Tasks.""" | ||
|
||
path = luigi.Parameter() | ||
table_name = luigi.Parameter() | ||
|
||
@property | ||
def single_input(self) -> PandasPickleTarget | QuickbaseTableTarget: | ||
input_count = len(self.input()) | ||
if input_count != 1: | ||
message = f"Expected a single input to this Task but found: {input_count}" | ||
raise ValueError(message) | ||
return self.input()[0] | ||
|
||
@property | ||
def input_pandas_dataframe(self) -> pd.DataFrame: | ||
input_object = self.single_input | ||
data_object = input_object.read() | ||
if not isinstance(data_object, pd.DataFrame): | ||
message = f"Expected pandas Dataframe but got: {type(data_object)}" | ||
raise TypeError(message) | ||
return data_object | ||
|
||
@property | ||
def input_pandas_series(self) -> pd.Series: | ||
input_object = self.single_input | ||
data_object = input_object.read() | ||
if not isinstance(data_object, pd.Series): | ||
message = f"Expected pandas Series but got: {type(data_object)}" | ||
raise TypeError(message) | ||
return data_object | ||
|
||
|
||
class PandasPickleTask(HRQBTask): | ||
"""Base Task class for Tasks that write pickled pandas objects.""" | ||
|
||
def target(self) -> PandasPickleTarget: | ||
return PandasPickleTarget( | ||
path=self.path, | ||
table_name=self.table_name, | ||
) | ||
|
||
def output(self) -> PandasPickleTarget: | ||
return self.target() | ||
|
||
|
||
class QuickbaseUpsertTask(HRQBTask): | ||
"""Base Task class for Tasks that upsert data to Quickbase tables.""" | ||
|
||
def target(self) -> QuickbaseTableTarget: | ||
return QuickbaseTableTarget( | ||
path=self.path, | ||
table_name=self.table_name, | ||
) | ||
|
||
def output(self) -> QuickbaseTableTarget: | ||
return self.target() | ||
|
||
|
||
class HRQBPipelineTask(luigi.WrapperTask): | ||
date = luigi.DateParameter(default=today_date()) |
This file contains 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 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 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,3 @@ | ||
[core] | ||
autoload_range=true | ||
parallel_scheduling=false |
This file contains 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,15 @@ | ||
"""hrqb.pipelines""" | ||
|
||
import luigi # type: ignore[import-untyped] | ||
from luigi.execution_summary import LuigiRunResult # type: ignore[import-untyped] | ||
|
||
|
||
def run_pipeline(pipeline_task: luigi.WrapperTask) -> LuigiRunResult: | ||
return luigi.build( | ||
[pipeline_task], | ||
local_scheduler=True, | ||
detailed_summary=True, | ||
) | ||
|
||
|
||
# TODO: add wrapper Pipeline tasks in this file # noqa: TD002, TD003, FIX002 |
Empty file.
This file contains 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,3 @@ | ||
"""hrqb.tasks.extract""" | ||
|
||
# TODO: add extract tasks in this file # noqa: TD002, TD003, FIX002 |
This file contains 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,3 @@ | ||
"""hrqb.tasks.load""" | ||
|
||
# TODO: add load tasks in this file # noqa: TD002, TD003, FIX002 |
This file contains 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,3 @@ | ||
"""hrqb.tasks.transform""" | ||
|
||
# TODO: add transform tasks in this file # noqa: TD002, TD003, FIX002 |
This file contains 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,7 @@ | ||
"""hrqb.utils""" | ||
|
||
import datetime | ||
|
||
|
||
def today_date() -> datetime.date: | ||
return datetime.datetime.now(tz=datetime.UTC).date() |
Empty file.
This file contains 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 |
---|---|---|
|
@@ -48,6 +48,7 @@ ignore = [ | |
"PLR0912", | ||
"PLR0913", | ||
"PLR0915", | ||
"S301", | ||
"S320", | ||
"S321", | ||
] | ||
|
Oops, something went wrong.