-
Notifications
You must be signed in to change notification settings - Fork 68
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
remove dependency on six, drop support for python 3.7, update dev dep…
…dendencies update pytest describe add flexible terminal string formatter start swapping in default formats start phasing out underline_cells wip wip demonstrate how custom formatting can be injected via pytest fixtures wip make sure format_string works with no formats add new custom formatter to readme bump to v0.10.0 New Chispa interface (#94) * add formats to dataframe comparer * add new chispa interface lock run tests for multiple python versions small fix add runs-on argument fix reset ci
- Loading branch information
Showing
22 changed files
with
684 additions
and
1,372 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
name: "setup-poetry-env" | ||
description: "Composite action to setup the Python and poetry environment." | ||
|
||
inputs: | ||
python-version: | ||
required: false | ||
description: "The python version to use" | ||
default: "3.11" | ||
|
||
runs: | ||
using: "composite" | ||
steps: | ||
- name: Set up python | ||
uses: actions/setup-python@v4 | ||
with: | ||
python-version: ${{ inputs.python-version }} | ||
|
||
- name: Install Poetry | ||
env: | ||
# renovate: datasource=pypi depName=poetry | ||
POETRY_VERSION: "1.5.1" | ||
run: curl -sSL https://install.python-poetry.org | python - -y | ||
shell: bash | ||
|
||
- name: Add Poetry to Path | ||
run: echo "$HOME/.local/bin" >> $GITHUB_PATH | ||
if: ${{ matrix.os != 'Windows' }} | ||
shell: bash | ||
|
||
- name: Add Poetry to Path | ||
run: echo "$APPDATA\Python\Scripts" >> $GITHUB_PATH | ||
if: ${{ matrix.os == 'Windows' }} | ||
shell: bash | ||
|
||
- name: Configure Poetry virtual environment in project | ||
run: poetry config virtualenvs.in-project true | ||
shell: bash | ||
|
||
- name: Load cached venv | ||
id: cached-poetry-dependencies | ||
uses: actions/cache@v3 | ||
with: | ||
path: .venv | ||
key: venv-${{ runner.os }}-${{ inputs.python-version }}-${{ hashFiles('poetry.lock') }} | ||
|
||
- name: Install dependencies | ||
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true' | ||
run: poetry install --no-interaction | ||
shell: bash |
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 was deleted.
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
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,8 @@ | ||
from dataclasses import dataclass | ||
|
||
@dataclass | ||
class DefaultFormats: | ||
mismatched_rows = ["red"] | ||
matched_rows = ["blue"] | ||
mismatched_cells = ["red", "underline"] | ||
matched_cells = ["blue"] |
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 |
---|---|---|
@@ -1,85 +1,78 @@ | ||
import chispa.six as six | ||
from itertools import zip_longest | ||
from chispa.prettytable import PrettyTable | ||
from chispa.bcolors import * | ||
import chispa | ||
from pyspark.sql.types import Row | ||
from typing import List | ||
from chispa.terminal_str_formatter import format_string | ||
from chispa.default_formats import DefaultFormats | ||
|
||
|
||
def assert_basic_rows_equality(rows1, rows2, underline_cells=False): | ||
if underline_cells: | ||
row_column_names = rows1[0].__fields__ | ||
num_columns = len(row_column_names) | ||
def assert_basic_rows_equality(rows1, rows2, underline_cells=False, formats=DefaultFormats()): | ||
if rows1 != rows2: | ||
t = PrettyTable(["df1", "df2"]) | ||
zipped = list(six.moves.zip_longest(rows1, rows2)) | ||
zipped = list(zip_longest(rows1, rows2)) | ||
all_rows_equal = True | ||
|
||
for r1, r2 in zipped: | ||
if r1 == r2: | ||
t.add_row([blue(r1), blue(r2)]) | ||
if r1 is None and r2 is not None: | ||
t.add_row([None, format_string(r2, formats.mismatched_rows)]) | ||
all_rows_equal = False | ||
elif r1 is not None and r2 is None: | ||
t.add_row([format_string(r1, formats.mismatched_rows), None]) | ||
all_rows_equal = False | ||
else: | ||
if underline_cells: | ||
t.add_row(__underline_cells_in_row( | ||
r1=r1, r2=r2, row_column_names=row_column_names, num_columns=num_columns)) | ||
else: | ||
t.add_row([r1, r2]) | ||
raise chispa.DataFramesNotEqualError("\n" + t.get_string()) | ||
r_zipped = list(zip_longest(r1.__fields__, r2.__fields__)) | ||
r1_string = [] | ||
r2_string = [] | ||
for r1_field, r2_field in r_zipped: | ||
if r1[r1_field] != r2[r2_field]: | ||
all_rows_equal = False | ||
r1_string.append(format_string(f"{r1_field}={r1[r1_field]}", formats.mismatched_cells)) | ||
r2_string.append(format_string(f"{r2_field}={r2[r2_field]}", formats.mismatched_cells)) | ||
else: | ||
r1_string.append(format_string(f"{r1_field}={r1[r1_field]}", formats.matched_cells)) | ||
r2_string.append(format_string(f"{r2_field}={r2[r2_field]}", formats.matched_cells)) | ||
r1_res = ", ".join(r1_string) | ||
r2_res = ", ".join(r2_string) | ||
|
||
t.add_row([r1_res, r2_res]) | ||
if all_rows_equal == False: | ||
raise chispa.DataFramesNotEqualError("\n" + t.get_string()) | ||
|
||
|
||
def assert_generic_rows_equality(rows1, rows2, row_equality_fun, row_equality_fun_args, underline_cells=False): | ||
def assert_generic_rows_equality(rows1, rows2, row_equality_fun, row_equality_fun_args, underline_cells=False, formats=DefaultFormats()): | ||
df1_rows = rows1 | ||
df2_rows = rows2 | ||
zipped = list(six.moves.zip_longest(df1_rows, df2_rows)) | ||
zipped = list(zip_longest(df1_rows, df2_rows)) | ||
t = PrettyTable(["df1", "df2"]) | ||
allRowsEqual = True | ||
if underline_cells: | ||
row_column_names = rows1[0].__fields__ | ||
num_columns = len(row_column_names) | ||
all_rows_equal = True | ||
for r1, r2 in zipped: | ||
# rows are not equal when one is None and the other isn't | ||
if (r1 is not None and r2 is None) or (r2 is not None and r1 is None): | ||
allRowsEqual = False | ||
t.add_row([r1, r2]) | ||
all_rows_equal = False | ||
t.add_row([format_string(r1, formats.mismatched_rows), format_string(r2, formats.mismatched_rows)]) | ||
# rows are equal | ||
elif row_equality_fun(r1, r2, *row_equality_fun_args): | ||
first = bcolors.LightBlue + str(r1) + bcolors.LightRed | ||
second = bcolors.LightBlue + str(r2) + bcolors.LightRed | ||
t.add_row([first, second]) | ||
r1_string = ", ".join(map(lambda f: f"{f}={r1[f]}", r1.__fields__)) | ||
r2_string = ", ".join(map(lambda f: f"{f}={r2[f]}", r2.__fields__)) | ||
t.add_row([format_string(r1_string, formats.matched_rows), format_string(r2_string, formats.matched_rows)]) | ||
# otherwise, rows aren't equal | ||
else: | ||
allRowsEqual = False | ||
# Underline cells if requested | ||
if underline_cells: | ||
t.add_row(__underline_cells_in_row( | ||
r1=r1, r2=r2, row_column_names=row_column_names, num_columns=num_columns)) | ||
else: | ||
t.add_row([r1, r2]) | ||
if allRowsEqual == False: | ||
raise chispa.DataFramesNotEqualError("\n" + t.get_string()) | ||
|
||
|
||
def __underline_cells_in_row(r1=Row, r2=Row, row_column_names=List[str], num_columns=int) -> List[str]: | ||
""" | ||
Takes two Row types, a list of column names for the Rows and the length of columns | ||
Returns list of two strings, with underlined columns within rows that are different for PrettyTable | ||
""" | ||
r1_string = "Row(" | ||
r2_string = "Row(" | ||
for index, column in enumerate(row_column_names): | ||
if ((index+1) == num_columns): | ||
append_str = "" | ||
else: | ||
append_str = ", " | ||
|
||
if r1[column] != r2[column]: | ||
r1_string += underline_text( | ||
f"{column}='{r1[column]}'") + f"{append_str}" | ||
r2_string += underline_text( | ||
f"{column}='{r2[column]}'") + f"{append_str}" | ||
else: | ||
r1_string += f"{column}='{r1[column]}'{append_str}" | ||
r2_string += f"{column}='{r2[column]}'{append_str}" | ||
|
||
r1_string += ")" | ||
r2_string += ")" | ||
r_zipped = list(zip_longest(r1.__fields__, r2.__fields__)) | ||
r1_string = [] | ||
r2_string = [] | ||
for r1_field, r2_field in r_zipped: | ||
if r1[r1_field] != r2[r2_field]: | ||
all_rows_equal = False | ||
r1_string.append(format_string(f"{r1_field}={r1[r1_field]}", formats.mismatched_cells)) | ||
r2_string.append(format_string(f"{r2_field}={r2[r2_field]}", formats.mismatched_cells)) | ||
else: | ||
r1_string.append(format_string(f"{r1_field}={r1[r1_field]}", formats.matched_cells)) | ||
r2_string.append(format_string(f"{r2_field}={r2[r2_field]}", formats.matched_cells)) | ||
r1_res = ", ".join(r1_string) | ||
r2_res = ", ".join(r2_string) | ||
|
||
return [bcolors.LightRed + r1_string, r2_string] | ||
t.add_row([r1_res, r2_res]) | ||
if all_rows_equal == False: | ||
raise chispa.DataFramesNotEqualError("\n" + t.get_string()) |
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
Oops, something went wrong.