Skip to content

ivnvxd/python-project-50

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

69 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

logo

Difference Generator

Calculate the difference between two files

Actions Status Lint and test check Maintainability Test Coverage

AboutInstallationUsageDemoAdditionally

Table of Contents

About

Difference Generator is a tool that determines the difference between two data structures. This is a popular task, for which there are many online services, such as http://www.jsondiff.com/.

Such a mechanism, for example, is used when outputting tests or when automatically tracking changes in configuration files.

Example:

gendiff --format plain filepath1.json filepath2.yml

Setting "common.setting4" was added with value: False
Setting "group1.baz" was updated. From 'bas' to 'bars'
Section "group2" was removed

Features:

  • Supported file formats: JSON, YAML.
  • Output as plain text, structured text or JSON.
  • Can be used as CLI tool or external library.

Built With

  • Python
  • Poetry
  • PyYAML
  • JSON
  • Pytest
  • flake8
  • argparse

Installation

Prerequisites

Python

Before installing the package make sure you have Python version 3.8 or higher installed:

>> python --version
Python 3.8.0+

Poetry

The project uses the Poetry dependency manager. To install Poetry use its official instruction.

Package

To use the package, you need to clone the repository to your computer. This is done using the git clone command. Clone the project:

>> git clone https://github.com/venyxD/python-project-50.git

Then you have to build the package and install it:

>> cd python-project-50
>> poetry build
>> python3 -m pip install --user dist/*.whl

Usage

Difference Generator can be used as CLI tool or as an external library.

As external library

from gendiff import generate_diff
diff = generate_diff(file_path1, file_path2, file_format)

As CLI tool

The general usage is (both absolute and relative paths to files are supported):

>> gendiff [-f file_format] file_path1 file_path2

Difference Generator provides help command as well:

>> gendiff --help

usage: gendiff [-h] [-f {stylish,plain,json}] first_file second_file

Compares two configuration files and shows a difference.

positional arguments:
  first_file
  second_file

options:
  -h, --help            show this help message and exit
  -f {stylish,plain,json}, --format {stylish,plain,json}
                        set format of output (default: 'stylish')

Demo

Stylish format

If no format option is provided, output will be provided in stylish format.

The difference is based on how the files have changed relative to each other, the keys are rendered in alphabetical order.

The absence of a plus or minus indicates that the key is in both files, and its values coincide. In all other situations, the value of the key is either different, or the key is only in one file.

>> gendiff file_path1.json file_path2.json

{
  - follow: false
    host: hexlet.io
  - proxy: 123.234.53.22
  - timeout: 50
  + timeout: 20
  + verbose: true
}

♦️ Compare two flat JSON and/or YAML files: stylish format

♦️ Compare two nested JSON and/or YAML files: stylish format

Plain format

Plain format reflects the situation as if we had combined the second object with the first one.

  • If the new value of the property is a complex value, [complex value] is provided.
  • If the property is nested, then the entire path to the root is displayed, not just including the parent.
>> gendiff --format plain file_path1.json file_path2.json

Property 'follow' was removed
Property 'proxy' was removed
Property 'timeout' was updated. From 50 to 20
Property 'verbose' was added with value: true

♦️ Compare two flat JSON and/or YAML files: plain format

♦️ Compare two nested JSON and/or YAML files: plain format

JSON format

In addition to an unstructured output (as a text), often an output in a structured format, such as JSON, is needed.

JSON (JavaScript Object Notation) is a standard text format for representing structured data based on JavaScript object syntax. It is usually used to transfer data in web applications (e.g. sending some data from the server to the client so that it can be displayed on a web page or vice versa).

>> gendiff --format json file_path1.json file_path2.json

{
    "follow": {
        "value": false,
        "type": "removed"
    },
    "host": {
        "value": "hexlet.io",
        "type": "unchanged"
    },
    "proxy": {
        "value": "123.234.53.22",
        "type": "removed"
    },
    "timeout": {
        "value": 50,
        "new value": 20,
        "type": "updated"
    },
    "verbose": {
        "value": true,
        "type": "added"
    }
}

♦️ Compare two flat JSON and/or YAML files: JSON format

♦️ Compare two nested JSON and/or YAML files: JSON format


Additionally

Dependencies

  • python = "^3.10"
  • PyYAML = "^6.0"

Dev Dependencies

  • flake8 = "^5.0.4"
  • pytest = "^7.2.0"
  • pytest-cov = "^4.0.0"

Makefile Commands

make build
Build the Poetry package.
make package-install
Install the package in the user's environment.
make package-reinstall
Reinstall the package in the user's environment.
make lint
Check code with flake8 linter.
make test
Run tests.
make check
Validate structure of pyproject.toml file, check code with tests and linter.

Project Tree
.
├── Makefile
├── README.md
├── coverage.xml
├── gendiff
│   ├── __init__.py
│   ├── constants.py
│   ├── diff.py
│   ├── file_handler.py
│   ├── find_diff.py
│   ├── formatters
│   │   ├── render.py
│   │   ├── render_json.py
│   │   ├── render_plain.py
│   │   └── render_stylish.py
│   ├── parse_cli.py
│   └── scripts
│       ├── __init__.py
│       └── gendiff.py
├── poetry.lock
├── pyproject.toml
├── setup.cfg
└── tests
    ├── fixtures
    │   ├── json
    │   │   └── ...
    │   ├── result
    │   │   └── ...
    │   └── yaml
    │       └── ...
    ├── test_cli_parse.py
    └── test_gendiff.py

:octocat: This is the second training project of the "Python Developer" course on Hexlet.io

GitHub @ivnvxd  ·  LinkedIn @Andrey Ivanov