Commit 751105ea authored by Bram Schoenmakers's avatar Bram Schoenmakers

Fixed pylint errors

Among others, moved methods by turning them into (inline) functions or
static methods.
parent e276dcd5
from setuptools import setup, find_packages
import os
import re
import codecs
import sys
here = os.path.abspath(os.path.dirname(__file__))
from setuptools import setup, find_packages
_HERE = os.path.abspath(os.path.dirname(__file__))
def read(*parts):
# intentionally *not* adding an encoding option to open
return codecs.open(os.path.join(here, *parts), 'r').read()
return codecs.open(os.path.join(_HERE, *parts), 'r').read()
def find_version(*file_paths):
......@@ -24,17 +24,17 @@ WATCHDOG = 'watchdog >= 0.8.3'
ICALENDAR = 'icalendar'
setup(
name = "topydo",
packages = find_packages(exclude=["test"]),
version = find_version('topydo', 'lib', 'Version.py'),
description = "A powerful todo.txt application for the console",
author = "Bram Schoenmakers",
author_email = "bram@topydo.org",
url = "https://www.topydo.org",
install_requires = [
name="topydo",
packages=find_packages(exclude=["test"]),
version=find_version('topydo', 'lib', 'Version.py'),
description="A powerful todo.txt application for the console",
author="Bram Schoenmakers",
author_email="bram@topydo.org",
url="https://www.topydo.org",
install_requires=[
'arrow >= 0.7.0',
],
extras_require = {
extras_require={
':sys_platform=="win32"': ['colorama>=0.2.5'],
':python_version=="3.2"': ['backports.shutil_get_terminal_size>=1.0.0'],
'columns': ['urwid >= 1.3.0', WATCHDOG],
......@@ -43,10 +43,10 @@ setup(
'test': ['coverage>=4.3', 'freezegun', 'green', ICALENDAR, 'pylint>=1.7.1'],
'test:python_version=="3.2"': ['mock'],
},
entry_points= {
'console_scripts': ['topydo = topydo.ui.UILoader:main'],
entry_points={
'console_scripts': ['topydo=topydo.ui.UILoader:main'],
},
classifiers = [
classifiers=[
"Development Status :: 5 - Production/Stable",
"Environment :: Console",
"Intended Audience :: End Users/Desktop",
......@@ -60,7 +60,7 @@ setup(
"Programming Language :: Python :: Implementation :: PyPy",
"Topic :: Utilities",
],
long_description = """\
long_description="""\
topydo is a powerful and customizable todo.txt application for the console, inspired by the todo.txt CLI by Gina Trapani.
Highlights of the additional features it provides:
......@@ -74,5 +74,5 @@ Highlights of the additional features it provides:
* Some conveniences when adding new items (e.g. adding creation date and use relative dates)
""",
test_suite = "test",
test_suite="test",
)
......@@ -15,7 +15,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import unittest
from unittest import skip
from test.topydo_testcase import TopydoTest
from topydo.lib.Config import config
......@@ -167,7 +166,7 @@ class ConfigTest(TopydoTest):
def test_config28(self):
""" test duplicates. """
keymap, keystates = config("test/data/ConfigTest7.conf").column_keymap()
keymap, _ = config("test/data/ConfigTest7.conf").column_keymap()
self.assertEqual(keymap['k'], 'bar')
self.assertEqual(keymap['z'], 'foobar')
......
......@@ -100,18 +100,17 @@ class DoCommandTest(CommandTest):
self.assertEqual(self.errors, "")
def test_do_subtasks_force1(self):
prompt_shown = False
def prompt(p_prompt):
global prompt_shown
prompt_shown = True
prompt.prompt_shown = True
prompt.prompt_shown = False
command = DoCommand(["-f", "1"], self.todolist, self.out, self.error,
prompt)
command.execute()
command.execute_post_archive_actions()
self.assertFalse(prompt_shown)
self.assertFalse(prompt.prompt_shown)
self.assertEqual(self.errors, "")
self.assertFalse(self.todolist.todo(2).is_completed())
......
......@@ -27,7 +27,7 @@ from topydo.lib.Config import config, ConfigError
class GetSubcommandTest(TopydoTest):
def test_normal_cmd(self):
args = ["add"]
real_cmd, final_args = get_subcommand(args)
real_cmd, _ = get_subcommand(args)
self.assertTrue(issubclass(real_cmd, AddCommand))
def test_cmd_help(self):
......
......@@ -15,7 +15,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import unittest
from datetime import date, timedelta
from datetime import date
from freezegun import freeze_time
from test.topydo_testcase import TopydoTest
......
......@@ -35,6 +35,9 @@ class DoCommand(DCommand):
super().__init__(
p_args, p_todolist, p_out, p_err, p_prompt)
self.condition = lambda todo: not todo.is_completed()
self.condition_failed_text = "Todo has already been completed."
def get_flags(self):
""" Additional flags. """
opts, long_opts = super().get_flags()
......@@ -75,15 +78,6 @@ class DoCommand(DCommand):
def prefix(self):
return "Completed: "
def condition(self, p_todo):
"""
An additional condition whether execute_specific should be executed.
"""
return not p_todo.is_completed()
def condition_failed_text(self):
return "Todo has already been completed."
def execute_specific(self, p_todo):
""" Actions specific to this command. """
self._handle_recurrence(p_todo)
......
......@@ -44,11 +44,11 @@ class EditCommand(MultiCommand):
def get_flags(self):
return ("dE:", [])
def process_flag(self, p_opt, p_value):
if p_opt == '-d':
def process_flag(self, p_option, p_value):
if p_option == '-d':
self.edit_archive = True
self.multi_mode = False
elif p_opt == '-E':
elif p_option == '-E':
self.editor = shlex.split(p_value)
def _process_flags(self):
......@@ -71,9 +71,10 @@ class EditCommand(MultiCommand):
return f
def _todos_from_temp(self, p_temp_file):
f = codecs.open(p_temp_file.name, encoding='utf-8')
todos = f.read().splitlines()
@staticmethod
def _todos_from_temp(p_temp_file):
with codecs.open(p_temp_file.name, encoding='utf-8') as temp:
todos = temp.read().splitlines()
todo_objs = []
for todo in todos:
......@@ -112,7 +113,7 @@ class EditCommand(MultiCommand):
orig_mtime = _get_file_mtime(temp_todos)
if not self._open_in_editor(temp_todos.name):
new_todos = self._todos_from_temp(temp_todos)
new_todos = EditCommand._todos_from_temp(temp_todos)
if _is_edited(orig_mtime, temp_todos):
for todo in self.todos:
......
......@@ -90,7 +90,7 @@ class ListCommand(ExpressionCommand):
elif opt == '-N':
# 2 lines are assumed to be taken up by printing the next prompt
# display at least one item
self.limit = self._N_lines()
self.limit = ListCommand._N_lines()
elif opt == '-n':
try:
self.limit = int(value)
......@@ -164,7 +164,8 @@ class ListCommand(ExpressionCommand):
return View(sorter, filters, self.todolist)
def _N_lines(self):
@staticmethod
def _N_lines():
''' Determine how many lines to print, such that the number of items
displayed will fit on the terminal (i.e one 'screen-ful' of items)
......@@ -182,7 +183,7 @@ class ListCommand(ExpressionCommand):
if "win32" in sys.platform:
lines_in_prompt += 1 # Windows will typically print a free line after
# the program output
a = re.findall('\$_', os.getenv('PROMPT', ''))
a = re.findall(r'\$_', os.getenv('PROMPT', ''))
lines_in_prompt += len(a)
else:
a = re.findall('\\n', os.getenv('PS1', ''))
......
......@@ -37,8 +37,8 @@ class PostponeCommand(MultiCommand):
def get_flags(self):
return("s", [])
def process_flag(self, p_opt, p_value):
if p_opt == '-s':
def process_flag(self, p_option, p_value):
if p_option == '-s':
self.move_start_date = True
def _execute_multi_specific(self):
......
......@@ -43,11 +43,11 @@ def get_backup_path():
class ChangeSet(object):
""" Class for operations related with backup management. """
def __init__(self, p_todolist=None, p_archive=None, p_label=[]):
def __init__(self, p_todolist=None, p_archive=None, p_label=None):
self.todolist = deepcopy(p_todolist)
self.archive = deepcopy(p_archive)
self.timestamp = str(int(time.time()))
self.label = ' '.join(p_label)
self.label = ' '.join(p_label if p_label else [])
try:
self.json_file = open(get_backup_path(), 'r+b')
......
......@@ -36,13 +36,14 @@ class DCommand(MultiCommand):
self.force = False
self._delta = []
self.condition = lambda _: True
self.condition_failed_text = ""
def get_flags(self):
return ("f", ["force"])
def process_flag(self, p_opt, p_value):
if p_opt == "-f" or p_opt == "--force":
def process_flag(self, p_option, p_value):
if p_option == "-f" or p_option == "--force":
self.force = True
def _uncompleted_children(self, p_todo):
......@@ -93,15 +94,6 @@ class DCommand(MultiCommand):
return [todo for todo in self.todolist.todos()
if not self._uncompleted_children(todo) and todo.is_active()]
def condition(self, _):
"""
An additional condition whether execute_specific should be executed.
"""
return True
def condition_failed_text(self):
raise NotImplementedError
def execute_specific(self, _):
raise NotImplementedError
......@@ -120,7 +112,7 @@ class DCommand(MultiCommand):
self._process_subtasks(todo)
self.execute_specific(todo)
else:
self.error(self.condition_failed_text())
self.error(self.condition_failed_text)
current_active = self._active_todos()
self._delta = [todo for todo in current_active
......
......@@ -14,8 +14,6 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import re
from topydo.lib import Filter
from topydo.lib.Command import Command
from topydo.lib.Config import config
......
......@@ -205,7 +205,7 @@ class ListFormatParser(object):
'T': lambda t: humanize_date(t.start_date()) if t.start_date() else '',
# unique text ID
'u': lambda t: self.todolist.uid(t),
'u': self.todolist.uid,
# unique text ID, padded with spaces
'U': lambda t: _filler(self.todolist.uid(t),
......
......@@ -148,57 +148,7 @@ class Sorter(object):
"""
def __init__(self, p_sortstring="desc:priority", p_groupstring=""):
self.groupfunctions = self._parse(p_groupstring, p_group=True) if p_groupstring else []
self.pregroupfunctions = self._parse(p_groupstring, p_group=False) if p_groupstring else []
self.sortfunctions = self._parse(p_sortstring, p_group=False)
def sort(self, p_todos):
"""
Sorts the list of todos given as a parameter, returns a new sorted
list.
The list is traversed in reverse order, such that the most specific
sort operation is done first, relying on the stability of the sorted()
function.
"""
return _apply_sort_functions(p_todos, self.sortfunctions)
def group(self, p_todos):
"""
Groups the todos according to the given group string.
"""
# preorder todos for the group sort
p_todos = _apply_sort_functions(p_todos, self.pregroupfunctions)
# initialize result with a single group
result = OrderedDict([((), p_todos)])
for (function, label), _ in self.groupfunctions:
oldresult = result
result = OrderedDict()
for oldkey, oldgroup in oldresult.items():
for key, _group in groupby(oldgroup, function):
newgroup = list(_group)
if not isinstance(key, list):
key = [key]
for subkey in key:
subkey = "{}: {}".format(label, subkey)
newkey = oldkey + (subkey,)
if newkey in result:
result[newkey] = result[newkey] + newgroup
else:
result[newkey] = newgroup
# sort all groups
for key, _group in result.items():
result[key] = self.sort(_group)
return result
def _parse(self, p_string, p_group):
def parse(p_string, p_group):
"""
Parses a sort/group string and returns a list of functions and the
desired order.
......@@ -270,3 +220,53 @@ class Sorter(object):
return result
self.groupfunctions = parse(p_groupstring, p_group=True) if p_groupstring else []
self.pregroupfunctions = parse(p_groupstring, p_group=False) if p_groupstring else []
self.sortfunctions = parse(p_sortstring, p_group=False)
def sort(self, p_todos):
"""
Sorts the list of todos given as a parameter, returns a new sorted
list.
The list is traversed in reverse order, such that the most specific
sort operation is done first, relying on the stability of the sorted()
function.
"""
return _apply_sort_functions(p_todos, self.sortfunctions)
def group(self, p_todos):
"""
Groups the todos according to the given group string.
"""
# preorder todos for the group sort
p_todos = _apply_sort_functions(p_todos, self.pregroupfunctions)
# initialize result with a single group
result = OrderedDict([((), p_todos)])
for (function, label), _ in self.groupfunctions:
oldresult = result
result = OrderedDict()
for oldkey, oldgroup in oldresult.items():
for key, _group in groupby(oldgroup, function):
newgroup = list(_group)
if not isinstance(key, list):
key = [key]
for subkey in key:
subkey = "{}: {}".format(label, subkey)
newkey = oldkey + (subkey,)
if newkey in result:
result[newkey] = result[newkey] + newgroup
else:
result[newkey] = newgroup
# sort all groups
for key, _group in result.items():
result[key] = self.sort(_group)
return result
......@@ -116,7 +116,7 @@ class TodoList(TodoListBase):
super().add_todos(p_todos)
for todo in self._todos:
todo.parents = types.MethodType(lambda i: self.parents(i), todo)
todo.parents = types.MethodType(self.parents, todo)
# only do administration when the dependency info is initialized,
# otherwise we postpone it until it's really needed (through the
......
......@@ -177,7 +177,8 @@ class CLIApplicationBase(object):
self._post_archive_action = None
self.backup = None
def _usage(self):
@staticmethod
def _usage():
usage()
sys.exit(0)
......@@ -208,7 +209,7 @@ class CLIApplicationBase(object):
elif opt in ("-v", "--version"):
version()
else:
self._usage()
CLIApplicationBase._usage()
if alt_config_path:
config(alt_config_path, overrides)
......@@ -237,21 +238,17 @@ class CLIApplicationBase(object):
if archive.dirty:
archive_file.write(archive.print_todos())
def _help(self, args):
if args is None:
pass # TODO
else:
pass # TODO
def is_read_only(self, p_command):
@staticmethod
def is_read_only(p_command):
""" Returns True when the given command class is read-only. """
read_only_commands = tuple(cmd for cmd
in ('revert', ) + READ_ONLY_COMMANDS)
return p_command.name() in read_only_commands
def _backup(self, p_command, p_args=[], p_label=None):
if config().backup_count() > 0 and p_command and not self.is_read_only(p_command):
call = [p_command.name()]+ p_args
def _backup(self, p_command, p_args=None, p_label=None):
if config().backup_count() > 0 and p_command and not CLIApplicationBase.is_read_only(p_command):
p_args = p_args if p_args else []
call = [p_command.name()] + p_args
from topydo.lib.ChangeSet import ChangeSet
label = p_label if p_label else call
......
......@@ -57,7 +57,7 @@ class CLIApplication(CLIApplicationBase):
sys.exit(1)
if subcommand is None:
self._usage()
CLIApplicationBase._usage()
if self._execute(subcommand, args) == False:
sys.exit(1)
......
......@@ -196,24 +196,7 @@ class UIApplication(CLIApplicationBase):
self._screen = urwid.raw_display.Screen()
if config().colors():
self._screen.register_palette(self._create_color_palette())
else:
self._screen.register_palette(self._create_mono_palette())
self._screen.set_terminal_properties(256)
self.mainloop = urwid.MainLoop(
self.mainwindow,
screen=self._screen,
unhandled_input=self._handle_input,
pop_ups=True
)
self.column_mode = _APPEND_COLUMN
self._set_alarm_for_next_midnight_update()
def _create_color_palette(self):
def create_color_palette():
project_color = to_urwid_color(config().project_color())
context_color = to_urwid_color(config().context_color())
metadata_color = to_urwid_color(config().metadata_color())
......@@ -249,7 +232,7 @@ class UIApplication(CLIApplicationBase):
return palette
def _create_mono_palette(self):
def create_mono_palette():
palette = [
(PaletteItem.DEFAULT_FOCUS, 'black', 'light gray'),
(PaletteItem.PROJECT_FOCUS, PaletteItem.DEFAULT_FOCUS),
......@@ -266,6 +249,23 @@ class UIApplication(CLIApplicationBase):
return palette
if config().colors():
self._screen.register_palette(create_color_palette())
else:
self._screen.register_palette(create_mono_palette())
self._screen.set_terminal_properties(256)
self.mainloop = urwid.MainLoop(
self.mainwindow,
screen=self._screen,
unhandled_input=self._handle_input,
pop_ups=True
)
self.column_mode = _APPEND_COLUMN
self._set_alarm_for_next_midnight_update()
def _set_alarm_for_next_midnight_update(self):
def callback(p_loop, p_data):
TodoWidget.wipe_cache()
......
......@@ -91,7 +91,6 @@ class TodoWidget(urwid.WidgetWrap):
priority_widget = urwid.Text(priority_text)
self.text_widget = urwid.Text(txt_markup)
progress = to_urwid_color(progress_color(p_todo)) if config().colors() else PaletteItem.DEFAULT
self.progress_bar = urwid.AttrMap(
urwid.SolidFill(' '),
{},
......
......@@ -16,7 +16,6 @@
""" Entry file for the topydo Prompt interface (CLI). """
import os.path
import shlex
import sys
......@@ -38,7 +37,6 @@ except ConfigError as config_error:
from topydo.Commands import get_subcommand
from topydo.lib.TodoFileWatched import TodoFileWatched
from topydo.lib import TodoList
class PromptApplication(CLIApplicationBase):
......
......@@ -52,15 +52,14 @@ class PromptCompleter(CompleterBase, Completer):
for candidate in candidates:
yield Completion(candidate, -len(p_word))
def get_completions(self, p_document, _):
def get_completions(self, p_word, p_is_first_word=False):
# include all characters except whitespaces (for + and @)
word_before_cursor = p_document.get_word_before_cursor(True)
word_before_cursor = p_word.get_word_before_cursor(True)
is_first_word = not re.match(r'\s*\S+\s',
p_document.current_line_before_cursor)
p_word.current_line_before_cursor)
if word_before_cursor.startswith(config().tag_due() + ':'):
return _dates(word_before_cursor)
elif word_before_cursor.startswith(config().tag_start() + ':'):
return _dates(word_before_cursor)
else:
return self._completion_generator(word_before_cursor, is_first_word)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment