diff --git a/README.md b/README.md index cc9274b..28155a5 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,8 @@ Organises Humble Bundle bundles based on their platform. Designed to work around the structure created via Talonius' [hb-downloader](https://github.com/talonius/hb-downloader). Other automated HB downloaders may not work with this out of the box. +![Copying files](media/hb_organiser_demo.png) + ## Install As it's packaged as a Pip module, `python3-pip` is required. Run `pip install --user hb-organiser` to install only for your user and omit `--user` to install for all. See `hb_organiser -h` for help. diff --git a/build/lib/hb_organiser/check.py b/build/lib/hb_organiser/check.py index 9bdc836..b08b32f 100644 --- a/build/lib/hb_organiser/check.py +++ b/build/lib/hb_organiser/check.py @@ -63,9 +63,12 @@ def source_levels(source, target=None): test = 'platform' level = item if target is not None: - abspath(f"{level}/{target}") + platform = abspath(f"{level}/{target}/") else: - Path(list(level.glob('*'))[0]) + platform = Path(list(level.glob('*'))[0]) + if not isdir(platform): + print(f"ERROR: detecting file: {platform} as platform directory") + return False return True except IndexError: print(f"ERROR: could not determine {test} directory in \"{level}\"") @@ -83,7 +86,9 @@ def number_of_items(source, filters): :return: :rtype: int """ + print("[ / ] INFO: Calculating relevant items in library\r", end="", flush=True) library = Library(source.split('/')[-1], source) + print(f"[ /{library.items}] INFO: Calculating relevant items in library\r", end="", flush=True) items = 0 for bundle in library.contents: @@ -100,4 +105,5 @@ def number_of_items(source, filters): if current_file.platform in filters and current_file.filetype != 'md5'\ or 'all' in filters and current_file.filetype != 'md5': items += 1 + print(f"[{items}/{library.items}] DONE: Calculating relevant items in library", flush=True) return items diff --git a/build/lib/hb_organiser/cli.py b/build/lib/hb_organiser/cli.py index 7cebf5a..f8515b7 100644 --- a/build/lib/hb_organiser/cli.py +++ b/build/lib/hb_organiser/cli.py @@ -12,6 +12,11 @@ def cli(): + """ + Contains the code pertaining to the CLI. All back-end logic is located elsewhere. + + :return: + """ parser = argparse.ArgumentParser(description="organises humble bundle bundles based on their platform.") parser.add_argument( "platform", nargs="+", type=str, diff --git a/build/lib/hb_organiser/organiser.py b/build/lib/hb_organiser/organiser.py index ba2edb4..98bf9ab 100644 --- a/build/lib/hb_organiser/organiser.py +++ b/build/lib/hb_organiser/organiser.py @@ -15,7 +15,9 @@ class HBOrganiser: Main program. Contains the methods used to organise the library. """ def __init__(self, source, destination=None, *filtered_platforms): # pylint: disable=keyword-arg-before-vararg + print("INFO: Connecting to library\r", end="") self.library = Library(source.split('/')[-1], source) + print("DONE: Connecting to library\r", end="", flush=True) self.destination = destination # TODO: clean this up. by default it would be a list within a list: [['all']] @@ -81,7 +83,6 @@ def loop_through_bundles(self): :rtype: bool """ try: # pylint: disable=too-many-nested-blocks - print(f"library items: {self.tasks}") task = 1 # Go through every bundle in library for bundle in self.library.contents: diff --git a/build/lib/tests/test_checks.py b/build/lib/tests/test_checks.py index da0ed9e..1e1ea40 100644 --- a/build/lib/tests/test_checks.py +++ b/build/lib/tests/test_checks.py @@ -1,34 +1,44 @@ from unittest import TestCase -from check import * +from hb_organiser.check import * class HBOrganiserTestCase(TestCase): - # === [ check_source_exists ] === # - def test_check_source_exists_returns_false_on_empty_path(self): + # === [ source_exists ] === # + def test_source_exists_returns_false_on_empty_path(self): self.assertFalse(source_exists('')) - def test_check_source_exists_returns_false_on_relative_bad_path(self): + def test_source_exists_returns_false_on_relative_bad_path(self): self.assertFalse(source_exists('~/fake_dir/')) - def test_check_source_exists_returns_false_on_absolute_bad_path(self): + def test_source_exists_returns_false_on_absolute_bad_path(self): self.assertFalse(source_exists('/home/fake_user/fake_dir/')) - def test_check_source_exists_returns_true_on_relative_good_path(self): - self.assertTrue(source_exists('library/')) + def test_source_exists_returns_true_on_relative_good_path(self): + self.assertTrue(source_exists('tests/test_libraries/library/')) - def test_check_source_exists_returns_true_on_absolute_good_path(self): + def test_source_exists_returns_true_on_absolute_good_path(self): self.assertTrue(source_exists('/')) - # === [ check_source_levels ] === # - def test_check_source_levels_returns_false_on_no_platform(self): - self.assertFalse(source_levels('library/bundle/')) + # === [ source_levels ] === # + def test_source_levels_returns_false_on_no_platform(self): + self.assertFalse(source_levels('tests/test_libraries/library/bundle/')) - def test_check_source_levels_returns_false_on_no_item(self): - self.assertFalse(source_levels('library/bundle/item/')) + def test_source_levels_returns_false_on_no_item(self): + self.assertFalse(source_levels('tests/test_libraries/library/bundle/item/')) - def test_check_source_levels_returns_false_on_no_bundle(self): - self.assertFalse(source_levels('library/bundle/item/platform/')) + def test_source_levels_returns_false_on_no_bundle(self): + self.assertFalse(source_levels('tests/test_libraries/library/bundle/item/platform/')) - def test_check_source_levels_return_true_on_good_path(self): - self.assertTrue('library/') + def test_source_levels_return_true_on_good_path(self): + self.assertTrue(source_levels('tests/test_libraries/library/')) + + def test_source_levels_return_true_when_target_set(self): + self.assertTrue(source_levels('tests/test_libraries/library/', 'bundle')) + + # === [ number_of_items ] === # + def test_number_of_items_returns_zero_ignoring_directories(self): + self.assertEqual(number_of_items('tests/test_libraries/library/', ['all']), 1) + + def test_number_of_items_returns_one_ignoring_md5_and_directories(self): + self.assertEqual(number_of_items('tests/test_libraries/other_library/', ['all']), 1) diff --git a/dist/hb_organiser-0.0.6-py3-none-any.whl b/dist/hb_organiser-0.0.6-py3-none-any.whl new file mode 100644 index 0000000..87bb806 Binary files /dev/null and b/dist/hb_organiser-0.0.6-py3-none-any.whl differ diff --git a/dist/hb_organiser-0.0.6.tar.gz b/dist/hb_organiser-0.0.6.tar.gz new file mode 100644 index 0000000..698b111 Binary files /dev/null and b/dist/hb_organiser-0.0.6.tar.gz differ diff --git a/hb_organiser.egg-info/PKG-INFO b/hb_organiser.egg-info/PKG-INFO index ef26da1..89e76eb 100644 --- a/hb_organiser.egg-info/PKG-INFO +++ b/hb_organiser.egg-info/PKG-INFO @@ -1,17 +1,28 @@ Metadata-Version: 2.1 Name: hb-organiser -Version: 0.0.5 +Version: 0.0.6 Summary: Organises Humble Bundle bundles based on their platform. Home-page: https://github.com/WhaleJ84/hb_organiser Author: James Whale Author-email: james@james-whale.com License: UNKNOWN -Description: # hb_organiser +Description: # hb\_organiser + + [![PyPI](https://img.shields.io/pypi/v/hb-organiser.svg)](https://pypi.python.org/pypi/hb-organiser) + ![Unittests](https://github.com/WhaleJ84/hb_organiser/workflows/Unittests/badge.svg) + [![codecov](https://codecov.io/gh/WhaleJ84/hb_organiser/branch/main/graph/badge.svg?token=IJSKBUAP81)](https://codecov.io/gh/WhaleJ84/hb_organiser) + ![Pylint](https://github.com/WhaleJ84/hb_organiser/workflows/Pylint/badge.svg) Organises Humble Bundle bundles based on their platform. Designed to work around the structure created via Talonius' [hb-downloader](https://github.com/talonius/hb-downloader). Other automated HB downloaders may not work with this out of the box. + ![Copying files](media/hb_organiser_demo.png) + + ## Install + + As it's packaged as a Pip module, `python3-pip` is required. Run `pip install --user hb-organiser` to install only for your user and omit `--user` to install for all. See `hb_organiser -h` for help. + ## Why is this needed? I mainly use Humble Bundle to purchase book bundles (that I'll totally read at some point, I swear!) and have accumulated thousands of books over the years. @@ -20,14 +31,19 @@ Description: # hb_organiser To alleviate this issue, I'm making this script that will organise my libraries with a click of a key. Duplicate items across different bundles will be ignored, all the books will be easily discovered via Calibre, and my sanity will be saved. + ## Features + + - Calculates number of tasks so that you're not left in the dark and can tell the progress. + + - A crude way of tracking files being corrupted via a cancelled transfer by logging what is being operated upon and clearing it once complete. If it doesn't get cleared, chances are it was corrupted. + + - Skips copying of duplicate files by checking for its existence first (although there is a chance it may skip newer files such as updated editions of books (see [issue 6](https://github.com/WhaleJ84/hb_organiser/issues/6))). + ## Immediate roadmap The immediate goal is to put out something working. To keep development more direct I'll outline pressing matters below: - - Publish Pip module - - At the moment it currently runs as a series of scripts. - This needs to change ASAP. - Cut down on operation times - Organising thousands of files in one go is very time-consuming - especially when working with game bundles. Speeding this up will save millions of hours of collective time over the years via optimisation. diff --git a/hb_organiser/check.py b/hb_organiser/check.py index b35d5ab..b08b32f 100644 --- a/hb_organiser/check.py +++ b/hb_organiser/check.py @@ -86,7 +86,9 @@ def number_of_items(source, filters): :return: :rtype: int """ + print("[ / ] INFO: Calculating relevant items in library\r", end="", flush=True) library = Library(source.split('/')[-1], source) + print(f"[ /{library.items}] INFO: Calculating relevant items in library\r", end="", flush=True) items = 0 for bundle in library.contents: @@ -103,4 +105,5 @@ def number_of_items(source, filters): if current_file.platform in filters and current_file.filetype != 'md5'\ or 'all' in filters and current_file.filetype != 'md5': items += 1 + print(f"[{items}/{library.items}] DONE: Calculating relevant items in library", flush=True) return items diff --git a/hb_organiser/organiser.py b/hb_organiser/organiser.py index ba2edb4..98bf9ab 100644 --- a/hb_organiser/organiser.py +++ b/hb_organiser/organiser.py @@ -15,7 +15,9 @@ class HBOrganiser: Main program. Contains the methods used to organise the library. """ def __init__(self, source, destination=None, *filtered_platforms): # pylint: disable=keyword-arg-before-vararg + print("INFO: Connecting to library\r", end="") self.library = Library(source.split('/')[-1], source) + print("DONE: Connecting to library\r", end="", flush=True) self.destination = destination # TODO: clean this up. by default it would be a list within a list: [['all']] @@ -81,7 +83,6 @@ def loop_through_bundles(self): :rtype: bool """ try: # pylint: disable=too-many-nested-blocks - print(f"library items: {self.tasks}") task = 1 # Go through every bundle in library for bundle in self.library.contents: diff --git a/media/hb_organiser_demo.png b/media/hb_organiser_demo.png new file mode 100644 index 0000000..aa3636f Binary files /dev/null and b/media/hb_organiser_demo.png differ diff --git a/setup.py b/setup.py index 9dfe951..b5a54d3 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setuptools.setup( name="hb_organiser", - version="0.0.5", + version="0.0.6", author="James Whale", author_email="james@james-whale.com", description="Organises Humble Bundle bundles based on their platform.",