diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9c6be00..6cb4e7a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,46 +1,59 @@ +ci: + skip: [pylint] + repos: -- repo: https://github.com/myint/autoflake + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.3.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - repo: https://github.com/myint/autoflake rev: v1.4 hooks: - - id: autoflake + - id: autoflake args: - - --in-place - - --remove-all-unused-imports - - --expand-star-imports - - --remove-duplicate-keys - - --remove-unused-variables -- repo: https://github.com/ambv/black - rev: 20.8b1 - hooks: - - id: black -- repo: https://github.com/pre-commit/pre-commit-hooks - rev: v3.4.0 - hooks: - - id: check-merge-conflict - - id: trailing-whitespace - - id: end-of-file-fixer - - id: check-json - - id: check-xml - - id: check-yaml -- repo: https://gitlab.com/pycqa/flake8 - rev: 3.8.4 - hooks: - - id: flake8 -- repo: https://github.com/PyCQA/isort - rev: 5.7.0 - hooks: - - id: isort -- repo: local - hooks: - - id: pylint + - --in-place + - --remove-all-unused-imports + - --expand-star-imports + - --remove-duplicate-keys + - --remove-unused-variables + - repo: https://github.com/asottile/pyupgrade + rev: v2.34.0 + hooks: + - id: pyupgrade + exclude: tests/testdata + args: [--py36-plus] + - repo: https://github.com/PyCQA/isort + rev: 5.10.1 + hooks: + - id: isort + exclude: tests/testdata + - repo: https://github.com/Pierre-Sassoulas/black-disable-checker/ + rev: v1.1.0 + hooks: + - id: black-disable-checker + - repo: https://github.com/psf/black + rev: 22.6.0 + hooks: + - id: black + args: [--safe, --quiet] + - repo: https://github.com/PyCQA/flake8 + rev: 4.0.1 + hooks: + - id: flake8 + additional_dependencies: [flake8-bugbear, flake8-typing-imports==1.12.0] + - repo: local + hooks: + - id: pylint name: pylint entry: pylint language: system types: [python] -- repo: https://github.com/pre-commit/mirrors-mypy - rev: v0.800 + args: ["-rn", "-sn"] + - repo: https://github.com/pre-commit/mirrors-mypy + rev: v0.961 hooks: - - id: mypy + - id: mypy name: mypy entry: mypy language: python @@ -48,3 +61,8 @@ repos: args: ["--ignore-missing-imports", "--scripts-are-modules"] require_serial: true additional_dependencies: [] + - repo: https://github.com/pre-commit/mirrors-prettier + rev: v2.7.1 + hooks: + - id: prettier + args: [--prose-wrap=always, --print-width=88] diff --git a/README.md b/README.md index ca8721d..fdc1b92 100644 --- a/README.md +++ b/README.md @@ -140,6 +140,7 @@ plt.savefig('customers-goods.png', bbox_inches='tight') # to save ![Customer goods](pysankey/customers-goods.png) Similar to seaborn, you can pass a matplotlib `Axes` to `sankey` function: + ```python import pandas as pd from pysankey import sankey @@ -169,20 +170,27 @@ plt.show() ## Important informations -Use of `figureName`, `closePlot`, `figSize` in `sankey()` is deprecated and will be remove in a future version. -This is done so matplotlib is used more transparently as this [issue](https://github.com/anazalea/pySankey/issues/26#issue-429312025) on the original github repo suggested. +Use of `figureName`, `closePlot`, `figSize` in `sankey()` is deprecated and will be +remove in a future version. This is done so matplotlib is used more transparently as +this [issue](https://github.com/anazalea/pySankey/issues/26#issue-429312025) on the +original github repo suggested. -Now, `sankey` does less of the customization and let the user do it to their liking by returning a matplotlib `Axes` object, which mean the user also has access to the `Figure` to customise. -Then they can choose what to do with it - showing it, saving it with much more flexibility. +Now, `sankey` does less of the customization and let the user do it to their liking by +returning a matplotlib `Axes` object, which mean the user also has access to the +`Figure` to customise. Then they can choose what to do with it - showing it, saving it +with much more flexibility. ### Recommended changes to your code - - To save a figure, one can simply do: - ```python - plt.savefig(".png", bbox_inches="tight", dpi=150) - ``` - - The `closePlot` is not needed anymore because without `plt.show()` after `sankey()`, no plot is displayed. - You can still do `plt.close()` to be sure to not display this plot if you display other plots afterwards. +- To save a figure, one can simply do: + +```python + plt.savefig(".png", bbox_inches="tight", dpi=150) +``` + +- The `closePlot` is not needed anymore because without `plt.show()` after `sankey()`, + no plot is displayed. You can still do `plt.close()` to be sure to not display this + plot if you display other plots afterwards. - You can modify the sankey size by changing the one from the matplotlib figure. ```python @@ -195,14 +203,14 @@ Then they can choose what to do with it - showing it, saving it with much more f ### Lint - pylint pysankey + pylint pysankey ### Testing - python -m unittest + python -m unittest ### Coverage - coverage run -m unittest - coverage html - # Open htmlcov/index.html in a navigator + coverage run -m unittest + coverage html + # Open htmlcov/index.html in a navigator diff --git a/pysankey/sankey.py b/pysankey/sankey.py index 371f893..c00d6f8 100644 --- a/pysankey/sankey.py +++ b/pysankey/sankey.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- r""" Produces simple Sankey Diagrams with matplotlib. @author: Anneya Golob & marcomanz & pierre-sassoulas & jorwoods & vgalisson @@ -29,7 +28,7 @@ class PySankeyException(Exception): - """ Generic PySankey Exception. """ + """Generic PySankey Exception.""" class NullsInFrame(PySankeyException): @@ -57,9 +56,7 @@ def check_data_matches_labels(labels, data, side): msg = "Labels: " + ",".join(labels) + "\n" if len(data) < 20: msg += "Data: " + ",".join(data) - raise LabelMismatch( - "{0} labels and data do not match.{1}".format(side, msg) - ) + raise LabelMismatch(f"{side} labels and data do not match.{msg}") def sankey( @@ -159,7 +156,7 @@ def sankey( def save_image(figureName): if figureName is not None: - fileName = "{}.png".format(figureName) + fileName = f"{figureName}.png" plt.savefig(fileName, bbox_inches="tight", dpi=150) LOGGER.info("Sankey diagram generated in '%s'", fileName) @@ -386,7 +383,7 @@ def plot_strips( def _get_positions_and_total_widths(df, labels, side): - """ Determine positions of label patches and total widths""" + """Determine positions of label patches and total widths""" widths = defaultdict() for i, label in enumerate(labels): labelWidths = {} diff --git a/pysankey/tests/generic_test.py b/pysankey/tests/generic_test.py index 2ee229c..c5c03e8 100644 --- a/pysankey/tests/generic_test.py +++ b/pysankey/tests/generic_test.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - import os import unittest @@ -20,7 +18,7 @@ def setUpClass(cls): cls.colorDict = "" def tearDown(self): - path = "{}.png".format(self.figure_name) + path = f"{self.figure_name}.png" # Comment this to check the resulting image if os.path.exists(path): os.remove(path) @@ -28,7 +26,7 @@ def tearDown(self): class TestFruit(GenericTest): - """ Base test to test with the data in fruit.txt """ + """Base test to test with the data in fruit.txt""" def setUp(self): self.figure_name = "fruit" @@ -47,7 +45,7 @@ def setUp(self): class TestCustomerGood(GenericTest): - """ Base test to test with the data in customers-goods.csv """ + """Base test to test with the data in customers-goods.csv""" def setUp(self): self.figure_name = "customer-good" diff --git a/pysankey/tests/test_create_dataframe.py b/pysankey/tests/test_create_dataframe.py index 1ad73e4..8cdbf46 100644 --- a/pysankey/tests/test_create_dataframe.py +++ b/pysankey/tests/test_create_dataframe.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import pandas as pd from pysankey.sankey import create_datadrame @@ -7,7 +6,7 @@ class TestCreateDataframeCustomerGood(TestCustomerGood): - """ Tests the create_dataframe function on the data in customers-goods.csv""" + """Tests the create_dataframe function on the data in customers-goods.csv""" def test_dataframe_correct_type(self): dataframe = create_datadrame( @@ -20,8 +19,8 @@ def test_dataframe_correct_type(self): def test_sorted_dataframe(self): """ - Tests that if we pass a sorted dataframe, it doesn't change the values due to an index - mismatch + Tests that if we pass a sorted dataframe, it doesn't change the values due to + an index mismatch. """ # Pass the data as is dataframe = create_datadrame( @@ -40,5 +39,8 @@ def test_sorted_dataframe(self): rightWeight=data_sorted["revenue"], ) - # Check that the values are still the same if we sort both dataframes the same way - assert (dataframe.sort_values(by="leftWeight").values == dataframe_sorted.values).all() + # Check that the values are still the same if we sort both dataframes + # the same way + assert ( + dataframe.sort_values(by="leftWeight").values == dataframe_sorted.values + ).all() diff --git a/pysankey/tests/test_deprecated.py b/pysankey/tests/test_deprecated.py index 4ef3eae..57b0046 100644 --- a/pysankey/tests/test_deprecated.py +++ b/pysankey/tests/test_deprecated.py @@ -1,15 +1,13 @@ -# -*- coding: utf-8 -*- - from pysankey import sankey from pysankey.tests.generic_test import TestFruit class TestErrorCase(TestFruit): - """ Test sankey's deprecation warnings. """ + """Test sankey's deprecation warnings.""" def test_deprecated_parameters(self): - """ Test if deprecation warnings are correctly triggered """ + """Test if deprecation warnings are correctly triggered""" with self.assertWarns(DeprecationWarning): sankey( self.data["true"], diff --git a/pysankey/tests/test_error_case.py b/pysankey/tests/test_error_case.py index eb43bd5..65f4e72 100644 --- a/pysankey/tests/test_error_case.py +++ b/pysankey/tests/test_error_case.py @@ -1,22 +1,20 @@ -# -*- coding: utf-8 -*- - from pysankey import LabelMismatch, NullsInFrame, sankey from pysankey.tests.generic_test import TestFruit class TestErrorCase(TestFruit): - """ Test sankey's error case. """ + """Test sankey's error case.""" def test_bad_color_labels(self): - """ sankey raise a value error when there is not enough color info""" + """sankey raise a value error when there is not enough color info""" bad_color_dict = {"apple": "#f71b1b", "orange": "#f78c1b"} with self.assertRaises(ValueError) as value_error: sankey(self.data["true"], self.data["predicted"], colorDict=bad_color_dict) self.assertIn(": lime, blueberry, banana, kiwi", str(value_error.exception)) def test_label_mismatch(self): - """ sankey raises a LabelMismatch when data doesn't match the labels""" + """sankey raises a LabelMismatch when data doesn't match the labels""" with self.assertRaises(LabelMismatch): sankey( self.data["true"], @@ -26,6 +24,6 @@ def test_label_mismatch(self): ) def test_nulls_in_frame(self): - """ sankey raises a NullsInFrame when left or right data is null""" + """sankey raises a NullsInFrame when left or right data is null""" with self.assertRaises(NullsInFrame): sankey([None], self.data["predicted"]) diff --git a/pysankey/tests/test_readme.py b/pysankey/tests/test_readme.py index a3aca36..6d09afa 100644 --- a/pysankey/tests/test_readme.py +++ b/pysankey/tests/test_readme.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - import matplotlib.pyplot as plt from pysankey import sankey @@ -8,7 +6,7 @@ class TestReadmeFruit(TestFruit): - """ Test use case from README with the data in fruit.txt""" + """Test use case from README with the data in fruit.txt""" def test_no_fail_readme(self): ax = sankey( @@ -23,7 +21,7 @@ def test_no_fail_readme(self): class TestReadmeCustomerGood(TestCustomerGood): - """ Test use case from README with the data in customer-goods.csv""" + """Test use case from README with the data in customer-goods.csv""" def test_no_fail_readme(self): weight = self.data["revenue"].values[1:].astype(float) diff --git a/pysankey/tests/test_sankey.py b/pysankey/tests/test_sankey.py index 580d734..0c0c9ef 100644 --- a/pysankey/tests/test_sankey.py +++ b/pysankey/tests/test_sankey.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - import matplotlib.pyplot as plt from pysankey import sankey diff --git a/setup.py b/setup.py index bbd39ac..a2b9e25 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ import setuptools -with open("README.md", "r", encoding="UTF-8") as fh: +with open("README.md", encoding="UTF-8") as fh: long_description = fh.read() TEST_REQUIRES = ["pylint", "coverage", "coveralls", "pre-commit", "pytest-cov"]