Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/tfeldmann/organize
Browse files Browse the repository at this point in the history
  • Loading branch information
tfeldmann committed Aug 19, 2019
2 parents 16dad48 + 071e085 commit cf5ede7
Show file tree
Hide file tree
Showing 38 changed files with 617 additions and 420 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
- Fixes an issue with globstring file exclusion.
- Remove `clint` dependency as it is no longer maintained.
- Added various integration tests
- The "~~ SIMULATION ~~"-banner now takes up the whole terminal width

## v1.5.3 (2019-08-01)
- Filename filter now supports lists.
Expand Down
4 changes: 4 additions & 0 deletions docs/page/filters.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ Created
-------
.. autoclass:: Created

Python
------
.. autoclass:: Python

Regex
-----
.. autoclass:: Regex
15 changes: 10 additions & 5 deletions organize/actions/action.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from textwrap import indent
from typing import Optional

from organize.compat import Path
from organize.utils import DotDict


Expand All @@ -14,18 +13,24 @@ class TemplateAttributeError(Error):


class Action:
def run(self, attrs: dict, simulate: bool) -> Optional[Path]:
# if you change the file path, return the new path here
pre_print_hook = None

def run(self, **kwargs):
return self.pipeline(DotDict(kwargs))

def pipeline(self, args: DotDict) -> Optional[dict]:
raise NotImplementedError

def print(self, msg):
""" print a message for the user """
if callable(self.pre_print_hook):
self.pre_print_hook() # pylint: disable=not-callable
print(indent("- [%s] %s" % (self.__class__.__name__, msg), " " * 4))

@staticmethod
def fill_template_tags(msg: str, attrs: dict) -> str:
def fill_template_tags(msg: str, args) -> str:
try:
return msg.format(**DotDict(attrs))
return msg.format(**args)
except AttributeError as exc:
cause = exc.args[0]
raise TemplateAttributeError(
Expand Down
12 changes: 6 additions & 6 deletions organize/actions/copy.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
import os
import shutil

from organize.compat import Path
from organize.utils import find_unused_filename, fullpath
from organize.utils import find_unused_filename, fullpath, DotDict

from .action import Action
from .trash import Trash
Expand Down Expand Up @@ -87,10 +86,11 @@ def __init__(self, dest: str, overwrite=False, counter_separator=" "):
self.overwrite = overwrite
self.counter_separator = counter_separator

def run(self, attrs: dict, simulate: bool):
path = attrs["path"]
def pipeline(self, args):
path = args["path"]
simulate = args["simulate"]

expanded_dest = self.fill_template_tags(self.dest, attrs)
expanded_dest = self.fill_template_tags(self.dest, args)
# if only a folder path is given we append the filename to have the full
# path. We use os.path for that because pathlib removes trailing slashes
if expanded_dest.endswith(("\\", "/")):
Expand All @@ -100,7 +100,7 @@ def run(self, attrs: dict, simulate: bool):
if new_path.exists() and not new_path.samefile(path):
if self.overwrite:
self.print("File already exists")
Trash().run({"path": new_path}, simulate=simulate)
Trash().run(path=new_path, simulate=simulate)
else:
new_path = find_unused_filename(
path=new_path, separator=self.counter_separator
Expand Down
10 changes: 4 additions & 6 deletions organize/actions/echo.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import logging

from organize.compat import Path

from .action import Action

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -74,10 +72,10 @@ def __init__(self, msg):
self.msg = msg
self.log = logging.getLogger(__name__)

def run(self, attrs: dict, simulate: bool):
path = attrs["path"]
logger.debug('Echo msg "%s", path: "%s", attrs: "%s"', self.msg, path, attrs)
full_msg = self.fill_template_tags(self.msg, attrs)
def pipeline(self, args):
path = args["path"]
logger.debug('Echo msg "%s", path: "%s", args: "%s"', self.msg, path, args)
full_msg = self.fill_template_tags(self.msg, args)
logger.info("Console output: %s", full_msg)
self.print("%s" % full_msg)

Expand Down
14 changes: 8 additions & 6 deletions organize/actions/move.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import os
import shutil

from organize.utils import find_unused_filename, fullpath
from organize.utils import DotDict, find_unused_filename, fullpath

from .action import Action
from .trash import Trash
Expand Down Expand Up @@ -90,10 +90,11 @@ def __init__(self, dest: str, overwrite=False, counter_separator=" "):
self.overwrite = overwrite
self.counter_separator = counter_separator

def run(self, attrs: dict, simulate: bool):
path = attrs["path"]
def pipeline(self, args):
path = args["path"]
simulate = args["simulate"]

expanded_dest = self.fill_template_tags(self.dest, attrs)
expanded_dest = self.fill_template_tags(self.dest, args)
# if only a folder path is given we append the filename to have the full
# path. We use os.path for that because pathlib removes trailing slashes
if expanded_dest.endswith(("\\", "/")):
Expand All @@ -105,7 +106,7 @@ def run(self, attrs: dict, simulate: bool):
if new_path_exists and not new_path_samefile:
if self.overwrite:
self.print("File already exists")
Trash().run({"path": new_path}, simulate=simulate)
Trash().run(path=new_path, simulate=simulate)
else:
new_path = find_unused_filename(
path=new_path, separator=self.counter_separator
Expand All @@ -120,7 +121,8 @@ def run(self, attrs: dict, simulate: bool):
new_path.parent.mkdir(parents=True, exist_ok=True)
logger.info('Moving "%s" to "%s"', path, new_path)
shutil.move(src=str(path), dst=str(new_path))
return new_path

return {"path": new_path}

def __str__(self):
return "Move(dest=%s, overwrite=%s)" % (self.dest, self.overwrite)
39 changes: 21 additions & 18 deletions organize/actions/python.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import logging
import textwrap

from .action import Action

Expand Down Expand Up @@ -60,23 +61,25 @@ class Python(Action):
"""

def __init__(self, code):
self.code = code

def run(self, attrs: dict, simulate: bool):
self.code = textwrap.dedent(code)

def create_method(self, name, argnames, code):
globals_ = globals().copy()
globals_["print"] = self.print
locals_ = locals().copy()
funccode = "def {fnc}__({arg}):\n{cod}\n\nself.{fnc} = {fnc}__\n".format(
fnc=name,
arg=", ".join(argnames),
cod=textwrap.indent(textwrap.dedent(code), " " * 4),
)
exec(funccode, globals_, locals_) # pylint: disable=exec-used

def pipeline(self, args):
simulate = args.simulate
if simulate:
self.print("Code not run in simulation")
self.print("Code not run in simulation." % args)
else:
path = attrs["path"]
logger.info(
'Executing python script:\n"""\n%s""", path="%s", args=%s',
self.code,
path,
attrs,
)
# local variables for inline function
locals_ = attrs.copy()
locals_["simulate"] = simulate
# replace default print function
globals_ = globals().copy()
globals_["print"] = self.print
exec(self.code, globals_, locals_)
logger.info('Executing python:\n"""\n%s\n""", args=%s', self.code, args)
self.create_method(name="usercode", argnames=args.keys(), code=self.code)
self.print("Running python script.")
return self.usercode(**args) # pylint: disable=no-member
10 changes: 5 additions & 5 deletions organize/actions/rename.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import logging
import os

from organize.compat import Path
from organize.utils import find_unused_filename

from .action import Action
Expand Down Expand Up @@ -64,9 +63,10 @@ def __init__(self, name: str, overwrite=False, counter_separator=" "):
self.overwrite = overwrite
self.counter_separator = counter_separator

def run(self, attrs: dict, simulate: bool) -> Path:
path = attrs["path"]
expanded_name = self.fill_template_tags(self.name, attrs)
def pipeline(self, args):
path = args["path"]
simulate = args["simulate"]
expanded_name = self.fill_template_tags(self.name, args)
new_path = path.parent / expanded_name

# handle filename collisions
Expand All @@ -75,7 +75,7 @@ def run(self, attrs: dict, simulate: bool) -> Path:
if new_path_exists and not new_path_samefile:
if self.overwrite:
self.print("File already exists")
Trash().run({"path": new_path}, simulate=simulate)
Trash().run(path=new_path, simulate=simulate)
else:
new_path = find_unused_filename(
path=new_path, separator=self.counter_separator
Expand Down
6 changes: 3 additions & 3 deletions organize/actions/shell.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ class Shell(Action):
def __init__(self, cmd: str):
self.cmd = cmd

def run(self, attrs: dict, simulate: bool):
full_cmd = self.fill_template_tags(self.cmd, attrs)
def pipeline(self, args):
full_cmd = self.fill_template_tags(self.cmd, args)
self.print("$ %s" % full_cmd)
if not simulate:
if not args.simulate:
# we use call instead of run to be compatible with python < 3.5
logger.info('Executing command "%s" in shell.', full_cmd)
subprocess.call(full_cmd, shell=True)
Expand Down
5 changes: 3 additions & 2 deletions organize/actions/trash.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ class Trash(Action):
- trash
"""

def run(self, attrs: dict, simulate: bool):
path = attrs["path"]
def pipeline(self, args):
path = args.path
simulate = args.simulate
from send2trash import send2trash

self.print('Trash "%s"' % path)
Expand Down
4 changes: 2 additions & 2 deletions organize/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,5 +148,5 @@ def list_actions_and_filters():
print(" " + name)


def print_error(text):
print(Style.BRIGHT + Fore.RED + "ERROR:" + Style.RESET_ALL + " " + text)
def print_error(e):
print(Style.BRIGHT + Fore.RED + "ERROR:" + Style.RESET_ALL + " %s" % e)
Loading

0 comments on commit cf5ede7

Please sign in to comment.