Skip to content

Commit

Permalink
Merge f7e204a into 9f1deb1
Browse files Browse the repository at this point in the history
  • Loading branch information
wimglenn committed Oct 8, 2018
2 parents 9f1deb1 + f7e204a commit 8f69e29
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 53 deletions.
5 changes: 1 addition & 4 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
[bdist_wheel]
universal = 1

[metadata]
license_file = LICENSE
universal = true

[coverage:run]
branch = True
Expand Down
18 changes: 9 additions & 9 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
from setuptools import find_packages, setup
from setuptools import setup

setup(
name='wimpy',
version='0.4',
description='Anti-copy-pasta',
url='https://github.com/wimglenn/wimpy',
author='Wim Glenn',
author_email='hey@wimglenn.com',
license='MIT',
packages=find_packages(exclude=['tests']),
name="wimpy",
version="0.5",
description="Anti-copy-pasta",
url="https://github.com/wimglenn/wimpy",
author="Wim Glenn",
author_email="hey@wimglenn.com",
license="MIT",
packages=["wimpy"],
)
97 changes: 63 additions & 34 deletions tests/test_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,35 @@

import pytest

from wimpy import WimpyError
from wimpy import cached_property
from wimpy import ceiling_division
from wimpy import chunks
from wimpy import grouper
from wimpy import is_subsequence
from wimpy import strip_prefix
from wimpy import strip_suffix
from wimpy import WimpyError
from wimpy import working_directory


@pytest.mark.parametrize('in_,pre,out', [
('www.yahoo.com', 'www.', 'yahoo.com'),
('www.yahoo.com', 'Www.', 'www.yahoo.com'),
])
@pytest.mark.parametrize(
"in_,pre,out",
[
("www.yahoo.com", "www.", "yahoo.com"),
("www.yahoo.com", "Www.", "www.yahoo.com"),
],
)
def test_strip_prefix(in_, pre, out):
assert strip_prefix(in_, pre) == out


@pytest.mark.parametrize('in_,suf,out', [
('www.yahoo.com', 'www.', 'www.yahoo.com'),
('www.yahoo.com', '.com', 'www.yahoo'),
])
@pytest.mark.parametrize(
"in_,suf,out",
[
("www.yahoo.com", "www.", "www.yahoo.com"),
("www.yahoo.com", ".com", "www.yahoo"),
],
)
def test_strip_suffix(in_, suf, out):
assert strip_suffix(in_, suf) == out

Expand All @@ -45,11 +52,11 @@ def prop(self):

def test_cached_property():
a = A()
assert 'prop' not in a.__dict__
assert "prop" not in a.__dict__
x = a.prop
assert 'prop' in a.__dict__
assert "prop" in a.__dict__
y = a.prop
assert 0. < x == y < 1.
assert 0.0 < x == y < 1.0
del a.prop # invalidate cache
z = a.prop # prop recomputed
assert x == y != z
Expand All @@ -60,45 +67,48 @@ def test_cached_property():
assert isinstance(A.prop, cached_property)


@pytest.mark.parametrize('numerator,denominator,result', [
(51, 10, 6),
(50, 10, 5),
(49, 10, 5),
(-49, 10, -4),
])
@pytest.mark.parametrize(
"numerator,denominator,result",
[(51, 10, 6), (50, 10, 5), (49, 10, 5), (-49, 10, -4)],
)
def test_ceiling_div(numerator, denominator, result):
assert ceiling_division(numerator, denominator) == result



@pytest.mark.parametrize('iterable,n,fillvalue,result', [
(range(6), 2, None, [(0, 1), (2, 3), (4, 5)]),
(range(5), 2, None, [(0, 1), (2, 3), (4, None)]),
(range(5), 2, 123, [(0, 1), (2, 3), (4, 123)]),
])
@pytest.mark.parametrize(
"iterable,n,fillvalue,result",
[
(range(6), 2, None, [(0, 1), (2, 3), (4, 5)]),
(range(5), 2, None, [(0, 1), (2, 3), (4, None)]),
(range(5), 2, 123, [(0, 1), (2, 3), (4, 123)]),
],
)
def test_grouper(iterable, n, fillvalue, result):
assert list(grouper(iterable, n, fillvalue)) == result


@pytest.mark.parametrize('iterable,chunk_size,overlap,result', [
('1234567', 3, 0, [('1', '2', '3'), ('4', '5', '6'), ('7',)]),
('123456', 3, 0, [('1', '2', '3'), ('4', '5', '6')]),
('123456', 4, 2, [('1', '2', '3', '4'), ('3', '4', '5', '6')]),
('', 3, 0, []),
])
@pytest.mark.parametrize(
"iterable,chunk_size,overlap,result",
[
("1234567", 3, 0, [("1", "2", "3"), ("4", "5", "6"), ("7",)]),
("123456", 3, 0, [("1", "2", "3"), ("4", "5", "6")]),
("123456", 4, 2, [("1", "2", "3", "4"), ("3", "4", "5", "6")]),
("", 3, 0, []),
],
)
def test_chunks(iterable, chunk_size, overlap, result):
assert list(chunks(iterable, chunk_size, overlap)) == result


def test_chunks_doesnt_get_stuck_due_to_small_chunk_size():
gen = chunks('123456', chunk_size=0)
with pytest.raises(WimpyError, match='chunk size too small'):
gen = chunks("123456", chunk_size=0)
with pytest.raises(WimpyError, match="chunk size too small"):
next(gen)


def test_chunks_doesnt_get_stuck_due_to_big_overlap():
gen = chunks('123456', chunk_size=3, overlap=3)
with pytest.raises(WimpyError, match='overlap too large'):
gen = chunks("123456", chunk_size=3, overlap=3)
with pytest.raises(WimpyError, match="overlap too large"):
next(gen)


Expand All @@ -108,3 +118,22 @@ def test_chunks_from_infinite_generator():
assert next(g) == (0, 0, 0, 0, 0)
assert next(g) == (0, 0, 0, 0, 0)
assert next(g) == (0, 0, 0, 0, 0)


@pytest.mark.parametrize(
"needle,haystack,result",
[
("23", "1234", True),
("32", "1234", False),
("24", "1234", True),
("1234", "1234", True),
("1234", "123", False),
("113", "112233", True),
("1113", "112233", False),
("", "x", True),
("", "", True),
("x", "", False),
],
)
def test_is_subsequence(needle, haystack, result):
assert is_subsequence(needle, haystack) == result
2 changes: 1 addition & 1 deletion wimpy/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from wimpy.exceptions import WimpyError
from wimpy.util import *

__version__ = '0.4'
__version__ = "0.5"
30 changes: 25 additions & 5 deletions wimpy/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,24 @@
from wimpy.exceptions import WimpyError


__all__ = ['cached_property', 'working_directory', 'strip_prefix', 'strip_suffix', 'ceiling_division', 'grouper', 'chunks']
__all__ = [
"cached_property",
"working_directory",
"strip_prefix",
"strip_suffix",
"ceiling_division",
"grouper",
"chunks",
"is_subsequence",
]


class cached_property(object):
"""
non-data descriptor: property is computed once per instance and then replaces itself
with an ordinary attribute. Deleting the attribute invalidates the cache.
"""

def __init__(self, func):
update_wrapper(self, func)
self.func = func
Expand All @@ -41,22 +51,22 @@ def working_directory(path):
def strip_prefix(s, prefix):
"""Removes the prefix, if it's there, otherwise returns input string unchanged"""
if s.startswith(prefix):
return s[len(prefix):]
return s[len(prefix) :]
return s


def strip_suffix(s, suffix):
"""Removes the suffix, if it's there, otherwise returns input string unchanged"""
if s.endswith(suffix):
return s[:len(s) - len(suffix)]
return s[: len(s) - len(suffix)]
return s


def ceiling_division(numerator, denominator):
"""Divide and round up"""
# Implementation relies on Python's // operator using floor division (round down)
# This might surprise C users who expect rounding towards zero
return -(-numerator//denominator)
return -(-numerator // denominator)


def grouper(iterable, n, fillvalue=None):
Expand Down Expand Up @@ -87,4 +97,14 @@ def chunks(iterable, chunk_size=3, overlap=0):
except StopIteration:
# if the iterator is exhausted, yield any remaining elements
if i > 0:
yield tuple(queue)[-i-overlap:]
yield tuple(queue)[-i - overlap :]


def is_subsequence(needle, haystack):
"""Are all the elements of needle contained in haystack, and in the same order?
There may be other elements interspersed throughout"""
it = iter(haystack)
for element in needle:
if element not in it:
return False
return True

0 comments on commit 8f69e29

Please sign in to comment.