Find differences between two CSV files based on a specified column identifier. 
from .csvcomparetool import CSVComparer

__version__ = "1.0.3"
__all__ = ["CSVComparer"]


src/csvcomparetool/__init__.py
liquidz00/csv-compare
# Author: liquidz00
# GitHub: https://github.com/liquidz00
#
#
# Written: Sep 08 23

import argparse
from src.csvcomparetool.csvcomparetool import CSVComparer

help_desc = """

CSV Compare Tool // github.com/liquidz00 // AUG 2023

Compare two different CSV files by specifying a column identifier. 

Usage (after navigating to project directory in Terminal): 
python3 cli.py path/to/first.csv path/to/second.csv column

Where 'column' is the column title containing data to compare

"""

def main():
    parser = argparse.ArgumentParser(description=help_desc, formatter_class=argparse.RawTextHelpFormatter)
    parser.add_argument('csv1', '-c1', type=str, help='Path to the first CSV file')
    parser.add_argument('csv2', '-c2', type=str, help='Path to the second CSV file')
    parser.add_argument('column', '-column', type=str, help='Column identifier for both CSVs')

    args = parser.parse_args()

    comparer = CSVComparer(args.csv1, args.csv2, args.column)

    if not comparer.validate_paths():
        print("CSV file paths are invalid. Please check the file paths and try again.")
        return

    if not comparer.validate_columns():
        print("Invalid column. Please check column identifier and try again.")

    differences = comparer.find_differences()

    if differences:
        print("Differences found:")
        for difference in differences:
            print(f"Record '{difference}' is present in CSV2 but not in CSV1.")
    else:
        print("No differences found.")

if __name__ == "__main__":
    main()

src/csvcomparetool/cli.py
liquidz00/csv-compare
# Author: liquidz00
# GitHub: https://github.com/liquidz00
#
#
# Written: Sep 08 23

import pandas as pd
import logging
import os
from typing import Optional, Union

# Logger
logger = logging.getLogger(__name__)

# StrPath
StrPath = Union[str, 'os.PathLike[str]']

class CSVComparer:
    def __init__(self, path_one: Optional[StrPath], path_two: Optional[StrPath], identifier: Optional[str]) -> None:
        self.path_one: Optional[StrPath] = path_one
        self.path_two: Optional[StrPath] = path_two
        self.identifier: Optional[str] = identifier

    def validate_paths(self):
        if not os.path.exists(self.path_one):
            logging.error(f"CSV file not found: {self.path_one}")
            return False
        if not os.path.exists(self.path_two):
            logging.error(f"CSV file not found: {self.path_two}")
            return False
        return True

    def validate_columns(self):
        db_1 = pd.read_csv(self.path_one)
        db_2 = pd.read_csv(self.path_two)

        if self.identifier not in db_1.columns:
            logging.error(f"Column '{self.identifier}' not found in {self.path_one}")
            return False
        if self.identifier not in db_2.columns:
            logging.error(f"Column '{self.identifier}' not found in {self.path_two}")
            return False
        return True

    def find_differences(self):
        if not self.validate_paths() or not self.validate_columns():
            return []

        db_1 = pd.read_csv(self.path_one)
        db_2 = pd.read_csv(self.path_two)

        users_1 = db_1[self.identifier].to_list()
        users_2 = db_2[self.identifier].to_list()

        differences = []

        for user in users_2:
            if user not in users_1:
                differences.append(user)

        return differences

src/csvcomparetool/csvcomparetool.py
liquidz00/csv-compare
import pytest
import os

from src.csvcomparetool.csvcomparetool import CSVComparer

BASE_DIR = os.path.dirname(__file__)

@pytest.fixture
def fruit_csvs():
    fruits1 = os.path.join(BASE_DIR, "fruits1.csv")
    fruits2 = os.path.join(BASE_DIR, "fruits2.csv")

    yield fruits1, fruits2

@pytest.fixture
def title_csvs():
    titles1 = os.path.join(BASE_DIR, "anyorg_old_titles.csv")
    titles2 = os.path.join(BASE_DIR, "anyorg_new_titles.csv")

    yield titles1, titles2

def test_fruits(fruit_csvs):
    csv1, csv2 = fruit_csvs
    col = "Fruit"

    comparer = CSVComparer(csv1, csv2, col).find_differences()

    expected_result = ["Banana"]

    assert comparer == expected_result

def test_titles(title_csvs):
    csv1, csv2 = title_csvs
    col = "Job Title"

    comparer = CSVComparer(csv1, csv2, col).find_differences()

    expected_result = ['Product Designer', 'Data Analyst', 'Software Developer', 'HR Administrator', 'Market Researcher', 'Quality Assurance Specialist', 'Support Specialist', 'Recruitment Manager', 'Public Relations Specialist', 'IT Support Specialist', 'Market Analyst', 'Customer Relations Specialist']

    assert comparer == expected_result

def test_invalid_column(title_csvs):
    with pytest.raises(Exception) as exc_info:
        csv1, csv2 = title_csvs
        CSVComparer(csv1, csv2, identifier="invalid column").find_differences()
        raise Exception("ERROR: Column identifier does not exist. Try again.")

    assert exc_info.value.args[0] == "ERROR: Column identifier does not exist. Try again."





tests/test_csv_comparer.py
liquidz00/csv-compare