From 58c2fe19c245d123f6e41901ab96fea52a5ccd3f Mon Sep 17 00:00:00 2001 From: iwishiwasaneagle Date: Mon, 7 Mar 2022 10:23:28 +0000 Subject: [PATCH 01/17] bring classifier up to speed with current tools --- .github/workflows/CI.yml | 42 ++++++++++++++++++++++ classifier/__init__.py | 15 ++++++++ classifier/classifier.py | 9 +++-- pyproject.toml | 6 ++++ requirements.txt | 4 +++ setup.cfg | 77 ++++++++++++++++++++++++++++++++++++++++ setup.py | 33 ++++++++--------- tests/requirements.txt | 2 ++ tox.ini | 30 ++++++++++++++++ 9 files changed, 197 insertions(+), 21 deletions(-) create mode 100644 .github/workflows/CI.yml create mode 100644 pyproject.toml create mode 100644 requirements.txt create mode 100644 setup.cfg create mode 100644 tests/requirements.txt create mode 100644 tox.ini diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml new file mode 100644 index 0000000..f7d166a --- /dev/null +++ b/.github/workflows/CI.yml @@ -0,0 +1,42 @@ +name: CI + +on: + push: + branches: [master, dev] + pull_request: + workflow_dispatch: + +jobs: + run-tests: + runs-on: ${{matrix.platform}} + strategy: + matrix: + platform: [ubuntu-latest, macos-latest, windows-latest] + python-version: ["3.7", "3.8", "3.9"] + steps: + - uses: actions/checkout@v2 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + + - uses: actions/cache@v2 + id: cache-tox-tests + with: + path: .tox + key: ${{ runner-os }}-${{ matrix.python-version }}-venv-${{ hashFiles('requirements.txt') }}-${{ hashFiles('tests/requirements.txt') }}-${{ hashFiles('setup.cfg') }} + restore-keys: | + ${{ runner.os }}-tox-tests + + - run: pip install tox + + - name: Run tox + run: tox + + - uses: codecov/codecov-action@v2.1.0 + if: "${{matrix.platform}}-${{matrix.python-version}}" == "ubuntu-latest-3.9" + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: coverage.xml + fail_ci_if_error: true \ No newline at end of file diff --git a/classifier/__init__.py b/classifier/__init__.py index e69de29..413503b 100644 --- a/classifier/__init__.py +++ b/classifier/__init__.py @@ -0,0 +1,15 @@ +import sys + +if sys.version_info[:2] >= (3, 8): + from importlib.metadata import PackageNotFoundError, version # pragma: no cover +else: + from importlib_metadata import PackageNotFoundError, version # pragma: no cover + +try: + # Change here if project is renamed and does not equal the package name + dist_name = __name__ + __version__ = version(dist_name) +except PackageNotFoundError: # pragma: no cover + __version__ = "unknown" +finally: + del version, PackageNotFoundError \ No newline at end of file diff --git a/classifier/classifier.py b/classifier/classifier.py index bd22471..a89a793 100755 --- a/classifier/classifier.py +++ b/classifier/classifier.py @@ -2,12 +2,13 @@ """ Classifier ----------------Contributors---------------- - https://github.com/bhrigu123/classifier/graphs/contributors + https://github.com/iwishiwasaneagle/classifier/graphs/contributors ----------------Maintainer---------------- - Bhrigu Srivastava + Jan-Hendrik Ewers ----------------License---------------- The MIT License [https://opensource.org/licenses/MIT] Copyright (c) 2015 Bhrigu Srivastava http://bhrigu.me + Copyright (c) 2022 Jan-Hendrik Ewers https://janhendrikewers.uk """ @@ -18,7 +19,7 @@ import sys -VERSION = 'Classifier 2.0' +VERSION = 'Classifier 3.0' DIRCONFFILE = '.classifier.conf' PLATFORM = sys.platform OS = os.name @@ -288,3 +289,5 @@ def run(self): print("Done!\n") return True +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..89157ad --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,6 @@ +[build-system] +# AVOID CHANGING REQUIRES: IT WILL BE UPDATED BY PYSCAFFOLD! +requires = ["setuptools>=46.1.0", "wheel", "setuptools_scm>=6.2"] +build-backend = "setuptools.build_meta" + +[tool.setuptools_scm] \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..2688e73 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +arrow==1.2.2 +loguru==0.6.0 +python-dateutil==2.8.2 +six==1.16.0 diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..9cb076f --- /dev/null +++ b/setup.cfg @@ -0,0 +1,77 @@ +[metadata] +name = classifier +description = Classify the files in your Downloads folder into suitable destinations +author=Bhrigu Srivastava +author_email=captain.bhrigu@gmail.com +maintainer=Jan-Hendrik Ewers +maintainer_email=dev.jh.ewers@gmail.com +license = MIT +license_files = LICENSE.txt +long_description = file: README.md +long_description_content_type = text/markdown; charset=UTF-8; variant=GFM +url = https://github.com/iwishiwasaneagle/classifier/ +# Add here related links, for example: +project_urls = + Source = "https://github.com/iwishiwasaneagle/classifier" + + +# Add here all kinds of additional classifiers as defined under +# https://pypi.org/classifiers/ +classifiers = + Development Status :: 5 - Production/Stable + License :: OSI Approved :: MIT License + Operating System :: OS Independent + + +[options] +zip_safe = False +packages = find_namespace: +include_package_data = True + +# Require a min/specific Python version (comma-separated conditions) +# python_requires = >=3.8 + +install_requires = + importlib-metadata; python_version<"3.8" + loguru==0.6.0 + arrow==1.2.2 + + +[options.packages.find] +where = src +exclude = + tests + +[options.extras_require] +test = + setuptools + pytest + pytest-cov + tox + +[options.entry_points] +console_scripts = + classifier = classifier.classifier:main + +[tool:pytest] +addopts = + --cov jpdmgen --cov-report term-missing + --verbose +norecursedirs = + dist + build + .tox +testpaths = tests + +[flake8] +max_line_length = 88 +extend_ignore = E203, W503 +# ^ Black-compatible +# E203 and W503 have edge cases handled by black +exclude = + .tox + build + dist + .eggs + docs/conf.py +per-file-ignores = "**/__init__.py:F401" # Unused import errors \ No newline at end of file diff --git a/setup.py b/setup.py index 58d88f3..fb1c164 100644 --- a/setup.py +++ b/setup.py @@ -1,20 +1,17 @@ +""" + Setup file for classifier. + Use setup.cfg to configure your project. +""" from setuptools import setup -setup( - name="classifier", - version="2.0", - description="Classify the files in your Downloads folder into suitable destinations.", - url="http://github.com/bhrigu123/classifier", - author="Bhrigu Srivastava", - author_email="captain.bhrigu@gmail.com", - license='MIT', - packages=["classifier"], - entry_points=""" - [console_scripts] - classifier = classifier.classifier:main - """, - install_requires=[ - 'arrow' - ], - zip_safe=False -) +if __name__ == "__main__": + try: + setup() + except: # noqa + print( + "\n\nAn error occurred while building the project, " + "please ensure you have the most updated version of setuptools, " + "setuptools_scm and wheel with:\n" + " pip install -U setuptools setuptools_scm wheel\n\n" + ) + raise \ No newline at end of file diff --git a/tests/requirements.txt b/tests/requirements.txt new file mode 100644 index 0000000..cffeec6 --- /dev/null +++ b/tests/requirements.txt @@ -0,0 +1,2 @@ +pytest +pytest-cov \ No newline at end of file diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..3746756 --- /dev/null +++ b/tox.ini @@ -0,0 +1,30 @@ +[tox] +minversion = 3.15 +envlist = test-py39 +isolated_build = True + + +[testenv] +description = + test: Invoke pytest to run automated tests +setenv = + MODULE = {toxinidir} +extras = + testing +commands = + test: pytest {posargs} --cov-report=xml --cov-branch --cov jpdmgen --cov-report term-missing +deps = + -r {toxinidir}/requirements.txt + -r {toxinidir}/tests/requirements.txt + +[testenv:{build,clean}] +description = + build: Build the package in isolation according to PEP517, see https://github.com/pypa/build + clean: Remove old distribution files and temporary build artifacts (./build and ./dist) +skip_install = True +changedir = {toxinidir} +deps = + build: build[virtualenv] +commands = + clean: python -c 'from shutil import rmtree; rmtree("build", True); rmtree("dist", True)' + build: python -m build . From fde410c98eb45b9ec2c9568833e947f24905d017 Mon Sep 17 00:00:00 2001 From: Jan-Hendrik Ewers Date: Mon, 7 Mar 2022 10:26:13 +0000 Subject: [PATCH 02/17] Update CI.yml --- .github/workflows/CI.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index f7d166a..9c012b0 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -35,8 +35,8 @@ jobs: run: tox - uses: codecov/codecov-action@v2.1.0 - if: "${{matrix.platform}}-${{matrix.python-version}}" == "ubuntu-latest-3.9" + if: ${{matrix.platform =="ubuntu-latest" $$ matrix.python-version == "3.9"}} with: token: ${{ secrets.CODECOV_TOKEN }} files: coverage.xml - fail_ci_if_error: true \ No newline at end of file + fail_ci_if_error: true From 01d91997fe6f2b2e3fb269b407acf2316e622d6b Mon Sep 17 00:00:00 2001 From: Jan-Hendrik Ewers Date: Mon, 7 Mar 2022 10:27:17 +0000 Subject: [PATCH 03/17] Update CI.yml --- .github/workflows/CI.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 9c012b0..eab7fc2 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -25,7 +25,7 @@ jobs: id: cache-tox-tests with: path: .tox - key: ${{ runner-os }}-${{ matrix.python-version }}-venv-${{ hashFiles('requirements.txt') }}-${{ hashFiles('tests/requirements.txt') }}-${{ hashFiles('setup.cfg') }} + key: ${{ runner.os }}-${{ matrix.python-version }}-venv-${{ hashFiles('requirements.txt') }}-${{ hashFiles('tests/requirements.txt') }}-${{ hashFiles('setup.cfg') }} restore-keys: | ${{ runner.os }}-tox-tests @@ -35,7 +35,7 @@ jobs: run: tox - uses: codecov/codecov-action@v2.1.0 - if: ${{matrix.platform =="ubuntu-latest" $$ matrix.python-version == "3.9"}} + if: ${{runner.os == 'Linux' $$ matrix.python-version == "3.9"}} with: token: ${{ secrets.CODECOV_TOKEN }} files: coverage.xml From 5765553e1fa4715749fe0a0dd1b15aff4eb9932b Mon Sep 17 00:00:00 2001 From: Jan-Hendrik Ewers Date: Mon, 7 Mar 2022 10:27:43 +0000 Subject: [PATCH 04/17] Update CI.yml --- .github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index eab7fc2..fd1ef08 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -35,7 +35,7 @@ jobs: run: tox - uses: codecov/codecov-action@v2.1.0 - if: ${{runner.os == 'Linux' $$ matrix.python-version == "3.9"}} + if: ${{runner.os == 'Linux' && matrix.python-version == "3.9"}} with: token: ${{ secrets.CODECOV_TOKEN }} files: coverage.xml From d63c908093c9e37c1fec7fa8f6c08294d8425ecd Mon Sep 17 00:00:00 2001 From: Jan-Hendrik Ewers Date: Mon, 7 Mar 2022 10:28:13 +0000 Subject: [PATCH 05/17] Update CI.yml --- .github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index fd1ef08..56a7179 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -35,7 +35,7 @@ jobs: run: tox - uses: codecov/codecov-action@v2.1.0 - if: ${{runner.os == 'Linux' && matrix.python-version == "3.9"}} + if: ${{runner.os == 'Linux' && matrix.python-version == '3.9'}} with: token: ${{ secrets.CODECOV_TOKEN }} files: coverage.xml From bb9ebbfb33194e52f8092460f328601d3fea1e63 Mon Sep 17 00:00:00 2001 From: iwishiwasaneagle Date: Mon, 7 Mar 2022 11:19:47 +0000 Subject: [PATCH 06/17] move testing to pytest --- .github/workflows/CI.yml | 4 +- classifier/classifier.py | 42 +++++++++------- setup.cfg | 3 -- tests/test_classifier.py | 105 ++++++++++++++++++++------------------- tox.ini | 4 +- 5 files changed, 84 insertions(+), 74 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index f7d166a..da85a41 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -15,7 +15,7 @@ jobs: python-version: ["3.7", "3.8", "3.9"] steps: - uses: actions/checkout@v2 - + - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v2 with: @@ -35,7 +35,7 @@ jobs: run: tox - uses: codecov/codecov-action@v2.1.0 - if: "${{matrix.platform}}-${{matrix.python-version}}" == "ubuntu-latest-3.9" + if: ${{matrix.platform}} == 'ubunut-${{matrix.python-version}} == "ubuntu-latest-3.9" with: token: ${{ secrets.CODECOV_TOKEN }} files: coverage.xml diff --git a/classifier/classifier.py b/classifier/classifier.py index a89a793..881f520 100755 --- a/classifier/classifier.py +++ b/classifier/classifier.py @@ -13,10 +13,12 @@ """ import argparse +from this import d import arrow import os import subprocess import sys +from loguru import logger VERSION = 'Classifier 3.0' @@ -48,7 +50,11 @@ class Classifier: Documents - https://en.wikipedia.org/wiki/List_of_Microsoft_Office_filename_extensions """ - def __init__(self): + def __init__(self, test=False): + if not test: + self.setup_parser() + + def setup_parser(self): self.description = "Organize files in your directory instantly,by classifying them into different folders" self.parser = argparse.ArgumentParser(description=self.description) @@ -110,7 +116,7 @@ def create_default_config(self): "DEBPackages: deb\n" + "Programs: exe, msi\n" + "RPMPackages: rpm") - print("CONFIG file created at: "+CONFIG) + logger.info("CONFIG file created at: "+CONFIG) def checkconfig(self): """ create a default config if not available """ @@ -132,7 +138,7 @@ def moveto(self, filename, from_folder, to_folder): to_file = os.path.join(to_folder, filename) # to move only files, not folders if not to_file == from_file: - print('moved: ' + str(to_file)) + logger.info('moved: ' + str(to_file)) if os.path.isfile(from_file): if not os.path.exists(to_folder): os.makedirs(to_folder) @@ -163,7 +169,7 @@ def classify(self, formats, output, directory): try: self.moveto(file, directory, folder) except Exception as e: - print('Cannot move file - {} - {}'.format(file, str(e))) + logger.info('Cannot move file - {} - {}'.format(file, str(e))) """ elif os.path.isdir(os.path.join(directory, file)) and self.args.recursive: self.classify(self.formats, output, os.path.join(directory, file)) @@ -171,11 +177,11 @@ def classify(self, formats, output, directory): return def classify_by_date(self, date_format, output, directory): - print("Scanning Files") + logger.info("Scanning Files") files = [x for x in os.listdir(directory) if not x.startswith('.')] creation_dates = map(lambda x: (x, arrow.get(os.path.getctime(os.path.join(directory, x)))), files) - print(creation_dates) + logger.info(creation_dates) for file, creation_date in creation_dates: folder = creation_date.format(date_format) @@ -198,13 +204,13 @@ def _format_arg(self, arg): def run(self): if self.args.version: # Show version information and quit - print(VERSION) + logger.info(VERSION) return False if self.args.types: # Show file format information then quit for key, value in self.formats.items(): - print(key + ': '+ value) + logger.info(key + ': '+ value) return False if self.args.edittypes: @@ -221,7 +227,7 @@ def run(self): return if bool(self.args.specific_folder) ^ bool(self.args.specific_types): - print( + logger.info( 'Specific Folder and Specific Types need to be specified together') sys.exit() @@ -252,7 +258,7 @@ def run(self): if self.args.dateformat: if not self.args.date: - print( + logger.info( 'Dateformat -df must be given alongwith date -dt option') sys.exit() @@ -262,31 +268,31 @@ def run(self): else: self.classify_by_date(self.dateformat, output, directory) elif self.dirconf and os.path.isfile(self.dirconf): - print('Found config in current directory') + logger.info('Found config in current directory') if self.args.output: - print('Your output directory is being ignored!!!') + logger.info('Your output directory is being ignored!!!') for items in open(self.dirconf, "r"): # reset formats for individual folders self.formats = {} try: (key, dst, val) = items.split(':') self.formats[key] = val.replace('\n', '').split(',') - print("\nScanning: " + directory + + logger.info("\nScanning: " + directory + "\nFor: " + key + '\nFormats: ' + val) self.classify(self.formats, dst, directory) except ValueError: - print("Your local config file is malformed. Please check and try again.") + logger.info("Your local config file is malformed. Please check and try again.") return False else: - print("\nScanning Folder: " + directory) + logger.info("\nScanning Folder: " + directory) if self.args.specific_types: - print("For: " + str(self.formats.items())) + logger.info("For: " + str(self.formats.items())) else: - print("Using the default CONFIG File\n") + logger.info("Using the default CONFIG File\n") self.classify(self.formats, output, directory) - print("Done!\n") + logger.info("Done!\n") return True if __name__ == "__main__": diff --git a/setup.cfg b/setup.cfg index 9cb076f..e0b06ee 100644 --- a/setup.cfg +++ b/setup.cfg @@ -54,9 +54,6 @@ console_scripts = classifier = classifier.classifier:main [tool:pytest] -addopts = - --cov jpdmgen --cov-report term-missing - --verbose norecursedirs = dist build diff --git a/tests/test_classifier.py b/tests/test_classifier.py index 16a5ccd..7b90fe0 100755 --- a/tests/test_classifier.py +++ b/tests/test_classifier.py @@ -1,58 +1,63 @@ # -*- coding: utf-8 -*- +from datetime import date +import pathlib import arrow import os import shutil -import unittest +import pytest import classifier.classifier as clf +import tempfile +FILES = [".test", "中文.test"] -class ClassifierTest(unittest.TestCase): - print(dir(clf)) - - __location = os.path.realpath( - os.path.join(os.getcwd(), os.path.dirname(__file__), '.unittest')) - - __tmp_files = [u'test_file', u'test_file_中文'] - __tmp_dirs = [u'test_dir', u'test_dir_中文'] - - def setUp(self): - if not os.path.exists(self.__location): - os.mkdir(self.__location) - os.chdir(self.__location) - for file_ in self.__tmp_files: - open(file_, 'w').close() - for dir_ in self.__tmp_dirs: - if not os.path.exists(dir_): - os.mkdir(dir_) - super(ClassifierTest, self).setUp() - - def tearDown(self): - shutil.rmtree(self.__location) - super(ClassifierTest, self).tearDown() - - def test_moveto(self): - target_dir = os.path.abspath(os.path.join(self.__location, 'moveto')) - for file_ in self.__tmp_files: - clf.self.moveto(file_, self.__location, target_dir) - - for file_ in self.__tmp_files: - final_file_path = os.path.join(target_dir, file_) - self.assertTrue(os.path.exists(final_file_path)) - - def test_classify_bydate(self): - date_format = 'YYYY-MM-DD' - target_files = [] - for file_ in self.__tmp_files: - target_dir = arrow.get(os.path.getctime(file_)).format(date_format) - final_file_path = os.path.join(target_dir, file_) - target_files.append(final_file_path) - clf.self.classify_by_date(date_format, self.__location) - for file_ in target_files: - self.assertTrue(os.path.exists(file_)) - for dir_ in self.__tmp_dirs: - self.assertTrue(os.path.exists(dir_)) - - -if __name__ == '__main__': - unittest.main() +def get_temp_dir(): + return tempfile.mkdtemp() + + +def get_tmp_file(suffix=".test", dir=None): + _, path = tempfile.mkstemp(suffix=suffix, dir=dir) + return path + + +@pytest.fixture +def classifier(): + tmpdir = get_temp_dir() + tmpfiles = [get_tmp_file(f, dir=tmpdir) for f in FILES] + + os.chdir(tmpdir) + + classifier = clf.Classifier(test=True) + classifier.__location = tmpdir + classifier.__files = tmpfiles + + yield classifier + + shutil.rmtree(tmpdir) + + +@pytest.mark.parametrize("target", ("moveto",)) +def test_moveto(classifier, target): + target_dir = pathlib.Path(classifier.__location, target) + for file in classifier.__files: + classifier.moveto(file, classifier.__location, target_dir) + + assert target_dir.joinpath(file).is_file() + + +@pytest.mark.parametrize("target", ("bydate",)) +def test_moveto(classifier, target): + date_fmt = "YYYY-MM-DD" + target_path = pathlib.Path(classifier.__location, target) + final_path = [] + for file in classifier.__files: + final_path.append( + target_path.joinpath( + arrow.get(os.path.getctime(file)).format(date_fmt), pathlib.Path(file).name + ) + ) + + classifier.classify_by_date(date_fmt, target_path, classifier.__location) + + for file in final_path: + assert pathlib.Path(file).exists() diff --git a/tox.ini b/tox.ini index 3746756..8e005e5 100644 --- a/tox.ini +++ b/tox.ini @@ -9,10 +9,12 @@ description = test: Invoke pytest to run automated tests setenv = MODULE = {toxinidir} +passenv= + HOME extras = testing commands = - test: pytest {posargs} --cov-report=xml --cov-branch --cov jpdmgen --cov-report term-missing + test: pytest --cov-report=xml --cov-branch --cov classifier --cov-report term-missing {posargs} deps = -r {toxinidir}/requirements.txt -r {toxinidir}/tests/requirements.txt From 71d894274a636e04e5b829b83362b37371368336 Mon Sep 17 00:00:00 2001 From: iwishiwasaneagle Date: Mon, 7 Mar 2022 11:23:34 +0000 Subject: [PATCH 07/17] make tox use default interpreter --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 8e005e5..fc51a86 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] minversion = 3.15 -envlist = test-py39 +envlist = test isolated_build = True From f84d2161ec965d25958d369e73b776f53866346c Mon Sep 17 00:00:00 2001 From: Jan-Hendrik Ewers Date: Mon, 7 Mar 2022 11:25:32 +0000 Subject: [PATCH 08/17] Update README.md --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 37f2179..5b89f30 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,19 @@ # Classifier + +[![CI](https://github.com/iwishiwasaneagle/classifier/actions/workflows/CI.yml/badge.svg)](https://github.com/iwishiwasaneagle/classifier/actions/workflows/CI.yml) +[![codecov](https://codecov.io/gh/iwishiwasaneagle/classifier/branch/master/graph/badge.svg?token=ZW51EYKLL0)](https://codecov.io/gh/iwishiwasaneagle/classifier) + Organize files in your current directory, by classifying them into folders of music, pdfs, images, etc. ## Installation + ```sh $ pip install classifier ``` + #### Compatibility -* Python 2.7 / Python 3.4 +* Python 3.7 - Python 3.9 * Linux / OSX / Windows From 27e301d33608879c996b1e398505cb1a2881a676 Mon Sep 17 00:00:00 2001 From: iwishiwasaneagle Date: Mon, 7 Mar 2022 11:27:27 +0000 Subject: [PATCH 09/17] try except for removing tests --- tests/test_classifier.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/test_classifier.py b/tests/test_classifier.py index 7b90fe0..a6caf29 100755 --- a/tests/test_classifier.py +++ b/tests/test_classifier.py @@ -8,9 +8,11 @@ import pytest import classifier.classifier as clf import tempfile +from loguru import loggers FILES = [".test", "中文.test"] + def get_temp_dir(): return tempfile.mkdtemp() @@ -33,7 +35,10 @@ def classifier(): yield classifier - shutil.rmtree(tmpdir) + try: + shutil.rmtree(tmpdir) + except PermissionError: + logger.error(f"Permission error when removing {tmpdir}") @pytest.mark.parametrize("target", ("moveto",)) @@ -53,7 +58,8 @@ def test_moveto(classifier, target): for file in classifier.__files: final_path.append( target_path.joinpath( - arrow.get(os.path.getctime(file)).format(date_fmt), pathlib.Path(file).name + arrow.get(os.path.getctime(file)).format(date_fmt), + pathlib.Path(file).name, ) ) From 0a5b3c3514a12807298f7221e5b79511572a1ef0 Mon Sep 17 00:00:00 2001 From: iwishiwasaneagle Date: Mon, 7 Mar 2022 11:35:08 +0000 Subject: [PATCH 10/17] disable windows testing for now. needs someone on a windows machine to figure it out --- .github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index ddf4386..31e7403 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -11,7 +11,7 @@ jobs: runs-on: ${{matrix.platform}} strategy: matrix: - platform: [ubuntu-latest, macos-latest, windows-latest] + platform: [ubuntu-latest, macos-latest] # Enable `windows-latest` once someone on a windows machine can figure out why os.rename doesn't work python-version: ["3.7", "3.8", "3.9"] steps: - uses: actions/checkout@v2 From 03f9eb3eaf66abc5c6b64c08545001549b29aa85 Mon Sep 17 00:00:00 2001 From: iwishiwasaneagle Date: Mon, 7 Mar 2022 11:39:46 +0000 Subject: [PATCH 11/17] change name for PyPi --- README.md | 2 +- setup.cfg | 5 ++--- tox.ini | 12 ++++++++++++ 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 5b89f30..e78c339 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Organize files in your current directory, by classifying them into folders of mu ## Installation ```sh -$ pip install classifier +$ pip install classifier-reborn ``` #### Compatibility diff --git a/setup.cfg b/setup.cfg index e0b06ee..d138f08 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,5 @@ [metadata] -name = classifier +name = classifier-reborn description = Classify the files in your Downloads folder into suitable destinations author=Bhrigu Srivastava author_email=captain.bhrigu@gmail.com @@ -10,9 +10,8 @@ license_files = LICENSE.txt long_description = file: README.md long_description_content_type = text/markdown; charset=UTF-8; variant=GFM url = https://github.com/iwishiwasaneagle/classifier/ -# Add here related links, for example: project_urls = - Source = "https://github.com/iwishiwasaneagle/classifier" + Tracker = https://github.com/iwishiwasaneagle/classifier/issues # Add here all kinds of additional classifiers as defined under diff --git a/tox.ini b/tox.ini index fc51a86..c63a288 100644 --- a/tox.ini +++ b/tox.ini @@ -30,3 +30,15 @@ deps = commands = clean: python -c 'from shutil import rmtree; rmtree("build", True); rmtree("dist", True)' build: python -m build . + +[testenv:publish] +description = + Publish the package you have been developing to a package index server. +skip_install = True +changedir = {toxinidir} +passenv = + HOME +deps = twine +commands = + python -m twine check dist/* + python -m twine upload --config-file "{env:HOME}/.pypirc" dist/* From 9afc58750ddd4ed7c881ddc4bc080f24d6c555ee Mon Sep 17 00:00:00 2001 From: iwishiwasaneagle Date: Mon, 7 Mar 2022 11:51:00 +0000 Subject: [PATCH 12/17] badges --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index e78c339..c033379 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,9 @@ [![CI](https://github.com/iwishiwasaneagle/classifier/actions/workflows/CI.yml/badge.svg)](https://github.com/iwishiwasaneagle/classifier/actions/workflows/CI.yml) [![codecov](https://codecov.io/gh/iwishiwasaneagle/classifier/branch/master/graph/badge.svg?token=ZW51EYKLL0)](https://codecov.io/gh/iwishiwasaneagle/classifier) +[![PyPI version](https://badge.fury.io/py/classifier-reborn.svg)](https://badge.fury.io/py/classifier-reborn) +![GitHub](https://img.shields.io/github/license/iwishiwasaneagle/classifier) + Organize files in your current directory, by classifying them into folders of music, pdfs, images, etc. From 939a7da8519ed492443af66dc1a88638b29d355c Mon Sep 17 00:00:00 2001 From: Jan-Hendrik Ewers Date: Mon, 7 Mar 2022 11:53:32 +0000 Subject: [PATCH 13/17] Create LICENSE --- LICENSE | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..c18ad7c --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2015 Bhrigu Srivastava +Copyright (c) 2022 Jan-Hendrik Ewers + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From 6f755bedb77cda6f591bd4b04c95f392ce1e84be Mon Sep 17 00:00:00 2001 From: Jan-Hendrik Ewers Date: Mon, 7 Mar 2022 11:54:54 +0000 Subject: [PATCH 14/17] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c033379..c96a344 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![CI](https://github.com/iwishiwasaneagle/classifier/actions/workflows/CI.yml/badge.svg)](https://github.com/iwishiwasaneagle/classifier/actions/workflows/CI.yml) [![codecov](https://codecov.io/gh/iwishiwasaneagle/classifier/branch/master/graph/badge.svg?token=ZW51EYKLL0)](https://codecov.io/gh/iwishiwasaneagle/classifier) [![PyPI version](https://badge.fury.io/py/classifier-reborn.svg)](https://badge.fury.io/py/classifier-reborn) -![GitHub](https://img.shields.io/github/license/iwishiwasaneagle/classifier) +[![GitHub](https://img.shields.io/github/license/iwishiwasaneagle/classifier)](https://github.com/iwishiwasaneagle/classifier/blob/master/LICENSE) Organize files in your current directory, by classifying them into folders of music, pdfs, images, etc. From 0cda127679114c82e85f34a9e58bf796a63117b5 Mon Sep 17 00:00:00 2001 From: iwishiwasaneagle Date: Mon, 7 Mar 2022 12:14:38 +0000 Subject: [PATCH 15/17] wasn't working due to import errors. works now --- classifier/__init__.py | 4 +++- classifier/classifier.py | 1 - setup.cfg | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/classifier/__init__.py b/classifier/__init__.py index 413503b..91eeffd 100644 --- a/classifier/__init__.py +++ b/classifier/__init__.py @@ -12,4 +12,6 @@ except PackageNotFoundError: # pragma: no cover __version__ = "unknown" finally: - del version, PackageNotFoundError \ No newline at end of file + del version, PackageNotFoundError + +from .classifier import main \ No newline at end of file diff --git a/classifier/classifier.py b/classifier/classifier.py index 881f520..30217e6 100755 --- a/classifier/classifier.py +++ b/classifier/classifier.py @@ -13,7 +13,6 @@ """ import argparse -from this import d import arrow import os import subprocess diff --git a/setup.cfg b/setup.cfg index d138f08..0a71d1a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -37,7 +37,7 @@ install_requires = [options.packages.find] -where = src +where = ./ exclude = tests @@ -50,7 +50,7 @@ test = [options.entry_points] console_scripts = - classifier = classifier.classifier:main + classifier = classifier:main [tool:pytest] norecursedirs = From 359a578fa84a7045525089ab5d53d43d27476483 Mon Sep 17 00:00:00 2001 From: iwishiwasaneagle Date: Mon, 7 Mar 2022 12:20:52 +0000 Subject: [PATCH 16/17] handle getting version from package rather than hard coding it --- classifier/__init__.py | 17 +---------------- classifier/_version.py | 14 ++++++++++++++ classifier/classifier.py | 4 ++-- 3 files changed, 17 insertions(+), 18 deletions(-) create mode 100644 classifier/_version.py diff --git a/classifier/__init__.py b/classifier/__init__.py index 91eeffd..05b266a 100644 --- a/classifier/__init__.py +++ b/classifier/__init__.py @@ -1,17 +1,2 @@ -import sys - -if sys.version_info[:2] >= (3, 8): - from importlib.metadata import PackageNotFoundError, version # pragma: no cover -else: - from importlib_metadata import PackageNotFoundError, version # pragma: no cover - -try: - # Change here if project is renamed and does not equal the package name - dist_name = __name__ - __version__ = version(dist_name) -except PackageNotFoundError: # pragma: no cover - __version__ = "unknown" -finally: - del version, PackageNotFoundError - +from ._version import __version__ from .classifier import main \ No newline at end of file diff --git a/classifier/_version.py b/classifier/_version.py new file mode 100644 index 0000000..bfeb717 --- /dev/null +++ b/classifier/_version.py @@ -0,0 +1,14 @@ +import sys + +if sys.version_info[:2] >= (3, 8): + from importlib.metadata import PackageNotFoundError, version # pragma: no cover +else: + from importlib_metadata import PackageNotFoundError, version # pragma: no cover + +try: + dist_name = __name__ + __version__ = version(dist_name) +except PackageNotFoundError: # pragma: no cover + __version__ = "unknown" +finally: + del version, PackageNotFoundError diff --git a/classifier/classifier.py b/classifier/classifier.py index 30217e6..5bb9a4d 100755 --- a/classifier/classifier.py +++ b/classifier/classifier.py @@ -19,8 +19,8 @@ import sys from loguru import logger +from classifier import __version__ -VERSION = 'Classifier 3.0' DIRCONFFILE = '.classifier.conf' PLATFORM = sys.platform OS = os.name @@ -203,7 +203,7 @@ def _format_arg(self, arg): def run(self): if self.args.version: # Show version information and quit - logger.info(VERSION) + logger.info(__version__) return False if self.args.types: From 0430298f74884a85559292cc1bee9ebbaac15af2 Mon Sep 17 00:00:00 2001 From: iwishiwasaneagle Date: Mon, 7 Mar 2022 12:24:32 +0000 Subject: [PATCH 17/17] use name of the pypi package (i.e. the wheel) and not the local package --- classifier/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classifier/_version.py b/classifier/_version.py index bfeb717..f49313c 100644 --- a/classifier/_version.py +++ b/classifier/_version.py @@ -6,7 +6,7 @@ from importlib_metadata import PackageNotFoundError, version # pragma: no cover try: - dist_name = __name__ + dist_name = "classifier-reborn" __version__ = version(dist_name) except PackageNotFoundError: # pragma: no cover __version__ = "unknown"