add tests (#44)
* fixed test_window_no_event * added strategy tests * removed unused code * added config tests * added more config tests * refactored tests * updated pytest
This commit is contained in:
parent
b75f0ff057
commit
8a27de8981
|
@ -11,7 +11,6 @@ from mobilizon_bots.config.publishers import publisher_names
|
||||||
def build_settings(
|
def build_settings(
|
||||||
settings_files: List[str] = None, validators: List[Validator] = None
|
settings_files: List[str] = None, validators: List[Validator] = None
|
||||||
):
|
):
|
||||||
|
|
||||||
SETTINGS_FILE = (
|
SETTINGS_FILE = (
|
||||||
settings_files
|
settings_files
|
||||||
or os.environ.get("MOBILIZON_BOTS_SETTINGS_FILE")
|
or os.environ.get("MOBILIZON_BOTS_SETTINGS_FILE")
|
||||||
|
@ -38,29 +37,8 @@ def build_and_validate_settings(settings_files: List[str] = None):
|
||||||
specific for each publisher, notifier and publication strategy.
|
specific for each publisher, notifier and publication strategy.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# we first do a preliminary load of the settings without validation. We will later use them to determine which
|
preliminary_validators = (
|
||||||
# publishers, notifiers and strategy have been selected
|
[Validator("selection.strategy", must_exist=True, is_type_of=str)]
|
||||||
raw_settings = build_settings(settings_files=settings_files)
|
|
||||||
|
|
||||||
# These validators are always applied
|
|
||||||
base_validators = (
|
|
||||||
[
|
|
||||||
# strategy to decide events to publish
|
|
||||||
Validator("selection.strategy", must_exist=True, is_type_of=str),
|
|
||||||
Validator(
|
|
||||||
"publishing.window.begin",
|
|
||||||
must_exist=True,
|
|
||||||
is_type_of=int,
|
|
||||||
gte=0,
|
|
||||||
lte=24,
|
|
||||||
),
|
|
||||||
Validator(
|
|
||||||
"publishing.window.end", must_exist=True, is_type_of=int, gte=0, lte=24
|
|
||||||
),
|
|
||||||
# url of the main Mobilizon instance to download events from
|
|
||||||
Validator("source.mobilizon.url", must_exist=True, is_type_of=str),
|
|
||||||
Validator("source.mobilizon.group", must_exist=True, is_type_of=str),
|
|
||||||
]
|
|
||||||
+ [
|
+ [
|
||||||
Validator(
|
Validator(
|
||||||
f"publisher.{publisher_name}.active", must_exist=True, is_type_of=bool
|
f"publisher.{publisher_name}.active", must_exist=True, is_type_of=bool
|
||||||
|
@ -75,6 +53,26 @@ def build_and_validate_settings(settings_files: List[str] = None):
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# we first do a preliminary load of the settings without validation. We will later use them to determine which
|
||||||
|
# publishers, notifiers and strategy have been selected
|
||||||
|
raw_settings = build_settings(
|
||||||
|
settings_files=settings_files, validators=preliminary_validators
|
||||||
|
)
|
||||||
|
|
||||||
|
# These validators are always applied
|
||||||
|
base_validators = [
|
||||||
|
# strategy to decide events to publish
|
||||||
|
Validator(
|
||||||
|
"publishing.window.begin", must_exist=True, is_type_of=int, gte=0, lte=24,
|
||||||
|
),
|
||||||
|
Validator(
|
||||||
|
"publishing.window.end", must_exist=True, is_type_of=int, gte=0, lte=24
|
||||||
|
),
|
||||||
|
# url of the main Mobilizon instance to download events from
|
||||||
|
Validator("source.mobilizon.url", must_exist=True, is_type_of=str),
|
||||||
|
Validator("source.mobilizon.group", must_exist=True, is_type_of=str),
|
||||||
|
] + preliminary_validators
|
||||||
|
|
||||||
# we retrieve validators that are conditional. Each module will analyze the settings and decide which validators
|
# we retrieve validators that are conditional. Each module will analyze the settings and decide which validators
|
||||||
# need to be applied.
|
# need to be applied.
|
||||||
strategy_validators = strategies.get_validators(raw_settings)
|
strategy_validators = strategies.get_validators(raw_settings)
|
||||||
|
@ -107,11 +105,11 @@ class CustomConfig:
|
||||||
if cls._instance is None:
|
if cls._instance is None:
|
||||||
print("Creating the object")
|
print("Creating the object")
|
||||||
cls._instance = super(CustomConfig, cls).__new__(cls)
|
cls._instance = super(CustomConfig, cls).__new__(cls)
|
||||||
cls.settings = build_settings(settings_files)
|
cls.settings = build_and_validate_settings(settings_files)
|
||||||
return cls._instance
|
return cls._instance
|
||||||
|
|
||||||
def update(self, settings_files: List[str] = None):
|
def update(self, settings_files: List[str] = None):
|
||||||
self.settings = build_settings(settings_files)
|
self.settings = build_and_validate_settings(settings_files)
|
||||||
|
|
||||||
|
|
||||||
def get_settings():
|
def get_settings():
|
||||||
|
|
|
@ -89,23 +89,6 @@ class SelectNextEventStrategy(EventSelectionStrategy):
|
||||||
return first_unpublished_event
|
return first_unpublished_event
|
||||||
|
|
||||||
|
|
||||||
class EventSelector:
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
published_events: List[MobilizonEvent],
|
|
||||||
unpublished_events: List[MobilizonEvent],
|
|
||||||
):
|
|
||||||
self.published_events = published_events.sort(key=lambda x: x.begin_datetime)
|
|
||||||
self.unpublished_events = unpublished_events.sort(
|
|
||||||
key=lambda x: x.begin_datetime
|
|
||||||
)
|
|
||||||
|
|
||||||
def select_event_to_publish(
|
|
||||||
self, strategy: EventSelectionStrategy
|
|
||||||
) -> Optional[MobilizonEvent]:
|
|
||||||
return strategy._select(self.published_events, self.unpublished_events)
|
|
||||||
|
|
||||||
|
|
||||||
STRATEGY_NAME_TO_STRATEGY_CLASS = {"next_event": SelectNextEventStrategy}
|
STRATEGY_NAME_TO_STRATEGY_CLASS = {"next_event": SelectNextEventStrategy}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -163,9 +163,5 @@ class AbstractPublisher(AbstractNotifier):
|
||||||
"""
|
"""
|
||||||
Retrieves publisher's message template.
|
Retrieves publisher's message template.
|
||||||
"""
|
"""
|
||||||
template_path = (
|
template_path = self.conf.msg_template_path or self.default_template_path
|
||||||
self.conf.msg_template_path
|
|
||||||
if hasattr(self.conf, "msg_template_path")
|
|
||||||
else self.default_template_path
|
|
||||||
)
|
|
||||||
return JINJA_ENV.get_template(template_path)
|
return JINJA_ENV.get_template(template_path)
|
||||||
|
|
|
@ -32,7 +32,7 @@ python-versions = ">=3.5"
|
||||||
name = "atomicwrites"
|
name = "atomicwrites"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
description = "Atomic file writes."
|
description = "Atomic file writes."
|
||||||
category = "dev"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||||
name = "attrs"
|
name = "attrs"
|
||||||
version = "21.2.0"
|
version = "21.2.0"
|
||||||
description = "Classes Without Boilerplate"
|
description = "Classes Without Boilerplate"
|
||||||
category = "dev"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||||
|
|
||||||
|
@ -110,6 +110,14 @@ category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "iniconfig"
|
||||||
|
version = "1.1.1"
|
||||||
|
description = "iniconfig: brain-dead simple config-ini parsing"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iso8601"
|
name = "iso8601"
|
||||||
version = "0.1.14"
|
version = "0.1.14"
|
||||||
|
@ -140,19 +148,11 @@ category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.6"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "more-itertools"
|
|
||||||
version = "8.8.0"
|
|
||||||
description = "More routines for operating on iterables, beyond itertools"
|
|
||||||
category = "dev"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.5"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "packaging"
|
name = "packaging"
|
||||||
version = "21.0"
|
version = "21.0"
|
||||||
description = "Core utilities for Python packages"
|
description = "Core utilities for Python packages"
|
||||||
category = "dev"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.6"
|
||||||
|
|
||||||
|
@ -163,7 +163,7 @@ pyparsing = ">=2.0.2"
|
||||||
name = "pluggy"
|
name = "pluggy"
|
||||||
version = "0.13.1"
|
version = "0.13.1"
|
||||||
description = "plugin and hook calling mechanisms for python"
|
description = "plugin and hook calling mechanisms for python"
|
||||||
category = "dev"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||||
|
|
||||||
|
@ -174,7 +174,7 @@ dev = ["pre-commit", "tox"]
|
||||||
name = "py"
|
name = "py"
|
||||||
version = "1.10.0"
|
version = "1.10.0"
|
||||||
description = "library with cross-python path, ini-parsing, io, code, log facilities"
|
description = "library with cross-python path, ini-parsing, io, code, log facilities"
|
||||||
category = "dev"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||||
|
|
||||||
|
@ -182,7 +182,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||||
name = "pyparsing"
|
name = "pyparsing"
|
||||||
version = "2.4.7"
|
version = "2.4.7"
|
||||||
description = "Python parsing module"
|
description = "Python parsing module"
|
||||||
category = "dev"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
|
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
|
||||||
|
|
||||||
|
@ -196,39 +196,38 @@ python-versions = ">=3.7,<4.0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pytest"
|
name = "pytest"
|
||||||
version = "5.4.3"
|
version = "6.2.4"
|
||||||
description = "pytest: simple powerful testing with Python"
|
description = "pytest: simple powerful testing with Python"
|
||||||
category = "dev"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.5"
|
python-versions = ">=3.6"
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""}
|
atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""}
|
||||||
attrs = ">=17.4.0"
|
attrs = ">=19.2.0"
|
||||||
colorama = {version = "*", markers = "sys_platform == \"win32\""}
|
colorama = {version = "*", markers = "sys_platform == \"win32\""}
|
||||||
more-itertools = ">=4.0.0"
|
iniconfig = "*"
|
||||||
packaging = "*"
|
packaging = "*"
|
||||||
pluggy = ">=0.12,<1.0"
|
pluggy = ">=0.12,<1.0.0a1"
|
||||||
py = ">=1.5.0"
|
py = ">=1.8.2"
|
||||||
wcwidth = "*"
|
toml = "*"
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
checkqa-mypy = ["mypy (==v0.761)"]
|
|
||||||
testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"]
|
testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pytest-asyncio"
|
name = "pytest-asyncio"
|
||||||
version = "0.10.0"
|
version = "0.15.1"
|
||||||
description = "Pytest support for asyncio."
|
description = "Pytest support for asyncio."
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">= 3.5"
|
python-versions = ">= 3.6"
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
pytest = ">=3.0.6"
|
pytest = ">=5.4.0"
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
testing = ["async-generator (>=1.3)", "coverage", "hypothesis (>=3.64)"]
|
testing = ["coverage", "hypothesis (>=5.7.1)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "python-dateutil"
|
name = "python-dateutil"
|
||||||
|
@ -291,6 +290,14 @@ category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
|
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml"
|
||||||
|
version = "0.10.2"
|
||||||
|
description = "Python Library for Tom's Obvious, Minimal Language"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tortoise-orm"
|
name = "tortoise-orm"
|
||||||
version = "0.17.4"
|
version = "0.17.4"
|
||||||
|
@ -333,18 +340,10 @@ brotli = ["brotlipy (>=0.6.0)"]
|
||||||
secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"]
|
secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"]
|
||||||
socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
|
socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wcwidth"
|
|
||||||
version = "0.2.5"
|
|
||||||
description = "Measures the displayed width of unicode strings in a terminal"
|
|
||||||
category = "dev"
|
|
||||||
optional = false
|
|
||||||
python-versions = "*"
|
|
||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "1.1"
|
lock-version = "1.1"
|
||||||
python-versions = "^3.9"
|
python-versions = "^3.9"
|
||||||
content-hash = "0879accc273f3fc21de4ca7a01682392ed44f1173b17b1e09e884a5b2c7ad51d"
|
content-hash = "8b2e404c14110b5a47d3ec0480b838c4811ce1ebfbe68170bd60a3d414dbb7c8"
|
||||||
|
|
||||||
[metadata.files]
|
[metadata.files]
|
||||||
aiosqlite = [
|
aiosqlite = [
|
||||||
|
@ -391,6 +390,10 @@ idna = [
|
||||||
{file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"},
|
{file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"},
|
||||||
{file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"},
|
{file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"},
|
||||||
]
|
]
|
||||||
|
iniconfig = [
|
||||||
|
{file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
|
||||||
|
{file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
|
||||||
|
]
|
||||||
iso8601 = [
|
iso8601 = [
|
||||||
{file = "iso8601-0.1.14-py2.py3-none-any.whl", hash = "sha256:e7e1122f064d626e17d47cd5106bed2c620cb38fe464999e0ddae2b6d2de6004"},
|
{file = "iso8601-0.1.14-py2.py3-none-any.whl", hash = "sha256:e7e1122f064d626e17d47cd5106bed2c620cb38fe464999e0ddae2b6d2de6004"},
|
||||||
{file = "iso8601-0.1.14.tar.gz", hash = "sha256:8aafd56fa0290496c5edbb13c311f78fa3a241f0853540da09d9363eae3ebd79"},
|
{file = "iso8601-0.1.14.tar.gz", hash = "sha256:8aafd56fa0290496c5edbb13c311f78fa3a241f0853540da09d9363eae3ebd79"},
|
||||||
|
@ -435,10 +438,6 @@ markupsafe = [
|
||||||
{file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"},
|
{file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"},
|
||||||
{file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"},
|
{file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"},
|
||||||
]
|
]
|
||||||
more-itertools = [
|
|
||||||
{file = "more-itertools-8.8.0.tar.gz", hash = "sha256:83f0308e05477c68f56ea3a888172c78ed5d5b3c282addb67508e7ba6c8f813a"},
|
|
||||||
{file = "more_itertools-8.8.0-py3-none-any.whl", hash = "sha256:2cf89ec599962f2ddc4d568a05defc40e0a587fbc10d5989713638864c36be4d"},
|
|
||||||
]
|
|
||||||
packaging = [
|
packaging = [
|
||||||
{file = "packaging-21.0-py3-none-any.whl", hash = "sha256:c86254f9220d55e31cc94d69bade760f0847da8000def4dfe1c6b872fd14ff14"},
|
{file = "packaging-21.0-py3-none-any.whl", hash = "sha256:c86254f9220d55e31cc94d69bade760f0847da8000def4dfe1c6b872fd14ff14"},
|
||||||
{file = "packaging-21.0.tar.gz", hash = "sha256:7dc96269f53a4ccec5c0670940a4281106dd0bb343f47b7471f779df49c2fbe7"},
|
{file = "packaging-21.0.tar.gz", hash = "sha256:7dc96269f53a4ccec5c0670940a4281106dd0bb343f47b7471f779df49c2fbe7"},
|
||||||
|
@ -460,12 +459,12 @@ pypika-tortoise = [
|
||||||
{file = "pypika_tortoise-0.1.1-py3-none-any.whl", hash = "sha256:860020094e01058ea80602c90d4a843d0a42cffefcf4f3cb1a7f2c18b880c638"},
|
{file = "pypika_tortoise-0.1.1-py3-none-any.whl", hash = "sha256:860020094e01058ea80602c90d4a843d0a42cffefcf4f3cb1a7f2c18b880c638"},
|
||||||
]
|
]
|
||||||
pytest = [
|
pytest = [
|
||||||
{file = "pytest-5.4.3-py3-none-any.whl", hash = "sha256:5c0db86b698e8f170ba4582a492248919255fcd4c79b1ee64ace34301fb589a1"},
|
{file = "pytest-6.2.4-py3-none-any.whl", hash = "sha256:91ef2131a9bd6be8f76f1f08eac5c5317221d6ad1e143ae03894b862e8976890"},
|
||||||
{file = "pytest-5.4.3.tar.gz", hash = "sha256:7979331bfcba207414f5e1263b5a0f8f521d0f457318836a7355531ed1a4c7d8"},
|
{file = "pytest-6.2.4.tar.gz", hash = "sha256:50bcad0a0b9c5a72c8e4e7c9855a3ad496ca6a881a3641b4260605450772c54b"},
|
||||||
]
|
]
|
||||||
pytest-asyncio = [
|
pytest-asyncio = [
|
||||||
{file = "pytest-asyncio-0.10.0.tar.gz", hash = "sha256:9fac5100fd716cbecf6ef89233e8590a4ad61d729d1732e0a96b84182df1daaf"},
|
{file = "pytest-asyncio-0.15.1.tar.gz", hash = "sha256:2564ceb9612bbd560d19ca4b41347b54e7835c2f792c504f698e05395ed63f6f"},
|
||||||
{file = "pytest_asyncio-0.10.0-py3-none-any.whl", hash = "sha256:d734718e25cfc32d2bf78d346e99d33724deeba774cc4afdf491530c6184b63b"},
|
{file = "pytest_asyncio-0.15.1-py3-none-any.whl", hash = "sha256:3042bcdf1c5d978f6b74d96a151c4cfb9dcece65006198389ccd7e6c60eb1eea"},
|
||||||
]
|
]
|
||||||
python-dateutil = [
|
python-dateutil = [
|
||||||
{file = "python-dateutil-2.8.1.tar.gz", hash = "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c"},
|
{file = "python-dateutil-2.8.1.tar.gz", hash = "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c"},
|
||||||
|
@ -487,6 +486,10 @@ six = [
|
||||||
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
|
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
|
||||||
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
|
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
|
||||||
]
|
]
|
||||||
|
toml = [
|
||||||
|
{file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
|
||||||
|
{file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
|
||||||
|
]
|
||||||
tortoise-orm = [
|
tortoise-orm = [
|
||||||
{file = "tortoise-orm-0.17.4.tar.gz", hash = "sha256:8314a9ae63d3f009bac5da3e7d1f7e3f2de8f9bad43ce1efcd3e059209cd3f9d"},
|
{file = "tortoise-orm-0.17.4.tar.gz", hash = "sha256:8314a9ae63d3f009bac5da3e7d1f7e3f2de8f9bad43ce1efcd3e059209cd3f9d"},
|
||||||
{file = "tortoise_orm-0.17.4-py3-none-any.whl", hash = "sha256:f052b6089e30748afec88669f1a1cf01a3662cdac81cf5427dfb338839ad6027"},
|
{file = "tortoise_orm-0.17.4-py3-none-any.whl", hash = "sha256:f052b6089e30748afec88669f1a1cf01a3662cdac81cf5427dfb338839ad6027"},
|
||||||
|
@ -500,7 +503,3 @@ urllib3 = [
|
||||||
{file = "urllib3-1.26.6-py2.py3-none-any.whl", hash = "sha256:39fb8672126159acb139a7718dd10806104dec1e2f0f6c88aab05d17df10c8d4"},
|
{file = "urllib3-1.26.6-py2.py3-none-any.whl", hash = "sha256:39fb8672126159acb139a7718dd10806104dec1e2f0f6c88aab05d17df10c8d4"},
|
||||||
{file = "urllib3-1.26.6.tar.gz", hash = "sha256:f57b4c16c62fa2760b7e3d97c35b255512fb6b59a259730f36ba32ce9f8e342f"},
|
{file = "urllib3-1.26.6.tar.gz", hash = "sha256:f57b4c16c62fa2760b7e3d97c35b255512fb6b59a259730f36ba32ce9f8e342f"},
|
||||||
]
|
]
|
||||||
wcwidth = [
|
|
||||||
{file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"},
|
|
||||||
{file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"},
|
|
||||||
]
|
|
||||||
|
|
|
@ -13,12 +13,12 @@ Jinja2 = "^2.11.3"
|
||||||
requests = "^2.25.1"
|
requests = "^2.25.1"
|
||||||
arrow = "^1.1.0"
|
arrow = "^1.1.0"
|
||||||
click = "^8.0.1"
|
click = "^8.0.1"
|
||||||
|
pytest = "^6.2.4"
|
||||||
|
|
||||||
[tool.poetry.dev-dependencies]
|
[tool.poetry.dev-dependencies]
|
||||||
asynctest = "^0.13"
|
|
||||||
pytest = "^5.3"
|
|
||||||
responses = "^0.13.3"
|
responses = "^0.13.3"
|
||||||
pytest-asyncio = "^0.10"
|
pytest-asyncio = "^0.15.1"
|
||||||
|
asynctest = "^0.13.0"
|
||||||
|
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = ["poetry-core>=1.0.0"]
|
requires = ["poetry-core>=1.0.0"]
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
from mobilizon_bots.config.config import get_settings, update_settings_files
|
||||||
|
|
||||||
|
|
||||||
|
def test_singleton():
|
||||||
|
config_1 = get_settings()
|
||||||
|
config_2 = get_settings()
|
||||||
|
assert id(config_1) == id(config_2)
|
||||||
|
|
||||||
|
|
||||||
|
def test_singleton_update():
|
||||||
|
config_1 = get_settings()
|
||||||
|
config_2 = update_settings_files([])
|
||||||
|
config_3 = get_settings()
|
||||||
|
assert id(config_1) != id(config_2)
|
||||||
|
assert id(config_2) == id(config_3)
|
|
@ -0,0 +1,40 @@
|
||||||
|
import dynaconf
|
||||||
|
import pkg_resources
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from mobilizon_bots.config.config import update_settings_files
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def invalid_settings_file(tmp_path, toml_content):
|
||||||
|
file = tmp_path / "tmp.toml"
|
||||||
|
file.write_text(toml_content)
|
||||||
|
return file
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("toml_content", ["invalid toml["])
|
||||||
|
def test_update_failure_invalid_toml(invalid_settings_file):
|
||||||
|
with pytest.raises(dynaconf.vendor.toml.decoder.TomlDecodeError):
|
||||||
|
update_settings_files([invalid_settings_file.absolute()])
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("toml_content", [""])
|
||||||
|
def test_update_failure_invalid_preliminary_config(invalid_settings_file):
|
||||||
|
with pytest.raises(dynaconf.validator.ValidationError):
|
||||||
|
update_settings_files([invalid_settings_file.absolute()])
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"invalid_toml,pattern_in_exception",
|
||||||
|
[
|
||||||
|
["config_with_strategy.toml", "publisher.*.active"],
|
||||||
|
["config_with_preliminary.toml", "publishing.window.begin"],
|
||||||
|
["config_with_invalid_telegram.toml", "token"],
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_update_failure_config_without_publishers(invalid_toml, pattern_in_exception):
|
||||||
|
with pytest.raises(dynaconf.validator.ValidationError) as e:
|
||||||
|
update_settings_files(
|
||||||
|
[pkg_resources.resource_filename("tests.resources.config", invalid_toml)]
|
||||||
|
)
|
||||||
|
assert e.match(pattern_in_exception)
|
|
@ -34,7 +34,8 @@ def mock_publication_window(publication_window):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_window_no_event():
|
@pytest.mark.parametrize("current_hour", [15])
|
||||||
|
def test_window_no_event(mock_arrow_now):
|
||||||
selected_event = SelectNextEventStrategy().select([], [])
|
selected_event = SelectNextEventStrategy().select([], [])
|
||||||
assert selected_event is None
|
assert selected_event is None
|
||||||
|
|
||||||
|
@ -105,6 +106,55 @@ def test_window_simple_event_found(
|
||||||
assert selected_event is unpublished_events[0]
|
assert selected_event is unpublished_events[0]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("current_hour", [15])
|
||||||
|
@pytest.mark.parametrize("strategy_name", ["next_event"])
|
||||||
|
def test_window_simple_no_published_events(
|
||||||
|
event_generator, set_strategy, mock_arrow_now,
|
||||||
|
):
|
||||||
|
"Testing that if no event is published, the function takes the first available unpublished event"
|
||||||
|
unpublished_events = [
|
||||||
|
event_generator(
|
||||||
|
published=False,
|
||||||
|
begin_date=arrow.Arrow(year=2021, month=1, day=5, hour=11, minute=30),
|
||||||
|
),
|
||||||
|
event_generator(
|
||||||
|
published=False,
|
||||||
|
begin_date=arrow.Arrow(year=2021, month=1, day=5, hour=11, minute=50),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
selected_event = select_event_to_publish([], unpublished_events)
|
||||||
|
assert selected_event is unpublished_events[0]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("current_hour", [15])
|
||||||
|
@pytest.mark.parametrize("strategy_name", ["next_event"])
|
||||||
|
def test_window_simple_event_too_recent(
|
||||||
|
event_generator, set_strategy, mock_arrow_now,
|
||||||
|
):
|
||||||
|
"Testing that if an event has been published too recently, no event is selected for publication"
|
||||||
|
unpublished_events = [
|
||||||
|
event_generator(
|
||||||
|
published=False,
|
||||||
|
begin_date=arrow.Arrow(year=2021, month=1, day=5, hour=11, minute=30),
|
||||||
|
),
|
||||||
|
event_generator(
|
||||||
|
published=False,
|
||||||
|
begin_date=arrow.Arrow(year=2021, month=1, day=5, hour=11, minute=50),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
published_events = [
|
||||||
|
event_generator(
|
||||||
|
published=True,
|
||||||
|
publication_time={"telegram": arrow.now().shift(minutes=-5)},
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
selected_event = select_event_to_publish(published_events, unpublished_events)
|
||||||
|
assert selected_event is None
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("current_hour", [15])
|
@pytest.mark.parametrize("current_hour", [15])
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"desired_break_window_days,days_passed_from_publication", [[1, 2], [2, 10], [4, 4]]
|
"desired_break_window_days,days_passed_from_publication", [[1, 2], [2, 10], [4, 4]]
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
|
||||||
|
[default.selection]
|
||||||
|
strategy = "next_event"
|
||||||
|
|
||||||
|
|
||||||
|
[default.source.mobilizon]
|
||||||
|
url="https://mobilizon.it/api"
|
||||||
|
group="tech_workers_coalition_italia"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[default.publishing.window]
|
||||||
|
begin=12
|
||||||
|
end=24
|
||||||
|
|
||||||
|
[default.selection.strategy_options]
|
||||||
|
break_between_events_in_minutes =1
|
||||||
|
|
||||||
|
|
||||||
|
[default.publisher.telegram]
|
||||||
|
active=true
|
||||||
|
chat_id="xxx"
|
||||||
|
token="xxx"
|
||||||
|
username="xxx"
|
||||||
|
|
||||||
|
[default.publisher.facebook]
|
||||||
|
active=false
|
||||||
|
[default.publisher.zulip]
|
||||||
|
active=false
|
||||||
|
[default.publisher.twitter]
|
||||||
|
active=false
|
||||||
|
[default.publisher.mastodon]
|
||||||
|
active=false
|
||||||
|
|
||||||
|
|
||||||
|
[default.notifier.telegram]
|
||||||
|
active=true
|
||||||
|
chat_id="xxx"
|
||||||
|
misspelled_token="xxx"
|
||||||
|
username="xxx"
|
||||||
|
[default.notifier.zulip]
|
||||||
|
active=false
|
||||||
|
[default.notifier.twitter]
|
||||||
|
active=false
|
||||||
|
[default.notifier.mastodon]
|
||||||
|
active=false
|
|
@ -0,0 +1,27 @@
|
||||||
|
|
||||||
|
[default.selection]
|
||||||
|
strategy = "next_event"
|
||||||
|
|
||||||
|
|
||||||
|
[default.publisher.telegram]
|
||||||
|
active=true
|
||||||
|
|
||||||
|
|
||||||
|
[default.publisher.facebook]
|
||||||
|
active=false
|
||||||
|
[default.publisher.zulip]
|
||||||
|
active=false
|
||||||
|
[default.publisher.twitter]
|
||||||
|
active=false
|
||||||
|
[default.publisher.mastodon]
|
||||||
|
active=false
|
||||||
|
|
||||||
|
|
||||||
|
[default.notifier.telegram]
|
||||||
|
active=true
|
||||||
|
[default.notifier.zulip]
|
||||||
|
active=false
|
||||||
|
[default.notifier.twitter]
|
||||||
|
active=false
|
||||||
|
[default.notifier.mastodon]
|
||||||
|
active=false
|
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
[default.selection]
|
||||||
|
strategy = "next_event"
|
Loading…
Reference in New Issue