mirror of
https://github.com/novoid/filetags.git
synced 2026-06-14 11:31:19 +00:00
first working version with tests
This commit is contained in:
parent
b8039e2d7c
commit
31044e073b
2 changed files with 112 additions and 48 deletions
110
filetag.py
110
filetag.py
|
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# Time-stamp: <2013-05-14 18:20:58 vk>
|
||||
# Time-stamp: <2013-05-14 22:41:20 vk>
|
||||
|
||||
## TODO:
|
||||
## * fix parts marked with «FIXXME»
|
||||
|
|
@ -31,7 +31,7 @@ FILENAME_TAG_SEPARATOR = u' -- '
|
|||
BETWEEN_TAG_SEPARATOR = u' '
|
||||
|
||||
USAGE = u"\n\
|
||||
" + sys.argv[0] + u"\n\
|
||||
" + sys.argv[0] + u" [<options>] <list of files>\n\
|
||||
\n\
|
||||
FIXXME\n\
|
||||
https://github.com/novoid/FIXXME\n\
|
||||
|
|
@ -64,6 +64,9 @@ parser.add_option("-r", "--remove", "-d", "--delete", action="store_true",
|
|||
parser.add_option("-i", "--interactive", action="store_true",
|
||||
help="interactive mode: ask for (a)dding or (r)emoving and name of tag(s)")
|
||||
|
||||
parser.add_option("-s", "--dryrun", dest="dryrun", action="store_true",
|
||||
help="enable dryrun mode: just simulate what would happen, do not modify files")
|
||||
|
||||
parser.add_option("-v", "--verbose", dest="verbose", action="store_true",
|
||||
help="enable verbose mode")
|
||||
|
||||
|
|
@ -199,29 +202,52 @@ def removing_tag_from_filename(filename, tagname):
|
|||
u'.' + extension
|
||||
|
||||
|
||||
def query_folder(folder, list_of_files_found):
|
||||
"""Walk the folder and its sub-folders and collect files matching
|
||||
INCLUDE_FILES_REGEX whose folder do not match
|
||||
EXCLUDE_FOLDERS_REGEX."""
|
||||
def extract_tags_from_argument(argument):
|
||||
"""
|
||||
@param argument: string containing one or more tags
|
||||
@param return: a list of unicode tags
|
||||
"""
|
||||
|
||||
## http://stackoverflow.com/questions/5141437/filtering-os-walk-dirs-and-files
|
||||
|
||||
for root, dirs, files in os.walk(folder):
|
||||
|
||||
# exclude dirs
|
||||
dirs[:] = [os.path.join(root, d) for d in dirs]
|
||||
dirs[:] = [d for d in dirs if not re.match(EXCLUDE_FOLDERS_REGEX, d)]
|
||||
|
||||
# exclude/include files
|
||||
files = [f for f in files if re.match(INCLUDE_FILES_REGEX, f)]
|
||||
files = [os.path.join(root, f) for f in files]
|
||||
|
||||
for fname in files:
|
||||
list_of_files_found.append(fname)
|
||||
|
||||
return list_of_files_found
|
||||
return argument.split(unicode(BETWEEN_TAG_SEPARATOR))
|
||||
|
||||
|
||||
def extract_filenames_from_argument(argument):
|
||||
"""
|
||||
@param argument: string containing one or more file names
|
||||
@param return: a list of unicode file names
|
||||
"""
|
||||
|
||||
return argument
|
||||
|
||||
|
||||
def handle_file(filename, tags, do_remove, dryrun):
|
||||
"""
|
||||
@param filename: list containing one or more file names
|
||||
@param tags: list containing one or more tags
|
||||
@param do_remove: boolean which defines if tags should be added (False) or removed (True)
|
||||
@param dryrun: boolean which defines if files should be changed (False) or not (True)
|
||||
@param return: error value
|
||||
"""
|
||||
|
||||
if os.path.isdir(filename):
|
||||
logging.warning("Skipping directory \"%s\" because this tool only renames file names." % filename)
|
||||
return
|
||||
elif not os.path.isfile(filename):
|
||||
logging.error("Skipping \"%s\" because this tool only renames existing file names." % filename)
|
||||
return
|
||||
|
||||
new_filename = filename
|
||||
for tagname in tags:
|
||||
if do_remove:
|
||||
new_filename = removing_tag_from_filename(new_filename, tagname)
|
||||
else:
|
||||
new_filename = adding_tag_to_filename(new_filename, tagname)
|
||||
|
||||
if dryrun:
|
||||
logging.info("renaming: \"%s\" > \"%s\"" % (filename, new_filename))
|
||||
else:
|
||||
logging.debug("renaming \"%s\" > \"%s\" ..." % (filename, new_filename))
|
||||
os.rename(filename, new_filename)
|
||||
|
||||
|
||||
def main():
|
||||
|
|
@ -248,23 +274,41 @@ def main():
|
|||
error_exit(3, "I found option \"--tag\" and option \"--interactive\". \n" +
|
||||
"Please choose either tag option OR interactive mode.")
|
||||
|
||||
|
||||
## interactive mode and remove flag is given (FIXXME: make it possible in future versions)
|
||||
if options.interactive and options.remove:
|
||||
error_exit(4, "I found option \"--interactive\" and option \"--remove\". \n" +
|
||||
"Please choose either interactive mode OR specify tag(s) to remove together with the \"--tag\" option.")
|
||||
tags = []
|
||||
|
||||
if options.interactive:
|
||||
|
||||
## extract list of tags
|
||||
## FIXXME
|
||||
if options.remove:
|
||||
logging.info("Interactive mode: tags get REMOVED from file names ...")
|
||||
else:
|
||||
logging.info("Interactive mode: tags get ADDED to file names ...")
|
||||
|
||||
## extract list of files
|
||||
## FIXXME
|
||||
## interactive: ask for list of tags
|
||||
logging.debug("interactive mode: asking for tags ...")
|
||||
|
||||
## iterate over files
|
||||
## FIXXME
|
||||
print "Please enter one or more tags (separated by \"" + BETWEEN_TAG_SEPARATOR + "\"): (abort with Ctrl-C)"
|
||||
entered_tags = sys.stdin.readline().strip()
|
||||
|
||||
tags = extract_tags_from_argument(entered_tags)
|
||||
|
||||
else:
|
||||
## non-interactive: extract list of tags
|
||||
logging.debug("non-interactive mode: extracting tags from argument ...")
|
||||
|
||||
tags = extract_tags_from_argument(options.tags)
|
||||
|
||||
logging.debug("tags found: [%s]" % '], ['.join(tags))
|
||||
|
||||
logging.debug("extracting list of files ...")
|
||||
logging.debug("len(args) [%s]" % str(len(args)))
|
||||
if len(args)<1:
|
||||
error_exit(5, "Please add at least one file name as argument")
|
||||
files = extract_filenames_from_argument(args)
|
||||
logging.debug("filenames found: [%s]" % '], ['.join(files))
|
||||
|
||||
logging.debug("iterate over files ...")
|
||||
for filename in files:
|
||||
handle_file(filename, tags, options.remove, options.dryrun)
|
||||
|
||||
logging.info("successfully finished.")
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# Time-stamp: <2013-05-14 18:21:24 vk>
|
||||
# Time-stamp: <2013-05-14 22:49:16 vk>
|
||||
|
||||
## invoke tests using following command line:
|
||||
## ~/src/vktag % PYTHONPATH="~/src/vktag:" tests/unit_tests.py --verbose
|
||||
|
|
@ -57,13 +57,10 @@ class TestMethods(unittest.TestCase):
|
|||
pass
|
||||
|
||||
|
||||
class NO_TestFiles(unittest.TestCase):
|
||||
class TestFileWithoutTags(unittest.TestCase):
|
||||
|
||||
tempdir = None
|
||||
testfile_without_tags = 'file_without_tags.txt'
|
||||
testfile_with_multiple_dots_and_no_tags = 'file.without.tags.txt'
|
||||
testfile_with_tag_foo = 'filename -- foo.txt'
|
||||
testfile_with_tag_bar = 'filename -- bar.txt'
|
||||
testfilename = 'a test file . for you.txt'
|
||||
|
||||
def setUp(self):
|
||||
|
||||
|
|
@ -73,13 +70,10 @@ class NO_TestFiles(unittest.TestCase):
|
|||
print "\ntemporary directory: " + self.tempdir
|
||||
|
||||
## create set of test files:
|
||||
self.create_tmp_file(self.testfile_without_tags)
|
||||
self.create_tmp_file(self.testfile_with_multiple_dots_and_no_tags)
|
||||
self.create_tmp_file(self.testfile_with_tag_foo)
|
||||
self.create_tmp_file(self.testfile_with_tag_bar)
|
||||
self.create_tmp_file(self.testfilename)
|
||||
|
||||
## double-check set-up:
|
||||
self.assertTrue(self.file_exists(self.testfile_without_tags))
|
||||
self.assertTrue(self.file_exists(self.testfilename))
|
||||
|
||||
|
||||
def create_tmp_file(self, name):
|
||||
|
|
@ -92,14 +86,40 @@ class NO_TestFiles(unittest.TestCase):
|
|||
return os.path.isfile(os.path.join(self.tempdir, name))
|
||||
|
||||
|
||||
def test_all(self):
|
||||
def test_add_and_remove_tags(self):
|
||||
|
||||
print "testing: foo bar\n"
|
||||
self.assertEqual(3 * 4, 12)
|
||||
## adding a tag to a file without any tags:
|
||||
filetag.handle_file(os.path.join(self.tempdir, self.testfilename), [u'bar'], False, False)
|
||||
self.assertEqual(self.file_exists(u'a test file . for you -- bar.txt'), True)
|
||||
|
||||
## adding a second tag:
|
||||
filetag.handle_file(os.path.join(self.tempdir, u'a test file . for you -- bar.txt'),
|
||||
[u'foo'], do_remove=False, dryrun=False)
|
||||
self.assertEqual(self.file_exists(u'a test file . for you -- bar foo.txt'), True)
|
||||
|
||||
## adding two tags:
|
||||
filetag.handle_file(os.path.join(self.tempdir, u'a test file . for you -- bar foo.txt'),
|
||||
[u'one', u'two'], do_remove=False, dryrun=False)
|
||||
self.assertEqual(self.file_exists(u'a test file . for you -- bar foo one two.txt'), True)
|
||||
|
||||
## simulating another tag:
|
||||
filetag.handle_file(os.path.join(self.tempdir, u'a test file . for you -- bar foo one two.txt'),
|
||||
[u'one', u'two'], do_remove=False, dryrun=True)
|
||||
self.assertEqual(self.file_exists(u'a test file . for you -- bar foo one two.txt'), True)
|
||||
|
||||
## removing three tag:
|
||||
filetag.handle_file(os.path.join(self.tempdir, u'a test file . for you -- bar foo one two.txt'),
|
||||
[u'bar', u'one', u'foo'], do_remove=True, dryrun=False)
|
||||
self.assertEqual(self.file_exists(u'a test file . for you -- two.txt'), True)
|
||||
|
||||
## removing last tag:
|
||||
filetag.handle_file(os.path.join(self.tempdir, u'a test file . for you -- two.txt'),
|
||||
[u'two'], do_remove=True, dryrun=False)
|
||||
self.assertEqual(self.file_exists(u'a test file . for you.txt'), True)
|
||||
|
||||
|
||||
def tearDown(self):
|
||||
|
||||
|
||||
rmtree(self.tempdir)
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue