Skip to content

Commit 9fa53c2

Browse files
committed
Fix #43: os path join raise unicode decode error
In python2, UnicodeDecodeError raised when dir/file name is non-ASCII using getcwdu (six provide getcwd to be compatible with Python3) to get current dir and passing it to listdir which also return unicode and decoding folder-relative args as utf-8 Arrange the structure of unittest, and add a testcase for classifying by date which will raise the Error mentioned before
1 parent 28cbf1d commit 9fa53c2

File tree

3 files changed

+67
-17
lines changed

3 files changed

+67
-17
lines changed

classifier/classifier.py

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
#!/usr/bin/env python
2-
import os
3-
import sys
42
import argparse
53
import arrow
4+
import os
5+
import six
6+
import sys
7+
8+
from six.moves import getcwd
69

710
"""
811
All format lists were taken from wikipedia, not all of them were added due to extensions
@@ -28,7 +31,7 @@ def moveto(file, from_folder, to_folder):
2831
def classify(formats, output):
2932
print("Scanning Files")
3033

31-
directory = os.getcwd()
34+
directory = getcwd()
3235

3336
for file in os.listdir(directory):
3437
filename, file_ext = os.path.splitext(file)
@@ -46,7 +49,7 @@ def classify(formats, output):
4649
def classify_by_date(date_format, output_dir):
4750
print("Scanning Files")
4851

49-
directory = os.getcwd()
52+
directory = getcwd()
5053
files = [x for x in os.listdir(directory) if not x.startswith('.')]
5154
creation_dates = map(lambda x: (x, arrow.get(os.path.getctime(x))), files)
5255

@@ -57,6 +60,18 @@ def classify_by_date(date_format, output_dir):
5760
print("Done!")
5861

5962

63+
def _format_text_arg(arg):
64+
if not isinstance(arg, six.text_type):
65+
arg = arg.decode('utf-8')
66+
return arg
67+
68+
69+
def _format_arg(arg):
70+
if isinstance(arg, six.string_types):
71+
arg = _format_text_arg(arg)
72+
return arg
73+
74+
6075
def main():
6176
description = "Organize files in your directory instantly,by classifying them into different folders"
6277
parser = argparse.ArgumentParser(description=description)
@@ -92,14 +107,17 @@ def main():
92107
sys.exit()
93108

94109
if args.specific_folder and args.specific_types:
95-
formats = {args.specific_folder: args.specific_types}
110+
specific_folder = _format_arg(args.specific_folder)
111+
formats = {specific_folder: args.specific_types}
96112

97113
if args.output is None:
98-
args.output = os.getcwd()
114+
output = getcwd()
115+
else:
116+
output = _format_arg(args.output)
99117

100118
if args.date:
101-
classify_by_date('DD-MM-YYYY', args.output)
119+
classify_by_date('DD-MM-YYYY', output)
102120
else:
103-
classify(formats, args.output)
121+
classify(formats, output)
104122

105123
sys.exit()

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
""",
1616
install_requires=[
1717
'arrow',
18+
'six',
1819
],
1920
zip_safe=False
2021
)

tests/test_classifier.py

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,59 @@
11
# -*- coding: utf-8 -*-
22

3+
import arrow
34
import os
5+
import shutil
46
import unittest
57

68
from classifier import classifier as clf
9+
from six.moves import getcwd
710

811

912
class ClassifierTest(unittest.TestCase):
1013

1114
__location = os.path.realpath(
12-
os.path.join(os.getcwd(), os.path.dirname(__file__)))
15+
os.path.join(getcwd(), os.path.dirname(__file__), '.unittest'))
1316

14-
__tmp_file_name = '.classifier_test'
17+
__tmp_files = [u'test_file', u'test_file_中文']
18+
__tmp_dirs = [u'test_dir', u'test_dir_中文']
1519

16-
def test_moveto(self):
20+
def setUp(self):
21+
if not os.path.exists(self.__location):
22+
os.mkdir(self.__location)
1723
os.chdir(self.__location)
18-
tmp_file = open(self.__tmp_file_name, 'w')
24+
for file_ in self.__tmp_files:
25+
open(file_, 'w').close()
26+
for dir_ in self.__tmp_dirs:
27+
if not os.path.exists(dir_):
28+
os.mkdir(dir_)
29+
super(ClassifierTest, self).setUp()
30+
31+
def tearDown(self):
32+
shutil.rmtree(self.__location)
33+
super(ClassifierTest, self).tearDown()
1934

20-
parent_dir = os.path.abspath(os.path.join(self.__location, os.pardir))
21-
clf.moveto(self.__tmp_file_name, self.__location, parent_dir)
35+
def test_moveto(self):
36+
target_dir = os.path.abspath(os.path.join(self.__location, 'moveto'))
37+
for file_ in self.__tmp_files:
38+
clf.moveto(file_, self.__location, target_dir)
39+
40+
for file_ in self.__tmp_files:
41+
final_file_path = os.path.join(target_dir, file_)
42+
self.assertTrue(os.path.exists(final_file_path))
43+
44+
def test_classify_bydate(self):
45+
date_format = 'DD-MM-YYYY'
46+
target_files = []
47+
for file_ in self.__tmp_files:
48+
target_dir = arrow.get(os.path.getctime(file_)).format(date_format)
49+
final_file_path = os.path.join(target_dir, file_)
50+
target_files.append(final_file_path)
51+
clf.classify_by_date(date_format, self.__location)
52+
for file_ in target_files:
53+
self.assertTrue(os.path.exists(final_file_path))
54+
for dir_ in self.__tmp_dirs:
55+
self.assertTrue(os.path.exists(dir_))
2256

23-
final_file_path = os.path.join(parent_dir, self.__tmp_file_name)
24-
self.assertTrue(os.path.exists(final_file_path))
25-
os.remove(final_file_path)
2657

2758
if __name__ == '__main__':
2859
unittest.main()

0 commit comments

Comments
 (0)