i3pystatus/tests/test_core_util.py
Егор 0d7156b5b1 WIP: Fix pycodestyle errors (#653)
* Fix pycodestyle errors

W503 is condracting PEP-8 and was added to the default ignore list by
pycodestyle developers

* Use setup.cfg for pycodestyle ignore parameters

Addresses #651 (kind of). Appending ignores to the default list prevents
us from getting warnings that we don't care about.

* W503 is not in the default ignore list in 2.4.0
2018-08-06 13:29:19 +00:00

235 lines
7.9 KiB
Python

#!/usr/bin/env python
import unittest
from unittest.mock import MagicMock
import string
import random
import types
import pytest
from i3pystatus.core.exceptions import ConfigAmbigiousClassesError, ConfigInvalidModuleError
from i3pystatus.core import util, ClassFinder
def test_lchop_prefixed():
assert util.lchop("12345", "12") == "345"
def test_lchop_no_prefix():
assert util.lchop("345", "") == "345"
def test_lchop_unmatched():
assert util.lchop("12345", "345") == "12345"
@pytest.mark.parametrize("iterable, limit, assrt", [
([1, 2, 3, 4], 3, [[1, 2], [3], [4]]),
([2, 1, 3, 4], 3, [[1, 2], [3], [4]]),
([0.33, 0.45, 0.89], 1, [[0.33, 0.45, 0.89]]),
([], 10, []),
])
def test_partition(iterable, limit, assrt):
partitions = util.partition(iterable, limit)
partitions = [sorted(partition) for partition in partitions]
for item in assrt:
assert sorted(item) in partitions
@pytest.mark.parametrize("iterable, predicate, assrt", [
([1, 2, 3, 4], lambda x: x < 2, []),
([1, 2, 3, 4], lambda x: x < 5 and x > 2, [4, 3]),
([1, 2, 3, 4], lambda x: x == 4, [4]),
([1, 2, 3, 4], lambda x: True, [4, 3, 2, 1]),
([1, 2], lambda x: False, []),
])
def test_popwhile(iterable, predicate, assrt):
assert list(util.popwhile(predicate, iterable)) == assrt
@pytest.mark.parametrize("valid, required, feed, missing", [
# ( valid, required, feed, missing )
(("foo", "bar", "baz"), ("foo",), ("bar",), ("foo",)),
(("foo", "bar", "baz"), ("foo",), tuple(), ("foo",)),
(("foo", "bar", "baz"), ("bar", "baz"), ("bar", "baz"), tuple()),
(("foo", "bar", "baz"), ("bar", "baz"), ("bar", "foo", "baz"), tuple()),
])
def test_keyconstraintdict_missing(valid, required, feed, missing):
kcd = util.KeyConstraintDict(valid_keys=valid, required_keys=required)
kcd.update(dict.fromkeys(feed))
assert kcd.missing() == set(missing)
class ModuleListTests(unittest.TestCase):
class ModuleBase:
pass
def setUp(self):
self.status_handler = MagicMock()
self.ml = util.ModuleList(self.status_handler, ClassFinder(self.ModuleBase))
def test_append_simple(self):
module = self.ModuleBase()
module.registered = MagicMock()
self.ml.append(module)
module.registered.assert_called_with(self.status_handler)
def _create_module_class(self, name, bases=None):
if not bases:
bases = (self.ModuleBase,)
return type(name, bases, {
"registered": MagicMock(),
"__init__": MagicMock(return_value=None),
})
def test_append_class_instanciation(self):
module_class = self._create_module_class("module_class")
self.ml.append(module_class)
module_class.__init__.assert_called_with()
module_class.registered.assert_called_with(self.status_handler)
def test_append_module(self):
pymod = types.ModuleType("test_mod")
pymod.some_class = self._create_module_class("some_class")
pymod.some_class.__module__ = "test_mod"
self.ml.append(pymod)
pymod.some_class.__init__.assert_called_with()
pymod.some_class.registered.assert_called_with(self.status_handler)
def test_append_module2(self):
# Here we test if imported classes are ignored as they should
pymod = types.ModuleType("test_mod")
pymod.some_class = self._create_module_class("some_class")
pymod.some_class.__module__ = "other_module"
with self.assertRaises(ConfigInvalidModuleError):
self.ml.append(pymod)
assert not pymod.some_class.__init__.called
assert not pymod.some_class.registered.called
def test_ambigious_classdef(self):
pymod = types.ModuleType("test_mod")
pymod.some_class = self._create_module_class("some_class")
pymod.some_class.__module__ = "test_mod"
pymod.some_other_class = self._create_module_class("some_other_class")
pymod.some_other_class.__module__ = "test_mod"
with self.assertRaises(ConfigAmbigiousClassesError):
self.ml.append(pymod)
def test_invalid_module(self):
pymod = types.ModuleType("test_mod")
with self.assertRaises(ConfigInvalidModuleError):
self.ml.append(pymod)
def test_append_class_inheritance(self):
in_between = self._create_module_class("in_between")
cls = self._create_module_class("cls", (in_between,))
self.ml.append(cls)
cls.__init__.assert_called_with()
cls.registered.assert_called_with(self.status_handler)
class KeyConstraintDictAdvancedTests(unittest.TestCase):
def test_invalid_1(self):
kcd = util.KeyConstraintDict(valid_keys=tuple(), required_keys=tuple())
with self.assertRaises(KeyError):
kcd["invalid"] = True
def test_invalid_2(self):
kcd = util.KeyConstraintDict(
valid_keys=("foo", "bar"), required_keys=tuple())
with self.assertRaises(KeyError):
kcd["invalid"] = True
def test_incomplete_iteration(self):
kcd = util.KeyConstraintDict(
valid_keys=("foo", "bar"), required_keys=("foo",))
with self.assertRaises(util.KeyConstraintDict.MissingKeys):
for x in kcd:
pass
def test_completeness(self):
kcd = util.KeyConstraintDict(
valid_keys=("foo", "bar"), required_keys=("foo",))
kcd["foo"] = False
for x in kcd:
pass
assert kcd.missing() == set()
def test_remove_required(self):
kcd = util.KeyConstraintDict(
valid_keys=("foo", "bar"), required_keys=("foo",))
kcd["foo"] = None
assert kcd.missing() == set()
del kcd["foo"]
assert kcd.missing() == {"foo"}
def test_set_twice(self):
kcd = util.KeyConstraintDict(
valid_keys=("foo", "bar"), required_keys=("foo",))
kcd["foo"] = 1
kcd["foo"] = 2
assert kcd.missing() == set()
del kcd["foo"]
assert kcd.missing() == {"foo"}
class FormatPTests(unittest.TestCase):
def test_escaping(self):
assert util.formatp(r"[razamba \[ mabe \]]") == "razamba [ mabe ]"
def test_numerical(self):
assert util.formatp("[{t} - [schmuh {x}]]", t=1, x=2) == "1 - schmuh 2"
assert util.formatp("[{t} - [schmuh {x}]]", t=1, x=0) == "1 - "
assert util.formatp("[{t} - [schmuh {x}]]", t=0, x=0) == ""
def test_nesting(self):
s = "[[{artist} - ]{album} - ]{title}"
assert util.formatp(s, title="Black rose") == "Black rose"
assert util.formatp(
s, artist="In Flames", title="Gyroscope") == "Gyroscope"
assert util.formatp(
s, artist="SOAD", album="Toxicity", title="Science") == "SOAD - Toxicity - Science"
assert util.formatp(
s, album="Toxicity", title="Science") == "Toxicity - Science"
def test_bare(self):
assert util.formatp("{foo} blar", foo="bar") == "bar blar"
def test_presuffix(self):
assert util.formatp(
"ALINA[{title} schnacke]KOMMAHER", title="") == "ALINAKOMMAHER"
assert util.formatp("grml[{title}]") == "grml"
assert util.formatp("[{t}]grml") == "grml"
def test_side_by_side(self):
s = "{status} [{artist} / [{album} / ]]{title}[ {song_elapsed}/{song_length}]"
assert util.formatp(s, status="", title="Only For The Weak",
song_elapsed="1:41", song_length="4:55") == "▷ Only For The Weak 1:41/4:55"
assert util.formatp(
s, status="", album="Foo", title="Die, Die, Crucified", song_elapsed="2:52") == " Die, Die, Crucified"
assert util.formatp("[[{a}][{b}]]", b=1) == "1"
def test_complex_field(self):
class NS:
pass
obj = NS()
obj.attr = "bar"
s = "[{a:.3f} m]{obj.attr}"
assert util.formatp(s, a=3.14123456789, obj=obj) == "3.141 mbar"
assert util.formatp(s, a=0.0, obj=obj) == "bar"