Update test style

This commit is contained in:
Andras Schmelczer 2022-07-05 13:14:05 +02:00
parent f188724d4b
commit 2db2253578
18 changed files with 778 additions and 686 deletions

View file

View file

@ -0,0 +1,62 @@
from asyncio import sleep
import pytest
from great_ai import (
ArgumentValidationError,
GreatAI,
WrongDecoratorOrderError,
parameter,
)
@pytest.mark.asyncio
async def test_create_trivial_cases() -> None:
@GreatAI.create
async def hello_world_1(name: str) -> str:
await sleep(0.5)
return f"Hello {name}!"
assert (await hello_world_1("andras").output) == "Hello andras!"
@GreatAI.create
async def hello_world_2(name: str) -> str:
await sleep(0.5)
return f"Hello {name}!"
assert (await hello_world_2("andras").output) == "Hello andras!"
@GreatAI.create()
async def hello_world_3(name: str) -> str:
await sleep(0.5)
return f"Hello {name}!"
assert (await hello_world_3("andras").output) == "Hello andras!"
@GreatAI.create()
async def hello_world_4(name):
await sleep(0.5)
return f"Hello {name}!"
assert (await hello_world_4("andras").output) == "Hello andras!"
@pytest.mark.asyncio
async def test_with_parameter() -> None:
@GreatAI.create
@parameter("name", validator=lambda v: len(v) > 5)
async def hello_world(name: str) -> str:
await sleep(0.5)
return f"Hello {name}!"
assert (await hello_world("andras").output) == "Hello andras!"
with pytest.raises(ArgumentValidationError):
await hello_world("short")
with pytest.raises(WrongDecoratorOrderError):
@parameter("name", validator=lambda v: len(v) > 5)
@GreatAI.create
def hello_world(name: str) -> str:
return f"Hello {name}!"

View file

@ -1,4 +1,3 @@
import unittest
from functools import lru_cache
import pytest
@ -11,55 +10,62 @@ from great_ai import (
)
class TestHumanReadableToByte(unittest.TestCase):
def test_create_simple_cases(self) -> None:
@GreatAI.create
def hello_world(name: str) -> str:
return f"Hello {name}!"
def test_create_trivial_cases() -> None:
@GreatAI.create
def hello_world_1(name: str) -> str:
return f"Hello {name}!"
assert hello_world("andras").output == "Hello andras!"
assert hello_world_1("andras").output == "Hello andras!"
@GreatAI.create
def hello_world(name):
return f"Hello {name}!"
@GreatAI.create
def hello_world_2(name):
return f"Hello {name}!"
assert hello_world("andras").output == "Hello andras!"
assert hello_world_2("andras").output == "Hello andras!"
@GreatAI.create()
def hello_world(name: str) -> str:
return f"Hello {name}!"
@GreatAI.create()
def hello_world_3(name: str) -> str:
return f"Hello {name}!"
assert hello_world("andras").output == "Hello andras!"
assert hello_world_3("andras").output == "Hello andras!"
def test_create_with_other_decorator(self) -> None:
@GreatAI.create
@lru_cache
def hello_world(name: str) -> str:
return f"Hello {name}!"
@GreatAI.create()
def hello_world_4(name):
return f"Hello {name}!"
assert hello_world("andras").output == "Hello andras!"
assert hello_world_4("andras").output == "Hello andras!"
@lru_cache
@GreatAI.create()
def hello_world(name: str) -> str:
return f"Hello {name}!"
assert hello_world("andras").output == "Hello andras!"
def test_create_with_other_decorator() -> None:
@GreatAI.create
@lru_cache
def hello_world(name: str) -> str:
return f"Hello {name}!"
assert hello_world("andras").output == "Hello andras!"
@lru_cache
@GreatAI.create()
def hello_world(name: str) -> str:
return f"Hello {name}!"
assert hello_world("andras").output == "Hello andras!"
def test_with_parameter() -> None:
@GreatAI.create
@parameter("name", validator=lambda v: len(v) > 5)
def hello_world(name: str) -> str:
return f"Hello {name}!"
assert hello_world("andras").output == "Hello andras!"
with pytest.raises(ArgumentValidationError):
hello_world("short")
with pytest.raises(WrongDecoratorOrderError):
def test_with_parameter(self) -> None:
@GreatAI.create
@parameter("name", validator=lambda v: len(v) > 5)
@GreatAI.create
def hello_world(name: str) -> str:
return f"Hello {name}!"
assert hello_world("andras").output == "Hello andras!"
with pytest.raises(ArgumentValidationError):
hello_world("short")
with pytest.raises(WrongDecoratorOrderError):
@parameter("name", validator=lambda v: len(v) > 5)
@GreatAI.create
def hello_world(name: str) -> str:
return f"Hello {name}!"

View file

@ -0,0 +1,9 @@
from great_ai import GreatAI
def test_process_batch() -> None:
@GreatAI.create(return_raw_result=True)
def f(x):
return x + 2
assert f.process_batch([3, 9, 34]) == [5, 11, 36]

View file

@ -1,26 +1,26 @@
import unittest
from great_ai.large_file.helper import human_readable_to_byte
class TestHumanReadableToByte(unittest.TestCase):
def test_simple_cases(self) -> None:
assert human_readable_to_byte("1KB") == 1024
assert human_readable_to_byte("2KB") == 2048
def test_simple_cases() -> None:
assert human_readable_to_byte("1KB") == 1024
assert human_readable_to_byte("2KB") == 2048
def test_fractions(self) -> None:
assert human_readable_to_byte("0.5KB") == 512
assert human_readable_to_byte("20.5KB") == 1024 * 20 + 512
def test_formatting(self) -> None:
assert human_readable_to_byte(" 1MB") == 1024 * 1024
assert human_readable_to_byte(" 2 MB") == 1024 * 1024 * 2
assert human_readable_to_byte(" 4 MB ") == 1024 * 1024 * 4
assert human_readable_to_byte("8MB ") == 1024 * 1024 * 8
assert human_readable_to_byte(" 1.5 MB ") == 1024 * 1024 * 1.5
def test_fractions() -> None:
assert human_readable_to_byte("0.5KB") == 512
assert human_readable_to_byte("20.5KB") == 1024 * 20 + 512
def test_casing(self) -> None:
assert human_readable_to_byte("0.5GB") == 0.5 * 1024 * 1024 * 1024
assert human_readable_to_byte("0.5gB") == 0.5 * 1024 * 1024 * 1024
assert human_readable_to_byte("0.5Gb") == 0.5 * 1024 * 1024 * 1024
assert human_readable_to_byte("0.5gb") == 0.5 * 1024 * 1024 * 1024
def test_formatting() -> None:
assert human_readable_to_byte(" 1MB") == 1024 * 1024
assert human_readable_to_byte(" 2 MB") == 1024 * 1024 * 2
assert human_readable_to_byte(" 4 MB ") == 1024 * 1024 * 4
assert human_readable_to_byte("8MB ") == 1024 * 1024 * 8
assert human_readable_to_byte(" 1.5 MB ") == 1024 * 1024 * 1.5
def test_casing() -> None:
assert human_readable_to_byte("0.5GB") == 0.5 * 1024 * 1024 * 1024
assert human_readable_to_byte("0.5gB") == 0.5 * 1024 * 1024 * 1024
assert human_readable_to_byte("0.5Gb") == 0.5 * 1024 * 1024 * 1024
assert human_readable_to_byte("0.5gb") == 0.5 * 1024 * 1024 * 1024

View file

@ -1,9 +1,9 @@
import unittest
from pathlib import Path
from typing import Any
from unittest.mock import Mock, patch
import boto3
import pytest
PATH = Path(__file__).parent.resolve()
@ -19,104 +19,112 @@ credentials = {
}
class TestLargeFileS3(unittest.TestCase):
def test_uninitialized(self) -> None:
self.assertRaises(ValueError, LargeFileS3, "test-file")
def test_uninitialized() -> None:
with pytest.raises(ValueError):
LargeFileS3("test-file")
def test_bad_file_modes(self) -> None:
self.assertRaises(ValueError, LargeFileS3, "test-file", "w", version=3)
self.assertRaises(ValueError, LargeFileS3, "test-file", "wb", version=3)
self.assertRaises(ValueError, LargeFileS3, "test-file", "w+r")
self.assertRaises(ValueError, LargeFileS3, "test-file", "test")
@patch.object(boto3, "client")
def test_initialized_with_dict(self, client: Any) -> None:
s3 = Mock()
s3.list_objects_v2 = Mock(
return_value={
"Contents": [
{
"Key": "test-file/0",
"Size": 30,
},
{
"Key": "test-file/1",
"Size": 300,
},
{
"Key": "test-file/2",
"Size": 187,
},
]
}
)
boto3.client = Mock(return_value=s3)
def test_bad_file_modes() -> None:
with pytest.raises(ValueError):
LargeFileS3("test-file", "w", version=3)
LargeFileS3.configure_credentials(
aws_region_name=credentials["aws_region_name"],
aws_access_key_id=credentials["aws_access_key_id"],
aws_secret_access_key=credentials["aws_secret_access_key"],
large_files_bucket_name=credentials["large_files_bucket_name"],
aws_endpoint_url=credentials["aws_endpoint_url"],
)
lf = LargeFileS3("test-file")
with pytest.raises(ValueError):
LargeFileS3("test-file", "wb", version=3)
boto3.client.assert_called_once_with(
"s3",
aws_access_key_id=credentials["aws_access_key_id"],
aws_secret_access_key=credentials["aws_secret_access_key"],
region_name=credentials["aws_region_name"],
endpoint_url=credentials["aws_endpoint_url"],
)
with pytest.raises(ValueError):
LargeFileS3("test-file", "w+r")
s3.list_objects_v2.assert_called_once_with(
Bucket=credentials["large_files_bucket_name"], Prefix="test-file"
)
with pytest.raises(ValueError):
LargeFileS3("test-file", "test")
assert lf._version == 2
assert lf._local_name == "test-file-2"
@patch.object(boto3, "client")
def test_initialized_with_file(self, client: Any) -> None:
s3 = Mock()
s3.list_objects_v2 = Mock(
return_value={
"Contents": [
{
"Key": "test-file/0",
"Size": 30,
},
{
"Key": "test-file/1",
"Size": 300,
},
{
"Key": "test-file/2",
"Size": 187,
},
]
}
)
@patch.object(boto3, "client")
def test_initialized_with_dict(client: Any) -> None:
s3 = Mock()
s3.list_objects_v2 = Mock(
return_value={
"Contents": [
{
"Key": "test-file/0",
"Size": 30,
},
{
"Key": "test-file/1",
"Size": 300,
},
{
"Key": "test-file/2",
"Size": 187,
},
]
}
)
boto3.client = Mock(return_value=s3)
boto3.client = Mock(return_value=s3)
LargeFileS3.configure_credentials(
aws_region_name=credentials["aws_region_name"],
aws_access_key_id=credentials["aws_access_key_id"],
aws_secret_access_key=credentials["aws_secret_access_key"],
large_files_bucket_name=credentials["large_files_bucket_name"],
aws_endpoint_url=credentials["aws_endpoint_url"],
)
lf = LargeFileS3("test-file")
LargeFileS3.configure_credentials_from_file(
PATH / "../../docs/example_secrets.ini"
)
lf = LargeFileS3("test-file")
boto3.client.assert_called_once_with(
"s3",
aws_access_key_id=credentials["aws_access_key_id"],
aws_secret_access_key=credentials["aws_secret_access_key"],
region_name=credentials["aws_region_name"],
endpoint_url=credentials["aws_endpoint_url"],
)
boto3.client.assert_called_once_with(
"s3",
aws_access_key_id=credentials["aws_access_key_id"],
aws_secret_access_key=credentials["aws_secret_access_key"],
region_name=credentials["aws_region_name"],
endpoint_url=credentials["aws_endpoint_url"],
)
s3.list_objects_v2.assert_called_once_with(
Bucket=credentials["large_files_bucket_name"], Prefix="test-file"
)
assert s3.list_objects_v2.called
s3.list_objects_v2.assert_called_once_with(
Bucket=credentials["large_files_bucket_name"], Prefix="test-file"
)
assert lf._version == 2
assert lf._local_name == "test-file-2"
assert lf._version == 2
assert lf._local_name == "test-file-2"
@patch.object(boto3, "client")
def test_initialized_with_file(client: Any) -> None:
s3 = Mock()
s3.list_objects_v2 = Mock(
return_value={
"Contents": [
{
"Key": "test-file/0",
"Size": 30,
},
{
"Key": "test-file/1",
"Size": 300,
},
{
"Key": "test-file/2",
"Size": 187,
},
]
}
)
boto3.client = Mock(return_value=s3)
LargeFileS3.configure_credentials_from_file(PATH / "../../docs/example_secrets.ini")
lf = LargeFileS3("test-file")
boto3.client.assert_called_once_with(
"s3",
aws_access_key_id=credentials["aws_access_key_id"],
aws_secret_access_key=credentials["aws_secret_access_key"],
region_name=credentials["aws_region_name"],
endpoint_url=credentials["aws_endpoint_url"],
)
assert s3.list_objects_v2.called
s3.list_objects_v2.assert_called_once_with(
Bucket=credentials["large_files_bucket_name"], Prefix="test-file"
)
assert lf._version == 2
assert lf._local_name == "test-file-2"

View file

@ -1,32 +1,31 @@
import unittest
import pytest
from great_ai.utilities import chunk
class TestChunk(unittest.TestCase):
def test_simple(self) -> None:
i = [1, 2, 3, 4]
def test_simple() -> None:
i = [1, 2, 3, 4]
assert list(chunk(i, 1)) == [[1], [2], [3], [4]]
assert list(chunk(i, 2)) == [[1, 2], [3, 4]]
assert list(chunk(i, 3)) == [[1, 2, 3], [4]]
assert list(chunk(i, 4)) == [[1, 2, 3, 4]]
assert list(chunk(i, 5)) == [[1, 2, 3, 4]]
assert list(chunk(i, 125)) == [[1, 2, 3, 4]]
assert list(chunk(i, 1)) == [[1], [2], [3], [4]]
assert list(chunk(i, 2)) == [[1, 2], [3, 4]]
assert list(chunk(i, 3)) == [[1, 2, 3], [4]]
assert list(chunk(i, 4)) == [[1, 2, 3, 4]]
assert list(chunk(i, 5)) == [[1, 2, 3, 4]]
assert list(chunk(i, 125)) == [[1, 2, 3, 4]]
def test_bad_argument(self) -> None:
with pytest.raises(AssertionError):
list(chunk([], -10))
with pytest.raises(AssertionError):
list(chunk([], 0))
def test_bad_argument() -> None:
with pytest.raises(AssertionError):
list(chunk([], -10))
def test_generator(self) -> None:
def my_generator():
for i in range(1, 11):
yield i
with pytest.raises(AssertionError):
list(chunk([], 0))
assert list(chunk(range(1, 11), 3)) == [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
assert list(chunk(my_generator(), 3)) == [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
def test_generator() -> None:
def my_generator():
for i in range(1, 11):
yield i
assert list(chunk(range(1, 11), 3)) == [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
assert list(chunk(my_generator(), 3)) == [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]

View file

@ -1,110 +1,112 @@
import unittest
from great_ai.utilities import clean
class TestClean(unittest.TestCase):
def test_xml_handling(self) -> None:
xml = '<strong>Hi, </strong> my name<br/>is <span style="color: hotpink;"> András</span>! &lt;&#51; <> < ></><> &lt;&gt; <|'
clean_xml = "Hi, my name is András! <3 <> <|"
clean_xml_ascii = "Hi, my name is Andras! <3 <> <|"
def test_xml_handling() -> None:
xml = '<strong>Hi, </strong> my name<br/>is <span style="color: hotpink;"> András</span>! &lt;&#51; <> < ></><> &lt;&gt; <|'
clean_xml = "Hi, my name is András! <3 <> <|"
clean_xml_ascii = "Hi, my name is Andras! <3 <> <|"
assert clean(xml) == clean_xml
assert clean(xml, ignore_xml=True, ignore_latex=True) == xml
assert clean(xml, convert_to_ascii=True) == clean_xml_ascii
def test_simple_latex_handling(self) -> None:
latex = 'Bj\\"{o}rn is \\textit{happy} 🙂'
clean_latex = "Björn is happy 🙂"
clean_latex_ascii = "Bjorn is happy"
assert clean(latex) == clean_latex
assert clean(latex, ignore_latex=True) == latex
assert clean(latex, convert_to_ascii=True) == clean_latex_ascii
def test_cursed(self) -> None:
cursed = """
t̴̨̢̝̻͚͓͉̀̄̃́͜o̸͉̰̼͖͖̅̀̓̿̇̚͝ ̶̢͕̄͊̾͑̂̀̉͑ṱ̸̨̛͈̣̠̤͍̰̂̅͋̀́h̸̹̐͗̅̉͐͂͝e̶̜̳̞̍͘ ̴̟̗̻̤̤̮̒̂̋̓́͐͘͜m̵̺̫̥̙̣̥͐̌͜o̴̖͙̙̎̒͂o̷̬̤͑̆̂̉̊̂n̸̥͒̊
"""
cleaned = "to the moon"
assert clean(cursed) == cursed.strip()
assert clean(cursed, convert_to_ascii=True) == cleaned
def test_whitespace(self) -> None:
text = """
word1
word2 \n\n\n\t
wo\t\f rd3
assert clean(xml) == clean_xml
assert clean(xml, ignore_xml=True, ignore_latex=True) == xml
assert clean(xml, convert_to_ascii=True) == clean_xml_ascii
""" # noqa: W293
cleaned = "word1 word2 wo rd3"
def test_simple_latex_handling() -> None:
latex = 'Bj\\"{o}rn is \\textit{happy} 🙂'
clean_latex = "Björn is happy 🙂"
clean_latex_ascii = "Bjorn is happy"
assert clean(text, convert_to_ascii=True) == cleaned
assert clean(text, ignore_xml=True, ignore_latex=True) == cleaned
assert clean(text) == cleaned
assert clean(latex) == clean_latex
assert clean(latex, ignore_latex=True) == latex
assert clean(latex, convert_to_ascii=True) == clean_latex_ascii
def test_hyphens(self) -> None:
text = """
break - word
break- word
break -word
break -word
break-\tword
"""
cleaned = "break - word break-word break-word break-word break-word"
assert clean(text) == cleaned
def test_cursed() -> None:
cursed = """
t̴̨̢̝̻͚͓͉̀̄̃́͜o̸͉̰̼͖͖̅̀̓̿̇̚͝ ̶̢͕̄͊̾͑̂̀̉͑ṱ̸̨̛͈̣̠̤͍̰̂̅͋̀́h̸̹̐͗̅̉͐͂͝e̶̜̳̞̍͘ ̴̟̗̻̤̤̮̒̂̋̓́͐͘͜m̵̺̫̥̙̣̥͐̌͜o̴̖͙̙̎̒͂o̷̬̤͑̆̂̉̊̂n̸̥͒̊
"""
cleaned = "to the moon"
def test_T_I_T_L_E_case(self) -> None:
text = "an a r t i c l e is to F I N D the purpose of a tree"
assert clean(cursed) == cursed.strip()
assert clean(cursed, convert_to_ascii=True) == cleaned
cleaned = "an article is to FIND the purpose of a tree"
assert clean(text) == cleaned
def test_whitespace() -> None:
text = """
def test_bracket_removal(self) -> None:
text = "something [0], and [frefe, ferf]"
cleaned = "something, and"
word1
assert clean(text, remove_brackets=True) == cleaned
self.assertEqual(
clean(text, ignore_xml=True, ignore_latex=True, remove_brackets=True),
cleaned,
)
self.assertEqual(
clean(text, convert_to_ascii=True, remove_brackets=True), cleaned
)
assert clean(text) == text
word2 \n\n\n\t
wo\t\f rd3
def test_latex_math_handling(self) -> None:
latex = "An increase of 3% was achieved with $q_1 = \\frac{3}{5}$."
bad_latex = "An increase of 3% was achieved with $q_1 = \\frac{3}/5$."
clean_latex = "An increase of 3% was achieved with q_1 = 3/5."
clean_bad_latex = "An increase of 3% was achieved with q_1 = 3//5."
assert clean(latex) == clean_latex
assert clean(bad_latex) == clean_bad_latex
assert clean(latex, ignore_latex=True) == latex
assert clean(bad_latex, ignore_latex=True) == bad_latex
""" # noqa: W293
cleaned = "word1 word2 wo rd3"
def test_everything(self) -> None:
text = """
Hi % 3 &gt;2 <h2 color="red">my paper</h2> there! cost- effective cost - effective cost -effective \\frac{1/2} hi \\frac{1}{2} \\textit{italic} \\`acc\\^ented text 北亰 æ IJ ij András öô 2132 rgrv \n\\ &nbsp; fd [32] [Bei et al., 2003]\n 🤡 🙄 😶🌫 🇲🇲
"""
cleaned = "Hi% 3 >2 my paper there! cost-effective cost - effective cost-effective 1/2/hi 1/2 italic accented text Bei Jing fi ae IJ ij ff Andras oo 2132 rgrv fd"
assert clean(text, convert_to_ascii=True) == cleaned
assert clean(text, ignore_xml=True, ignore_latex=True) == cleaned
assert clean(text) == cleaned
self.assertEqual(
clean(text, convert_to_ascii=True, remove_brackets=True), cleaned
)
def test_empty(self) -> None:
assert clean("", convert_to_ascii=True) == ""
def test_hyphens() -> None:
text = """
break - word
break- word
break -word
break -word
break-\tword
"""
cleaned = "break - word break-word break-word break-word break-word"
def test_punctuation_fixing(self) -> None:
text = " Dear reader ( or listener ) , welcome ! "
fixed = "Dear reader (or listener), welcome!"
assert clean(text) == fixed
assert clean(text) == cleaned
def test_T_I_T_L_E_case() -> None:
text = "an a r t i c l e is to F I N D the purpose of a tree"
cleaned = "an article is to FIND the purpose of a tree"
assert clean(text) == cleaned
def test_bracket_removal() -> None:
text = "something [0], and [frefe, ferf]"
cleaned = "something, and"
assert clean(text, remove_brackets=True) == cleaned
assert (
clean(text, ignore_xml=True, ignore_latex=True, remove_brackets=True) == cleaned
)
assert clean(text, convert_to_ascii=True, remove_brackets=True) == cleaned
assert clean(text) == text
def test_latex_math_handling() -> None:
latex = "An increase of 3% was achieved with $q_1 = \\frac{3}{5}$."
bad_latex = "An increase of 3% was achieved with $q_1 = \\frac{3}/5$."
clean_latex = "An increase of 3% was achieved with q_1 = 3/5."
clean_bad_latex = "An increase of 3% was achieved with q_1 = 3//5."
assert clean(latex) == clean_latex
assert clean(bad_latex) == clean_bad_latex
assert clean(latex, ignore_latex=True) == latex
assert clean(bad_latex, ignore_latex=True) == bad_latex
def test_everything() -> None:
text = """
Hi % 3 &gt;2 <h2 color="red">my paper</h2> there! cost- effective cost - effective cost -effective \\frac{1/2} hi \\frac{1}{2} \\textit{italic} \\`acc\\^ented text 北亰 æ IJ ij András öô 2132 rgrv \n\\ &nbsp; fd [32] [Bei et al., 2003]\n 🤡 🙄 😶🌫 🇲🇲
"""
cleaned = "Hi% 3 >2 my paper there! cost-effective cost - effective cost-effective 1/2/hi 1/2 italic accented text Bei Jing fi ae IJ ij ff Andras oo 2132 rgrv fd"
clean(text, convert_to_ascii=True, remove_brackets=True) == cleaned
def test_empty() -> None:
assert clean("", convert_to_ascii=True) == ""
def test_punctuation_fixing() -> None:
text = " Dear reader ( or listener ) , welcome ! "
fixed = "Dear reader (or listener), welcome!"
assert clean(text) == fixed

View file

@ -1,5 +1,4 @@
import os
import unittest
from pathlib import Path
import pytest
@ -9,83 +8,89 @@ from great_ai.utilities import ConfigFile
DATA_PATH = Path(__file__).parent.resolve() / "data"
class TestConfigFile(unittest.TestCase):
def test_simple(self) -> None:
c = ConfigFile(DATA_PATH / "good.conf")
assert c.zeroth_key == "test"
assert c.first_key == "András"
assert c.second_key == "test 2"
assert c.third_key == "test= 2=="
assert (
c.fourth_key
== """
def test_simple() -> None:
c = ConfigFile(DATA_PATH / "good.conf")
assert c.zeroth_key == "test"
assert c.first_key == "András"
assert c.second_key == "test 2"
assert c.third_key == "test= 2=="
assert (
c.fourth_key
== """
this#
is
multiline
"""
)
assert c.whitespace == "hardly matters"
with pytest.raises(KeyError):
c.this
)
assert c.whitespace == "hardly matters"
with pytest.raises(KeyError):
c.this
def test_simple_dict(self) -> None:
c = ConfigFile(DATA_PATH / "good.conf")
assert c["zeroth_key"] == "test"
assert c["first_key"] == "András"
assert c["second_key"] == "test 2"
assert c["third_key"] == "test= 2=="
assert (
c["fourth_key"]
== """
def test_simple_dict() -> None:
c = ConfigFile(DATA_PATH / "good.conf")
assert c["zeroth_key"] == "test"
assert c["first_key"] == "András"
assert c["second_key"] == "test 2"
assert c["third_key"] == "test= 2=="
assert (
c["fourth_key"]
== """
this#
is
multiline
"""
)
assert c["whitespace"] == "hardly matters"
with pytest.raises(KeyError):
c["#this"]
)
assert c["whitespace"] == "hardly matters"
with pytest.raises(KeyError):
c["#this"]
def test_string_path(self) -> None:
c = ConfigFile(str(DATA_PATH / "good.conf"))
assert c.zeroth_key == "test"
assert c.first_key == "András"
assert c.second_key == "test 2"
assert c.third_key == "test= 2=="
assert (
c.fourth_key
== """
def test_string_path() -> None:
c = ConfigFile(str(DATA_PATH / "good.conf"))
assert c.zeroth_key == "test"
assert c.first_key == "András"
assert c.second_key == "test 2"
assert c.third_key == "test= 2=="
assert (
c.fourth_key
== """
this#
is
multiline
"""
)
assert c.whitespace == "hardly matters"
)
assert c.whitespace == "hardly matters"
def test_env(self) -> None:
os.environ["alma"] = "12"
c = ConfigFile(DATA_PATH / "env.conf")
del os.environ["alma"]
assert c.first_key == "test"
assert c.second_key == "12"
def test_env_not_exists(self) -> None:
with pytest.raises(KeyError):
ConfigFile(DATA_PATH / "env-bad.conf")
def test_env() -> None:
os.environ["alma"] = "12"
c = ConfigFile(DATA_PATH / "env.conf")
del os.environ["alma"]
assert c.first_key == "test"
assert c.second_key == "12"
def test_env_not_exists_fallback(self) -> None:
os.environ["alma"] = "12"
c = ConfigFile(DATA_PATH / "env.conf")
assert c.fourth_key == "this is a default value"
def test_env_exists_ignore_fallback(self) -> None:
os.environ["alma"] = "12"
os.environ["SOMETHING"] = "hi"
c = ConfigFile(DATA_PATH / "env.conf")
del os.environ["SOMETHING"]
def test_env_not_exists() -> None:
with pytest.raises(KeyError):
ConfigFile(DATA_PATH / "env-bad.conf")
assert c.fourth_key == "hi"
def test_duplicate_key(self) -> None:
with pytest.raises(KeyError):
ConfigFile(DATA_PATH / "bad.conf")
def test_env_not_exists_fallback() -> None:
os.environ["alma"] = "12"
c = ConfigFile(DATA_PATH / "env.conf")
assert c.fourth_key == "this is a default value"
def test_env_exists_ignore_fallback() -> None:
os.environ["alma"] = "12"
os.environ["SOMETHING"] = "hi"
c = ConfigFile(DATA_PATH / "env.conf")
del os.environ["SOMETHING"]
assert c.fourth_key == "hi"
def test_duplicate_key() -> None:
with pytest.raises(KeyError):
ConfigFile(DATA_PATH / "bad.conf")

View file

@ -1,97 +1,94 @@
import unittest
from pathlib import Path
import matplotlib
import pytest
matplotlib.use("Agg") # don't show a window for each test
from great_ai.utilities import evaluate_ranking
class TestEvaluateRanking(unittest.TestCase):
def test_default(self) -> None:
results = evaluate_ranking(
["a", "a", "b", "b", "c", "d", "d", "d"],
[10, 7, 11, 6, 8, 2, 7, 1],
target_recall=0.6,
reverse_order=True,
)
def test_default() -> None:
results = evaluate_ranking(
["a", "a", "b", "b", "c", "d", "d", "d"],
[10, 7, 11, 6, 8, 2, 7, 1],
target_recall=0.6,
reverse_order=True,
)
self.assertEqual(
results,
{"d": 1.0, "c": 0.6666666666666666, "b": 0.4},
)
assert results == {"d": 1.0, "c": 0.6666666666666666, "b": 0.4}
results = evaluate_ranking(
["a", "a", "b", "b", "c", "d", "d", "d"],
[10, 7, 11, 6, 8, 2, 7, 1],
target_recall=0.6,
reverse_order=False,
disable_interpolation=True,
)
results = evaluate_ranking(
["a", "a", "b", "b", "c", "d", "d", "d"],
[10, 7, 11, 6, 8, 2, 7, 1],
target_recall=0.6,
reverse_order=False,
disable_interpolation=True,
)
self.assertEqual(
results,
{"a": 0.6666666666666666, "b": 0.3333333333333333, "c": 0.2857142857142857},
)
assert results == {
"a": 0.6666666666666666,
"b": 0.3333333333333333,
"c": 0.2857142857142857,
}
def test_mismatching_lengths(self) -> None:
self.assertRaises(
ValueError,
evaluate_ranking,
def test_mismatching_lengths() -> None:
with pytest.raises(ValueError):
evaluate_ranking(
["a", "a", "b", "b", "c"],
[10, 7, 11, 6, 8, 2, 7, 1],
target_recall=0.6,
)
def test_invalid_recalls(self) -> None:
self.assertRaises(
AssertionError,
evaluate_ranking,
def test_invalid_recalls() -> None:
with pytest.raises(AssertionError):
evaluate_ranking(
["a", "a", "b", "b"],
[10, 7, 11, 6],
target_recall=10.6,
)
self.assertRaises(
AssertionError,
evaluate_ranking,
with pytest.raises(AssertionError):
evaluate_ranking(
["a", "a", "b", "b"],
[10, 7, 11, 6],
target_recall=-0.0001,
)
self.assertRaises(
AssertionError,
evaluate_ranking,
with pytest.raises(AssertionError):
evaluate_ranking(
["a", "a", "b", "b"],
[10, 7, 11, 6],
target_recall=1.00001,
)
def test_empty(self) -> None:
evaluate_ranking(
[],
[],
target_recall=0.6,
)
evaluate_ranking(
["a"],
[1],
target_recall=0.6,
)
def test_empty() -> None:
evaluate_ranking(
[],
[],
target_recall=0.6,
)
def test_save(self) -> None:
path = Path("test.svg")
path.unlink(missing_ok=True)
evaluate_ranking(
["a"],
[1],
target_recall=0.6,
)
evaluate_ranking(
["a", "a", "b", "b", "c", "d", "d", "d"],
[10, 7, 11, 6, 8, 2, 7, 1],
target_recall=0.1,
output_svg=path,
)
self.assertTrue(path.exists())
path.unlink()
def test_save() -> None:
path = Path("test.svg")
path.unlink(missing_ok=True)
evaluate_ranking(
["a", "a", "b", "b", "c", "d", "d", "d"],
[10, 7, 11, 6, 8, 2, 7, 1],
target_recall=0.1,
output_svg=path,
)
assert path.exists()
path.unlink()

View file

@ -1,58 +1,59 @@
import unittest
from great_ai.utilities import get_sentences
class TestGetSentences(unittest.TestCase):
def test_default(self) -> None:
text = "This is a complete sentence. So is this. However this is n" # ot.
expected = ["This is a complete sentence.", "So is this.", "However this is n"]
def test_default() -> None:
text = "This is a complete sentence. So is this. However this is n" # ot.
expected = ["This is a complete sentence.", "So is this.", "However this is n"]
assert get_sentences(text) == expected
assert get_sentences(text, ignore_partial=True) == expected[0:2]
def test_complex(self) -> None:
text = """
This is a complete sentence. So is this.
End of paragraph.
assert get_sentences(text) == expected
assert get_sentences(text, ignore_partial=True) == expected[0:2]
Negation contractions (like don't or ain't) are resolved.
def test_complex() -> None:
text = """
This is a complete sentence. So is this.
End of paragraph.
However this is not a sent
"""
expected = [
"This is a complete sentence.",
"So is this.",
"End of paragraph.",
"Negation contractions (like don't or ain't) are resolved.",
"However this is not a sent",
]
Negation contractions (like don't or ain't) are resolved.
print(get_sentences(text, ignore_partial=True))
However this is not a sent
"""
assert get_sentences(text) == expected
assert get_sentences(text, ignore_partial=True) == expected[:-1]
expected = [
"This is a complete sentence.",
"So is this.",
"End of paragraph.",
"Negation contractions (like don't or ain't) are resolved.",
"However this is not a sent",
]
def test_true_casing(self) -> None:
text = "This is also referred to as a Convolutional Neural Network (CNN)."
expected = ["this is also referred to as a Convolutional Neural Network (CNN)."]
print(get_sentences(text, ignore_partial=True))
assert get_sentences(text, true_case=True) == expected
assert get_sentences(text) == expected
assert get_sentences(text, ignore_partial=True) == expected[:-1]
def test_remove_punctuation(self) -> None:
text = "Also, we --- the authors --- have to find less intrusive, and higher potential procedures. "
expected = [
"Also we the authors have to find less intrusive and higher potential procedures"
]
assert get_sentences(text, remove_punctuation=True) == expected
def test_true_casing() -> None:
text = "This is also referred to as a Convolutional Neural Network (CNN)."
expected = ["this is also referred to as a Convolutional Neural Network (CNN)."]
def test_empty(self) -> None:
assert get_sentences("") == []
assert get_sentences(" ") == []
assert get_sentences(" \n ") == []
assert get_sentences("", ignore_partial=True) == []
assert get_sentences("", true_case=True) == []
assert get_sentences("", remove_punctuation=True) == []
assert get_sentences(text, true_case=True) == expected
def test_remove_punctuation() -> None:
text = "Also, we --- the authors --- have to find less intrusive, and higher potential procedures. "
expected = [
"Also we the authors have to find less intrusive and higher potential procedures"
]
assert get_sentences(text, remove_punctuation=True) == expected
def test_empty() -> None:
assert get_sentences("") == []
assert get_sentences(" ") == []
assert get_sentences(" \n ") == []
assert get_sentences("", ignore_partial=True) == []
assert get_sentences("", true_case=True) == []
assert get_sentences("", remove_punctuation=True) == []

View file

@ -1,31 +1,30 @@
import unittest
from great_ai.utilities import english_name_of_language, is_english, predict_language
class TestLanguage(unittest.TestCase):
def test_predict_language(self) -> None:
assert predict_language("This is an English text.") == "en"
assert predict_language("Ez egy magyar szöveg.") == "hu"
assert predict_language("32") == "und"
assert predict_language("") == "und"
def test_predict_language() -> None:
assert predict_language("This is an English text.") == "en"
assert predict_language("Ez egy magyar szöveg.") == "hu"
assert predict_language("32") == "und"
assert predict_language("") == "und"
def test_is_english(self) -> None:
self.assertTrue(is_english("en"))
self.assertTrue(is_english("en-US"))
self.assertFalse(is_english("hu"))
self.assertFalse(is_english("de"))
self.assertFalse(is_english("zh"))
self.assertFalse(is_english("zh-TW"))
self.assertFalse(is_english("und"))
self.assertFalse(is_english(""))
self.assertFalse(is_english(None))
def english_name_of_language(self) -> None:
assert english_name_of_language("en") == "English"
assert english_name_of_language("hu") == "Hungarian"
assert english_name_of_language("zh") == "Chinese"
assert english_name_of_language("zh-TW") == "Chinese"
assert english_name_of_language("und") == "Unknown language"
assert english_name_of_language("") == "Unknown language"
assert english_name_of_language(None) == "Unknown language"
def test_is_english() -> None:
assert is_english("en")
assert is_english("en-US")
assert not is_english("hu")
assert not is_english("de")
assert not is_english("zh")
assert not is_english("zh-TW")
assert not is_english("und")
assert not is_english("")
assert not is_english(None)
def english_name_of_language() -> None:
assert english_name_of_language("en") == "English"
assert english_name_of_language("hu") == "Hungarian"
assert english_name_of_language("zh") == "Chinese"
assert english_name_of_language("zh-TW") == "Chinese"
assert english_name_of_language("und") == "Unknown language"
assert english_name_of_language("") == "Unknown language"
assert english_name_of_language(None) == "Unknown language"

View file

@ -1,5 +1,3 @@
import unittest
import pytest
from great_ai.utilities import WorkerException, parallel_map
@ -7,110 +5,112 @@ from great_ai.utilities import WorkerException, parallel_map
COUNT = int(1e5) + 3
class TestParallelMap(unittest.TestCase):
def test_simple_case_with_progress_bar(self) -> None:
assert list(parallel_map(lambda v: v**2, range(COUNT), concurrency=4)) == [
v**2 for v in range(COUNT)
]
def test_simple_case_with_progress_bar() -> None:
assert list(parallel_map(lambda v: v**2, range(COUNT), concurrency=4)) == [
v**2 for v in range(COUNT)
]
def test_with_iterable(self) -> None:
from time import sleep
def my_generator():
for i in range(10):
yield i
sleep(0.1)
def test_with_iterable() -> None:
from time import sleep
expected = [v**3 for v in range(10)]
def my_generator():
for i in range(10):
yield i
sleep(0.1)
assert (
list(parallel_map(lambda x: x**3, my_generator(), chunk_size=1))
== expected
expected = [v**3 for v in range(10)]
assert (
list(parallel_map(lambda x: x**3, my_generator(), chunk_size=1)) == expected
)
def test_simple_case_without_progress_bar() -> None:
assert list(parallel_map(lambda v: v**2, range(COUNT), concurrency=2)) == [
v**2 for v in range(COUNT)
]
def test_simple_case_invalid_values() -> None:
with pytest.raises(AssertionError):
list(parallel_map(lambda v: v**2, range(COUNT), concurrency=0))
with pytest.raises(AssertionError):
list(parallel_map(lambda v: v**2, range(COUNT), chunk_size=0))
def test_this_process_exception() -> None:
def my_generator():
yield 1
yield 2
yield 3
assert False
with pytest.raises(AssertionError):
list(
parallel_map(lambda v: v**2, my_generator(), concurrency=2, chunk_size=2)
)
def test_simple_case_without_progress_bar(self) -> None:
assert list(parallel_map(lambda v: v**2, range(COUNT), concurrency=2)) == [
v**2 for v in range(COUNT)
]
def test_simple_case_invalid_values(self) -> None:
with pytest.raises(AssertionError):
list(parallel_map(lambda v: v**2, range(COUNT), concurrency=0))
with pytest.raises(AssertionError):
list(parallel_map(lambda v: v**2, range(COUNT), chunk_size=0))
def test_this_process_exception(self) -> None:
def my_generator():
yield 1
yield 2
yield 3
assert False
with pytest.raises(AssertionError):
list(
parallel_map(
lambda v: v**2, my_generator(), concurrency=2, chunk_size=2
)
)
with pytest.raises(AssertionError):
list(
parallel_map(
lambda v: v**2, my_generator(), concurrency=1, chunk_size=2
)
)
def test_ignore_this_process_exception(self) -> None:
def my_generator():
yield 1
yield 2
yield 3
yield 1 / 0
assert list(
parallel_map(
lambda v: v**2,
my_generator(),
concurrency=2,
chunk_size=2,
ignore_exceptions=True,
)
) == [1, 4]
assert list(
parallel_map(
lambda v: v**2,
my_generator(),
concurrency=1,
chunk_size=2,
ignore_exceptions=True,
)
) == [1, 4, 9]
def test_worker_process_exception(self) -> None:
def oh_no(_):
raise ValueError("hi")
with pytest.raises(WorkerException):
list(parallel_map(oh_no, range(COUNT), concurrency=2))
with pytest.raises(WorkerException):
list(parallel_map(oh_no, range(COUNT), concurrency=1))
def test_ignore_worker_process_exception(self) -> None:
def oh_no(_):
raise ValueError("hi")
assert (
list(parallel_map(oh_no, range(3), concurrency=2, ignore_exceptions=True))
== [None] * 3
)
assert (
list(parallel_map(oh_no, range(3), concurrency=1, ignore_exceptions=True))
== [None] * 3
with pytest.raises(AssertionError):
list(
parallel_map(lambda v: v**2, my_generator(), concurrency=1, chunk_size=2)
)
def test_no_op(self) -> None:
assert list(parallel_map(lambda v: v**2, [])) == []
assert list(parallel_map(lambda v: v**2, [], chunk_size=100)) == []
assert list(parallel_map(lambda v: v**2, [], concurrency=100)) == []
def test_ignore_this_process_exception() -> None:
def my_generator():
yield 1
yield 2
yield 3
yield 1 / 0
assert list(
parallel_map(
lambda v: v**2,
my_generator(),
concurrency=2,
chunk_size=2,
ignore_exceptions=True,
)
) == [1, 4]
assert list(
parallel_map(
lambda v: v**2,
my_generator(),
concurrency=1,
chunk_size=2,
ignore_exceptions=True,
)
) == [1, 4, 9]
def test_worker_process_exception() -> None:
def oh_no(_):
raise ValueError("hi")
with pytest.raises(WorkerException):
list(parallel_map(oh_no, range(COUNT), concurrency=2))
with pytest.raises(WorkerException):
list(parallel_map(oh_no, range(COUNT), concurrency=1))
def test_ignore_worker_process_exception() -> None:
def oh_no(_):
raise ValueError("hi")
assert (
list(parallel_map(oh_no, range(3), concurrency=2, ignore_exceptions=True))
== [None] * 3
)
assert (
list(parallel_map(oh_no, range(3), concurrency=1, ignore_exceptions=True))
== [None] * 3
)
def test_no_op() -> None:
assert list(parallel_map(lambda v: v**2, [])) == []
assert list(parallel_map(lambda v: v**2, [], chunk_size=100)) == []
assert list(parallel_map(lambda v: v**2, [], concurrency=100)) == []

View file

@ -1,5 +1,3 @@
import unittest
import pytest
from great_ai.utilities import WorkerException, threaded_parallel_map
@ -7,118 +5,125 @@ from great_ai.utilities import WorkerException, threaded_parallel_map
COUNT = int(1e5) + 3
class TestParallelMap(unittest.TestCase):
def test_simple_case_with_progress_bar(self) -> None:
assert list(
threaded_parallel_map(lambda v: v**2, range(COUNT), concurrency=4)
) == [v**2 for v in range(COUNT)]
def test_simple_case_with_progress_bar() -> None:
assert list(
threaded_parallel_map(lambda v: v**2, range(COUNT), concurrency=4)
) == [v**2 for v in range(COUNT)]
def test_with_iterable(self) -> None:
from time import sleep
def my_generator():
for i in range(10):
yield i
sleep(0.1)
def test_with_iterable() -> None:
from time import sleep
expected = [v**3 for v in range(10)]
def my_generator():
for i in range(10):
yield i
sleep(0.1)
assert (
list(threaded_parallel_map(lambda x: x**3, my_generator(), chunk_size=1))
== expected
)
expected = [v**3 for v in range(10)]
def test_simple_case_without_progress_bar(self) -> None:
assert list(
threaded_parallel_map(lambda v: v**2, range(COUNT), concurrency=2)
) == [v**2 for v in range(COUNT)]
assert (
list(threaded_parallel_map(lambda x: x**3, my_generator(), chunk_size=1))
== expected
)
def test_simple_case_invalid_values(self) -> None:
with pytest.raises(AssertionError):
list(threaded_parallel_map(lambda v: v**2, range(COUNT), concurrency=0))
with pytest.raises(AssertionError):
list(threaded_parallel_map(lambda v: v**2, range(COUNT), chunk_size=0))
def test_simple_case_without_progress_bar() -> None:
assert list(
threaded_parallel_map(lambda v: v**2, range(COUNT), concurrency=2)
) == [v**2 for v in range(COUNT)]
def test_this_worker_exception(self) -> None:
def my_generator():
yield 1
yield 2
yield 3
assert False
with pytest.raises(AssertionError):
list(
threaded_parallel_map(
lambda v: v**2, my_generator(), concurrency=2, chunk_size=2
)
)
def test_simple_case_invalid_values() -> None:
with pytest.raises(AssertionError):
list(threaded_parallel_map(lambda v: v**2, range(COUNT), concurrency=0))
with pytest.raises(AssertionError):
list(
threaded_parallel_map(
lambda v: v**2, my_generator(), concurrency=1, chunk_size=2
)
)
with pytest.raises(AssertionError):
list(threaded_parallel_map(lambda v: v**2, range(COUNT), chunk_size=0))
def test_ignore_this_worker_exception(self) -> None:
def my_generator():
yield 1
yield 2
yield 3
yield 1 / 0
assert list(
def test_this_worker_exception() -> None:
def my_generator():
yield 1
yield 2
yield 3
assert False
with pytest.raises(AssertionError):
list(
threaded_parallel_map(
lambda v: v**2,
my_generator(),
concurrency=2,
chunk_size=2,
ignore_exceptions=True,
lambda v: v**2, my_generator(), concurrency=2, chunk_size=2
)
) == [1, 4]
assert list(
)
with pytest.raises(AssertionError):
list(
threaded_parallel_map(
lambda v: v**2,
my_generator(),
concurrency=1,
chunk_size=2,
ignore_exceptions=True,
lambda v: v**2, my_generator(), concurrency=1, chunk_size=2
)
) == [1, 4, 9]
def test_worker_worker_exception(self) -> None:
def oh_no(_):
raise ValueError("hi")
with pytest.raises(WorkerException):
list(threaded_parallel_map(oh_no, range(COUNT), concurrency=2))
with pytest.raises(WorkerException):
list(threaded_parallel_map(oh_no, range(COUNT), concurrency=1))
def test_ignore_worker_worker_exception(self) -> None:
def oh_no(_):
raise ValueError("hi")
assert (
list(
threaded_parallel_map(
oh_no, range(3), concurrency=2, ignore_exceptions=True
)
)
== [None] * 3
)
assert (
list(
threaded_parallel_map(
oh_no, range(3), concurrency=1, ignore_exceptions=True
)
)
== [None] * 3
)
def test_no_op(self) -> None:
assert list(threaded_parallel_map(lambda v: v**2, [])) == []
assert list(threaded_parallel_map(lambda v: v**2, [], chunk_size=100)) == []
assert list(threaded_parallel_map(lambda v: v**2, [], concurrency=100)) == []
def test_ignore_this_worker_exception() -> None:
def my_generator():
yield 1
yield 2
yield 3
yield 1 / 0
assert list(
threaded_parallel_map(
lambda v: v**2,
my_generator(),
concurrency=2,
chunk_size=2,
ignore_exceptions=True,
)
) == [1, 4]
assert list(
threaded_parallel_map(
lambda v: v**2,
my_generator(),
concurrency=1,
chunk_size=2,
ignore_exceptions=True,
)
) == [1, 4, 9]
def test_worker_worker_exception() -> None:
def oh_no(_):
raise ValueError("hi")
with pytest.raises(WorkerException):
list(threaded_parallel_map(oh_no, range(COUNT), concurrency=2))
with pytest.raises(WorkerException):
list(threaded_parallel_map(oh_no, range(COUNT), concurrency=1))
def test_ignore_worker_worker_exception() -> None:
def oh_no(_):
raise ValueError("hi")
assert (
list(
threaded_parallel_map(
oh_no, range(3), concurrency=2, ignore_exceptions=True
)
)
== [None] * 3
)
assert (
list(
threaded_parallel_map(
oh_no, range(3), concurrency=1, ignore_exceptions=True
)
)
== [None] * 3
)
def test_no_op() -> None:
assert list(threaded_parallel_map(lambda v: v**2, [])) == []
assert list(threaded_parallel_map(lambda v: v**2, [], chunk_size=100)) == []
assert list(threaded_parallel_map(lambda v: v**2, [], concurrency=100)) == []

View file

@ -1,5 +1,3 @@
import unittest
from great_ai.utilities import unique
original = [
@ -12,43 +10,44 @@ original = [
]
class TestUnique(unittest.TestCase):
def test_default(self) -> None:
values = [
*original,
("a", 2),
("a", 1),
("a", -3),
("b", 5),
("c", 5),
("d", 2),
]
def test_default() -> None:
values = [
*original,
("a", 2),
("a", 1),
("a", -3),
("b", 5),
("c", 5),
("d", 2),
]
expected = original
expected = original
assert unique(values) == expected
assert unique(values, key=lambda v: v) == expected
assert unique(values) == expected
assert unique(values, key=lambda v: v) == expected
def test_with_key_0(self) -> None:
values = original
expected = [
("a", 1),
("b", 5),
("c", 5),
("d", 2),
]
def test_with_key_0() -> None:
values = original
assert unique(values, key=lambda v: v[0]) == expected
expected = [
("a", 1),
("b", 5),
("c", 5),
("d", 2),
]
def test_with_key_1(self) -> None:
values = original
assert unique(values, key=lambda v: v[0]) == expected
expected = [
("a", 1),
("b", 5),
("a", -3),
("d", 2),
]
assert unique(values, key=lambda v: v[1]) == expected
def test_with_key_1() -> None:
values = original
expected = [
("a", 1),
("b", 5),
("a", -3),
("d", 2),
]
assert unique(values, key=lambda v: v[1]) == expected