Skip to content

Commit

Permalink
code reorg
Browse files Browse the repository at this point in the history
  • Loading branch information
Thomas Feldmann committed Mar 2, 2018
1 parent e44a637 commit 51e712a
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 66 deletions.
4 changes: 2 additions & 2 deletions main.py
@@ -1,4 +1,4 @@
from organize import cli
from organize import main

if __name__ == '__main__':
cli.main()
main.main()
2 changes: 1 addition & 1 deletion organize/config.py
Expand Up @@ -143,7 +143,7 @@ class Error(Exception):

class NoRulesFoundError(Error):
def __str__(self):
return "No 'rules' found in configuration file"
return 'No rules found in configuration file'

class ParsingError(Error):
pass
Expand Down
7 changes: 4 additions & 3 deletions organize/core.py
@@ -1,12 +1,14 @@
import logging
from collections import defaultdict, namedtuple
from typing import Iterable, Tuple, Generator

from clint.textui import colored, indent, puts

from .utils import Path, bold

logger = logging.getLogger(__name__)


Job = namedtuple('Job', 'folder path filters actions')
Job.__doc__ = """
:param str folder: the folder the file was found in
Expand Down Expand Up @@ -45,7 +47,7 @@ def filter_pipeline(job):
return result


def action_pipeline(job, attrs, simulate): # type: (Job, dict, bool) -> None
def action_pipeline(job: Job, attrs: dict, simulate: bool):
try:
current_path = job.path.resolve()
for action in job.actions:
Expand All @@ -58,8 +60,7 @@ def action_pipeline(job, attrs, simulate): # type: (Job, dict, bool) -> None
action.print('%s %s' % (colored.red('ERROR!', bold=True), e))


def execute_rules(rules, simulate): # type: (bool) -> None
# TODO: warning for multiple rules applying to the same path?
def execute_rules(rules, simulate):
jobs = list(find_jobs(rules))
if not jobs:
puts('Nothing to do.')
Expand Down
140 changes: 81 additions & 59 deletions organize/cli.py → organize/main.py
Expand Up @@ -28,21 +28,34 @@
import logging.config
import os
import subprocess
import sys

import appdirs
import yaml
from clint.textui import indent, puts
from clint.textui import colored, indent, puts
from docopt import docopt

from .__version__ import __version__
from .config import Config
from .core import execute_rules
from .utils import Path, bold

logger = logging.getLogger(__name__)
# prepare config and log folders
app_dirs = appdirs.AppDirs('organize')
config_dir = Path(app_dirs.user_config_dir)
config_path = config_dir / 'config.yaml'
log_dir = Path(app_dirs.user_log_dir)
log_path = log_dir / 'organize.log'

for folder in (config_dir, log_dir):
folder.mkdir(parents=True, exist_ok=True)
if not config_path.exists():
config_path.touch()

# configure logging
LOGGING = """
version: 1
disable_existing_loggers: false
formatters:
simple:
format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
Expand All @@ -52,24 +65,82 @@
level: DEBUG
formatter: simple
stream: ext://sys.stdout
loggers:
simpleExample:
file:
class: logging.handlers.TimedRotatingFileHandler
level: DEBUG
handlers: [console]
propagate: no
filename: {filename}
formatter: simple
when: midnight
backupCount: 35
root:
level: DEBUG
handlers: [console]
"""
handlers: [file]
""".format(filename=str(log_path))
logging.config.dictConfig(yaml.load(LOGGING))
logger = logging.getLogger(__name__)


def main():
""" entry point for the command line interface """
args = docopt(__doc__, version=__version__, help=True)
# > organize config
if args['config']:
if args['--open-folder']:
open_in_filemanager(config_dir)
elif args['--path']:
print(str(config_path))
elif args['--debug']:
config_debug()
else:
config_edit()
# > organize list
elif args['list']:
list_actions_and_filters()
# > organize sim / run
else:
try:
config = Config.from_file(config_path)
execute_rules(config.rules, simulate=args['sim'])
except Config.Error as e:
logger.exception(e)
print_error(e)
print("Try 'organize config --debug' for easier debugging.")
print('Full traceback at: %s' % log_path)
sys.exit(1)


def config_edit():
""" open the config file in $EDITOR or default text editor """
editor = os.getenv('EDITOR')
if editor:
subprocess.call([editor, str(config_path)])
else:
open_in_filemanager(config_path)


def open_in_filemanager(path):
""" opens the given path in file manager, using the default application """
import webbrowser
webbrowser.open(path.as_uri())


def config_debug():
""" prints the config with resolved aliases and tries to parse rules """
try:
print('Your configuration rules:')
config = Config.from_file(config_path)
if not config.config:
print_error('Config file is empty')
print(config.yaml())
_ = config.rules
except Config.Error as e:
print_error(e)
else:
print(colored.green('Everything seems fine.'))


def list_actions_and_filters():
""" Prints a list of available actions and filters """
import inspect
from organize import filters, actions
puts(bold('Filters:'))
Expand All @@ -83,54 +154,5 @@ def list_actions_and_filters():
puts(name)


def config_debug(config_path):
""" prints the config with resolved aliases and tries to parse rules """
try:
config = Config.from_file(config_path)
print(config.yaml())
_ = config.rules
except Config.Error as exc:
print(exc)


def open_in_editor(path):
""" open the config file in $EDITOR or default text editor """
# create empty config file if it does not exist
if not path.exists():
path.touch()
editor = os.getenv('EDITOR')
if editor:
subprocess.call([editor, str(path)])
else:
open_in_filemanager(path)


def main():
# prepare config and log folders
app_dirs = appdirs.AppDirs('organize')
config_dir = Path(app_dirs.user_config_dir)
config_path = config_dir / 'config.yaml'
log_dir = Path(app_dirs.user_log_dir)
for folder in (config_dir, log_dir):
folder.mkdir(parents=True, exist_ok=True)

args = docopt(__doc__, version=__version__, help=True)
if args['config']:
if args['--open-folder']:
open_in_filemanager(config_dir)
elif args['--path']:
print(str(config_path))
elif args['--debug']:
config_debug(config_path)
else:
open_in_editor(config_path)

elif args['list']:
list_actions_and_filters()
else:
try:
config = Config.from_file(config_path)
execute_rules(config.rules, simulate=args['sim'])
except Config.Error as e:
print('There is a problem in your config file:')
print(e)
def print_error(text):
print('%s %s' % (colored.red('ERROR!', bold=True), text))
2 changes: 2 additions & 0 deletions organize/utils.py
Expand Up @@ -3,6 +3,8 @@

import colorama

# in python < 3.5 the pathlib module misses some features so we have to import
# a backported alternative
if sys.version_info < (3, 5):
from pathlib2 import Path
else:
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Expand Up @@ -41,7 +41,7 @@
url='https://github.com/tfeldmann/organize',
packages=find_packages(exclude=['tests']),
entry_points={
'console_scripts': ['organize=organize.cli:main'],
'console_scripts': ['organize=organize.main:main'],
},
install_requires=install_requires,
include_package_data=True,
Expand Down

0 comments on commit 51e712a

Please sign in to comment.