diff --git a/channels-lock.scm b/channels-lock.scm index 520f730..2558af2 100644 --- a/channels-lock.scm +++ b/channels-lock.scm @@ -1,11 +1,12 @@ -(use-modules (guix channels)) +(define-module (channels-lock) + #:use-module (guix channels)) (list (channel (name 'guix) (url "https://git.savannah.gnu.org/git/guix.git") (commit - "72abf9b9b82d2f5f34b7d22b7aae6f2398336a93") + "61c8d0fe3dd5415de5617a5251d7ff14dd17a545") (introduction (make-channel-introduction "afb9f2752315f131e4ddd44eba02eed403365085" diff --git a/guix.scm b/guix.scm index 75b5293..e78c5c0 100644 --- a/guix.scm +++ b/guix.scm @@ -1,3 +1,4 @@ -(use-modules (docker mobilizon-reshare)) +(define-module (guix) + #:use-module (docker mobilizon-reshare)) mobilizon-reshare.git diff --git a/manifest.scm b/manifest.scm index 5349477..65b50ad 100644 --- a/manifest.scm +++ b/manifest.scm @@ -7,28 +7,11 @@ #:use-module (guix profiles) #:use-module (srfi srfi-1)) -(define channels - ;; This is the old revision from which we want to - ;; extract docker-compose. - (list (channel - (name 'guix) - (url "https://git.savannah.gnu.org/git/guix.git") - (commit - "07f55a361e23152b48f34425f116a725cce39e48")))) - -(define inferior - ;; An inferior representing the above revision. - (inferior-for-channels channels)) - -;; Now create a manifest with the current packages -;; and the old "docker-compose" package. (packages->manifest (append - ;; docker-compose fails to build on current master, hence this hack. - (list (first (lookup-inferior-packages inferior "docker-compose"))) (map cadr (package-direct-inputs mobilizon-reshare.git)) (map specification->package+output '("git-cal" "man-db" "texinfo" "python-pre-commit" "cloc" "ripgrep" "python-semver" - "fd")))) + "fd" "docker-compose")))) diff --git a/mobilizon_reshare/cli/cli.py b/mobilizon_reshare/cli/cli.py index d49c078..1337ff2 100644 --- a/mobilizon_reshare/cli/cli.py +++ b/mobilizon_reshare/cli/cli.py @@ -11,7 +11,7 @@ from mobilizon_reshare.cli.commands.recap.main import recap_command as recap_mai from mobilizon_reshare.cli.commands.start.main import start_command as start_main from mobilizon_reshare.cli.commands.pull.main import pull_command as pull_main from mobilizon_reshare.cli.commands.publish.main import publish_command as publish_main -from mobilizon_reshare.config.config import current_version +from mobilizon_reshare.config.config import current_version, get_settings from mobilizon_reshare.config.publishers import publisher_names from mobilizon_reshare.event.event import EventPublicationStatus from mobilizon_reshare.cli.commands.retry.main import ( @@ -19,6 +19,31 @@ from mobilizon_reshare.cli.commands.retry.main import ( retry_publication_command, ) from mobilizon_reshare.models.publication import PublicationStatus +from mobilizon_reshare.publishers import get_active_publishers + + +def test_settings(ctx, param, value): + if not value or ctx.resilient_parsing: + return + get_settings() + click.echo("OK!") + ctx.exit() + + +def print_version(ctx, param, value): + if not value or ctx.resilient_parsing: + return + click.echo(current_version()) + ctx.exit() + + +def print_platforms(ctx, param, value): + if not value or ctx.resilient_parsing: + return + for platform in get_active_publishers(): + click.echo(platform) + ctx.exit() + status_name_to_enum = { "event": { @@ -46,32 +71,70 @@ to_date_option = click.option( "--end", type=click.DateTime(), expose_value=True, - help="Include only events that begin before this datetime.", + help="Include only events that end before this datetime.", ) -event_status_option = click.argument( +event_status_argument = click.argument( "status", type=click.Choice(list(status_name_to_enum["event"].keys())), default="all", expose_value=True, ) -publication_status_option = click.argument( +publication_status_argument = click.argument( "status", type=click.Choice(list(status_name_to_enum["publication"].keys())), default="all", expose_value=True, ) - - -def print_version(ctx, param, value): - if not value or ctx.resilient_parsing: - return - click.echo(current_version()) - ctx.exit() +event_uuid_option = click.option( + "-E", + "--event", + type=click.UUID, + expose_value=True, + help="Publish the given event.", +) +publication_uuid_option = click.option( + "-P", + "--publication", + type=click.UUID, + expose_value=True, + help="Publish the given publication.", +) +platform_name_option = click.option( + "-p", + "--platform", + type=str, + expose_value=True, + help="Publish to the given platform. This makes sense only for events.", +) +list_supported_option = click.option( + "--list-platforms", + is_flag=True, + callback=print_platforms, + expose_value=False, + is_eager=True, + help="Show all active platforms.", +) +test_configuration = click.option( + "-t", + "--test-configuration", + is_flag=True, + callback=test_settings, + expose_value=False, + is_eager=True, + help="Validate the current configuration.", +) @click.group() +@test_configuration +@list_supported_option @click.option( - "--version", is_flag=True, callback=print_version, expose_value=False, is_eager=True + "--version", + is_flag=True, + callback=print_version, + expose_value=False, + is_eager=True, + help="Show the current version.", ) @pass_context def mobilizon_reshare(obj): @@ -99,7 +162,8 @@ def recap(): @mobilizon_reshare.command( - help="Fetch the latest events from Mobilizon and store them." + help="Fetch the latest events from Mobilizon, store them if they are unknown, " + "update them if they are known and changed." ) def pull(): safe_execution( @@ -107,7 +171,13 @@ def pull(): ) -@mobilizon_reshare.command(help="Select an event and publish it.") +@mobilizon_reshare.command( + help="Select an event with the current configured strategy" + " and publish it to all active platforms." +) +@event_uuid_option +@publication_uuid_option +@platform_name_option def publish(): safe_execution( publish_main, @@ -125,7 +195,7 @@ def publication(): @event.command(help="Query for events in the database.", name="list") -@event_status_option +@event_status_argument @from_date_option @to_date_option def event_list(status, begin, end): @@ -141,7 +211,7 @@ def event_list(status, begin, end): @publication.command(help="Query for publications in the database.", name="list") -@publication_status_option +@publication_status_argument @from_date_option @to_date_option def publication_list(status, begin, end): diff --git a/mobilizon_reshare/cli/commands/publish/main.py b/mobilizon_reshare/cli/commands/publish/main.py index 6e1be91..27ad294 100644 --- a/mobilizon_reshare/cli/commands/publish/main.py +++ b/mobilizon_reshare/cli/commands/publish/main.py @@ -1,10 +1,14 @@ -from mobilizon_reshare.main.publish import publish +import logging + +from mobilizon_reshare.main.publish import select_and_publish + +logger = logging.getLogger(__name__) async def publish_command(): """ - STUB - :return: + Select an event with the current configured strategy + and publish it to all active platforms. """ - reports = await publish() - return 0 if reports and reports.successful else 1 + report = await select_and_publish() + return 0 if report and report.successful else 1 diff --git a/mobilizon_reshare/event/event_selection_strategies.py b/mobilizon_reshare/event/event_selection_strategies.py index 9ad32c8..c50bdaa 100644 --- a/mobilizon_reshare/event/event_selection_strategies.py +++ b/mobilizon_reshare/event/event_selection_strategies.py @@ -93,7 +93,7 @@ def select_unpublished_events( def select_event_to_publish( published_events: List[MobilizonEvent], unpublished_events: List[MobilizonEvent], -): +) -> Optional[MobilizonEvent]: strategy = STRATEGY_NAME_TO_STRATEGY_CLASS[ get_settings()["selection"]["strategy"] diff --git a/mobilizon_reshare/main/publish.py b/mobilizon_reshare/main/publish.py index 1461ab2..59d5c2a 100644 --- a/mobilizon_reshare/main/publish.py +++ b/mobilizon_reshare/main/publish.py @@ -3,6 +3,8 @@ from typing import Optional from mobilizon_reshare.event.event import MobilizonEvent from mobilizon_reshare.event.event_selection_strategies import select_event_to_publish +from mobilizon_reshare.publishers import get_active_publishers +from mobilizon_reshare.publishers.abstract import EventPublication from mobilizon_reshare.publishers.coordinator import ( PublicationFailureNotifiersCoordinator, PublisherCoordinatorReport, @@ -18,33 +20,49 @@ from mobilizon_reshare.storage.query.write import save_publication_report logger = logging.getLogger(__name__) -async def publish( - events: Optional[list[MobilizonEvent]] = None, +async def publish_publications( + publications: list[EventPublication], +) -> PublisherCoordinatorReport: + report = PublisherCoordinator(publications).run() + + await save_publication_report(report) + for publication_report in report.reports: + if not publication_report.succesful: + PublicationFailureNotifiersCoordinator( + publication_report, + ).notify_failure() + + return report + + +async def publish_event( + event: MobilizonEvent, publishers: Optional[list[Optional[str]]] = None +) -> PublisherCoordinatorReport: + logger.info(f"Event to publish found: {event.name}") + + if not (publishers and all(publishers)): + publishers = get_active_publishers() + + publications = await build_publications(event, publishers) + return await publish_publications(publications) + + +async def select_and_publish( + unpublished_events: Optional[list[MobilizonEvent]] = None, ) -> Optional[PublisherCoordinatorReport]: """ STUB :return: """ - if events is None: - events = await events_without_publications() + if unpublished_events is None: + unpublished_events = await events_without_publications() event = select_event_to_publish( list(await get_published_events()), - events, + unpublished_events, ) if event: - logger.info(f"Event to publish found: {event.name}") - - publications = await build_publications(event) - reports = PublisherCoordinator(publications).run() - - await save_publication_report(reports) - for report in reports.reports: - if not report.succesful: - PublicationFailureNotifiersCoordinator( - report, - ).notify_failure() - return reports + return await publish_event(event) else: logger.info("No event to publish found") diff --git a/mobilizon_reshare/main/retry.py b/mobilizon_reshare/main/retry.py index 5b98b99..4fb90a2 100644 --- a/mobilizon_reshare/main/retry.py +++ b/mobilizon_reshare/main/retry.py @@ -2,22 +2,20 @@ import logging from typing import Optional from uuid import UUID +from mobilizon_reshare.main.publish import publish_publications from mobilizon_reshare.publishers.coordinator import ( - PublisherCoordinator, PublisherCoordinatorReport, - PublicationFailureLoggerCoordinator, ) from mobilizon_reshare.storage.query.exceptions import EventNotFound from mobilizon_reshare.storage.query.read import ( get_failed_publications_for_event, get_publication, ) -from mobilizon_reshare.storage.query.write import save_publication_report logger = logging.getLogger(__name__) -async def retry_event_publications(event_id): +async def retry_event_publications(event_id) -> Optional[PublisherCoordinatorReport]: failed_publications = await get_failed_publications_for_event(event_id) if not failed_publications: @@ -25,24 +23,17 @@ async def retry_event_publications(event_id): return logger.info(f"Found {len(failed_publications)} publications.") - return PublisherCoordinator(failed_publications).run() + return await publish_publications(failed_publications) async def retry_publication(publication_id) -> Optional[PublisherCoordinatorReport]: - # TODO test this function publication = await get_publication(publication_id) if not publication: logger.info(f"Publication {publication_id} not found.") return logger.info(f"Publication {publication_id} found.") - reports = PublisherCoordinator([publication]).run() - - await save_publication_report(reports) - - for report in reports.reports: - if not report.succesful: - PublicationFailureLoggerCoordinator(report,).notify_failure() + return await publish_publications([publication]) async def retry_event( @@ -53,15 +44,8 @@ async def retry_event( "Autonomous retry not implemented yet, please specify an event_id" ) try: - reports = await retry_event_publications(mobilizon_event_id) + return await retry_event_publications(mobilizon_event_id) except EventNotFound as e: logger.debug(e, exc_info=True) logger.error(f"Event with id {mobilizon_event_id} not found") return - - if not reports: - return - await save_publication_report(reports) - for report in reports.reports: - if not report.succesful: - PublicationFailureLoggerCoordinator(report,).notify_failure() diff --git a/mobilizon_reshare/main/start.py b/mobilizon_reshare/main/start.py index c2f3515..29ada96 100644 --- a/mobilizon_reshare/main/start.py +++ b/mobilizon_reshare/main/start.py @@ -1,7 +1,7 @@ import logging.config from typing import Optional -from mobilizon_reshare.main.publish import publish +from mobilizon_reshare.main.publish import select_and_publish from mobilizon_reshare.main.pull import pull from mobilizon_reshare.publishers.coordinator import PublisherCoordinatorReport @@ -14,4 +14,4 @@ async def start() -> Optional[PublisherCoordinatorReport]: :return: """ events = await pull() - return await publish(events) + return await select_and_publish(events) diff --git a/mobilizon_reshare/publishers/coordinator.py b/mobilizon_reshare/publishers/coordinator.py index 6239631..baa53ab 100644 --- a/mobilizon_reshare/publishers/coordinator.py +++ b/mobilizon_reshare/publishers/coordinator.py @@ -156,7 +156,7 @@ class Sender: class AbstractNotifiersCoordinator(ABC): - def __init__(self, report, notifiers: List[AbstractPlatform] = None): + def __init__(self, report: EventPublicationReport, notifiers: List[AbstractPlatform] = None): self.platforms = notifiers or [ get_notifier_class(notifier)() for notifier in get_active_notifiers() ] diff --git a/mobilizon_reshare/storage/query/read.py b/mobilizon_reshare/storage/query/read.py index 723cac7..ecd9474 100644 --- a/mobilizon_reshare/storage/query/read.py +++ b/mobilizon_reshare/storage/query/read.py @@ -1,4 +1,3 @@ -import dataclasses from functools import partial from typing import Iterable, Optional from uuid import UUID @@ -12,7 +11,6 @@ from mobilizon_reshare.event.event import MobilizonEvent, EventPublicationStatus from mobilizon_reshare.models.event import Event from mobilizon_reshare.models.publication import Publication, PublicationStatus from mobilizon_reshare.models.publisher import Publisher -from mobilizon_reshare.publishers import get_active_publishers from mobilizon_reshare.publishers.abstract import EventPublication from mobilizon_reshare.storage.query import CONNECTION_NAME from mobilizon_reshare.storage.query.converter import ( @@ -68,7 +66,7 @@ async def events_with_status( async def get_all_publications( from_date: Optional[Arrow] = None, to_date: Optional[Arrow] = None, -) -> Iterable[EventPublication]: +) -> Iterable[Publication]: return await prefetch_publication_relations( _add_date_window(Publication.all(), "timestamp", from_date, to_date) ) @@ -86,6 +84,10 @@ async def get_all_events( ] +async def get_all_publishers() -> list[Publisher]: + return await Publisher.all() + + async def prefetch_event_relations(queryset: QuerySet[Event]) -> list[Event]: return ( await queryset.prefetch_related("publications__publisher") @@ -152,6 +154,10 @@ async def get_event(event_mobilizon_id: UUID) -> Event: return events[0] +async def get_mobilizon_event(event_mobilizon_id: UUID) -> MobilizonEvent: + return event_from_model(await get_event(event_mobilizon_id)) + + async def get_publisher_by_name(name) -> Publisher: return await Publisher.filter(name=name).first() @@ -165,13 +171,15 @@ async def is_known(event: MobilizonEvent) -> bool: @atomic(CONNECTION_NAME) -async def build_publications(event: MobilizonEvent) -> list[EventPublication]: +async def build_publications( + event: MobilizonEvent, publishers: list[str] +) -> list[EventPublication]: event_model = await get_event(event.mobilizon_id) models = [ await event_model.build_publication_by_publisher_name(name) - for name in get_active_publishers() + for name in publishers ] - return [publication_from_orm(m, dataclasses.replace(event)) for m in models] + return [publication_from_orm(m, event) for m in models] @atomic(CONNECTION_NAME) @@ -194,7 +202,7 @@ async def get_failed_publications_for_event( @atomic(CONNECTION_NAME) -async def get_publication(publication_id): +async def get_publication(publication_id: UUID): try: publication = await prefetch_publication_relations( Publication.get(id=publication_id).first() diff --git a/poetry.lock b/poetry.lock index 732651a..503ca54 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,6 +1,6 @@ [[package]] name = "aerich" -version = "0.6.2" +version = "0.6.3" description = "A database migrations tool for Tortoise ORM." category = "main" optional = false @@ -8,8 +8,8 @@ python-versions = ">=3.7,<4.0" [package.dependencies] click = "*" -ddlparse = "*" dictdiffer = "*" +pydantic = "*" tomlkit = "*" tortoise-orm = "*" @@ -87,11 +87,11 @@ tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (> [[package]] name = "babel" -version = "2.9.1" +version = "2.10.1" description = "Internationalization utilities" category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=3.6" [package.dependencies] pytz = ">=2015.7" @@ -151,7 +151,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [[package]] name = "coverage" -version = "6.3.2" +version = "6.3.3" description = "Code coverage measurement for Python" category = "dev" optional = false @@ -168,17 +168,6 @@ category = "dev" optional = false python-versions = ">=3.6" -[[package]] -name = "ddlparse" -version = "1.10.0" -description = "DDL parase and Convert to BigQuery JSON schema" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -pyparsing = "*" - [[package]] name = "dictdiffer" version = "0.9.0" @@ -203,7 +192,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [[package]] name = "dynaconf" -version = "3.1.7" +version = "3.1.8" description = "The dynamic configurator for your Python Project" category = "main" optional = false @@ -214,6 +203,7 @@ all = ["redis", "ruamel.yaml", "configobj", "hvac"] configobj = ["configobj"] ini = ["configobj"] redis = ["redis"] +test = ["pytest", "pytest-cov", "pytest-xdist", "pytest-mock", "flake8", "pep8-naming", "flake8-debugger", "flake8-print", "flake8-todo", "radon", "flask (>=0.12)", "django", "python-dotenv", "toml", "codecov", "redis", "hvac", "configobj"] toml = ["toml"] vault = ["hvac"] yaml = ["ruamel.yaml"] @@ -279,11 +269,11 @@ python-versions = "*" [[package]] name = "jinja2" -version = "3.0.3" +version = "3.1.2" description = "A very fast and expressive template engine." category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.dependencies] MarkupSafe = ">=2.0" @@ -380,28 +370,43 @@ category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +[[package]] +name = "pydantic" +version = "1.9.0" +description = "Data validation and settings management using python 3.6 type hinting" +category = "main" +optional = false +python-versions = ">=3.6.1" + +[package.dependencies] +typing-extensions = ">=3.7.4.3" + +[package.extras] +dotenv = ["python-dotenv (>=0.10.4)"] +email = ["email-validator (>=1.0.3)"] + [[package]] name = "pygments" -version = "2.11.2" +version = "2.12.0" description = "Pygments is a syntax highlighting package written in Python." category = "dev" optional = false -python-versions = ">=3.5" +python-versions = ">=3.6" [[package]] name = "pyparsing" -version = "3.0.7" -description = "Python parsing module" -category = "main" +version = "3.0.9" +description = "pyparsing module - Classes and methods to define and execute parsing grammars" +category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.6.8" [package.extras] -diagrams = ["jinja2", "railroad-diagrams"] +diagrams = ["railroad-diagrams", "jinja2"] [[package]] name = "pypika-tortoise" -version = "0.1.3" +version = "0.1.4" description = "Forked from pypika and streamline just for tortoise-orm" category = "main" optional = false @@ -481,7 +486,7 @@ six = ">=1.5" [[package]] name = "python-slugify" -version = "6.1.1" +version = "6.1.2" description = "A Python slugify application that also handles Unicode" category = "dev" optional = false @@ -569,7 +574,7 @@ python-versions = "*" [[package]] name = "soupsieve" -version = "2.3.1" +version = "2.3.2.post1" description = "A modern CSS selector implementation for Beautiful Soup." category = "main" optional = false @@ -609,7 +614,7 @@ test = ["pytest", "pytest-cov", "html5lib", "cython", "typed-ast"] [[package]] name = "sphinx-autodoc-typehints" -version = "1.17.0" +version = "1.17.1" description = "Type hints (PEP 484) support for the Sphinx autodoc extension" category = "dev" optional = false @@ -619,7 +624,7 @@ python-versions = ">=3.7" Sphinx = ">=4" [package.extras] -testing = ["covdefaults (>=2)", "coverage (>=6)", "diff-cover (>=6.4)", "nptyping (>=1)", "pytest (>=6)", "pytest-cov (>=3)", "sphobjinv (>=2)", "typing-extensions (>=3.5)"] +testing = ["covdefaults (>=2)", "coverage (>=6)", "diff-cover (>=6.4)", "nptyping (>=1,<2)", "pytest (>=6)", "pytest-cov (>=3)", "sphobjinv (>=2)", "typing-extensions (>=3.5)"] type_comments = ["typed-ast (>=1.4.0)"] [[package]] @@ -741,7 +746,7 @@ python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" [[package]] name = "tomlkit" -version = "0.10.0" +version = "0.10.2" description = "Style preserving TOML library" category = "main" optional = false @@ -787,11 +792,11 @@ test = ["vcrpy (>=1.10.3)"] [[package]] name = "typing-extensions" -version = "4.1.1" -description = "Backported and Experimental Type Hints for Python 3.6+" +version = "4.2.0" +description = "Backported and Experimental Type Hints for Python 3.7+" category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [[package]] name = "unidecode" @@ -816,25 +821,25 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [[package]] name = "zipp" -version = "3.7.0" +version = "3.8.0" description = "Backport of pathlib-compatible object wrapper for zip files" category = "dev" optional = false python-versions = ">=3.7" [package.extras] -docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] -testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"] +docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)"] [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "19e6c973a5b0b994d22429a27794f96f8c616e13cc8249a9110b20d9e14eec8c" +content-hash = "93588989100f72f9ee6e064af3ea66d2ae23e57c62acb0a92d414377f57490b9" [metadata.files] aerich = [ - {file = "aerich-0.6.2-py3-none-any.whl", hash = "sha256:4e150c5549e75e0df1ba38b7e7bff0f92e2ef2b2937782ccc7dc90ea4c3f1f0f"}, - {file = "aerich-0.6.2.tar.gz", hash = "sha256:784b91f977925b0303a6225db1af3a37c038ac383f6633da926d3bd013c79de4"}, + {file = "aerich-0.6.3-py3-none-any.whl", hash = "sha256:d45f98214ed54b8ec9be949df264c5b0b9e8b79d8f8ba9e68714675bc81a5574"}, + {file = "aerich-0.6.3.tar.gz", hash = "sha256:96ac087922048470687264125cb9dfeaade982219c78e6a9b91a0fb67eaa1cd1"}, ] aiosqlite = [ {file = "aiosqlite-0.17.0-py3-none-any.whl", hash = "sha256:6c49dc6d3405929b1d08eeccc72306d3677503cc5e5e43771efc1e00232e8231"}, @@ -865,8 +870,8 @@ attrs = [ {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"}, ] babel = [ - {file = "Babel-2.9.1-py2.py3-none-any.whl", hash = "sha256:ab49e12b91d937cd11f0b67cb259a57ab4ad2b59ac7a3b41d6c06c0ac5b0def9"}, - {file = "Babel-2.9.1.tar.gz", hash = "sha256:bc0c176f9f6a994582230df350aa6e05ba2ebe4b3ac317eab29d9be5d2768da0"}, + {file = "Babel-2.10.1-py3-none-any.whl", hash = "sha256:3f349e85ad3154559ac4930c3918247d319f21910d5ce4b25d439ed8693b98d2"}, + {file = "Babel-2.10.1.tar.gz", hash = "sha256:98aeaca086133efb3e1e2aad0396987490c8425929ddbcfe0550184fdc54cd13"}, ] beautifulsoup4 = [ {file = "beautifulsoup4-4.10.0-py3-none-any.whl", hash = "sha256:9a315ce70049920ea4572a4055bc4bd700c940521d36fc858205ad4fcde149bf"}, @@ -889,57 +894,53 @@ colorama = [ {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, ] coverage = [ - {file = "coverage-6.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9b27d894748475fa858f9597c0ee1d4829f44683f3813633aaf94b19cb5453cf"}, - {file = "coverage-6.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:37d1141ad6b2466a7b53a22e08fe76994c2d35a5b6b469590424a9953155afac"}, - {file = "coverage-6.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9987b0354b06d4df0f4d3e0ec1ae76d7ce7cbca9a2f98c25041eb79eec766f1"}, - {file = "coverage-6.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:26e2deacd414fc2f97dd9f7676ee3eaecd299ca751412d89f40bc01557a6b1b4"}, - {file = "coverage-6.3.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4dd8bafa458b5c7d061540f1ee9f18025a68e2d8471b3e858a9dad47c8d41903"}, - {file = "coverage-6.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:46191097ebc381fbf89bdce207a6c107ac4ec0890d8d20f3360345ff5976155c"}, - {file = "coverage-6.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6f89d05e028d274ce4fa1a86887b071ae1755082ef94a6740238cd7a8178804f"}, - {file = "coverage-6.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:58303469e9a272b4abdb9e302a780072c0633cdcc0165db7eec0f9e32f901e05"}, - {file = "coverage-6.3.2-cp310-cp310-win32.whl", hash = "sha256:2fea046bfb455510e05be95e879f0e768d45c10c11509e20e06d8fcaa31d9e39"}, - {file = "coverage-6.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:a2a8b8bcc399edb4347a5ca8b9b87e7524c0967b335fbb08a83c8421489ddee1"}, - {file = "coverage-6.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:f1555ea6d6da108e1999b2463ea1003fe03f29213e459145e70edbaf3e004aaa"}, - {file = "coverage-6.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5f4e1edcf57ce94e5475fe09e5afa3e3145081318e5fd1a43a6b4539a97e518"}, - {file = "coverage-6.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7a15dc0a14008f1da3d1ebd44bdda3e357dbabdf5a0b5034d38fcde0b5c234b7"}, - {file = "coverage-6.3.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21b7745788866028adeb1e0eca3bf1101109e2dc58456cb49d2d9b99a8c516e6"}, - {file = "coverage-6.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:8ce257cac556cb03be4a248d92ed36904a59a4a5ff55a994e92214cde15c5bad"}, - {file = "coverage-6.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b0be84e5a6209858a1d3e8d1806c46214e867ce1b0fd32e4ea03f4bd8b2e3359"}, - {file = "coverage-6.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:acf53bc2cf7282ab9b8ba346746afe703474004d9e566ad164c91a7a59f188a4"}, - {file = "coverage-6.3.2-cp37-cp37m-win32.whl", hash = "sha256:8bdde1177f2311ee552f47ae6e5aa7750c0e3291ca6b75f71f7ffe1f1dab3dca"}, - {file = "coverage-6.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:b31651d018b23ec463e95cf10070d0b2c548aa950a03d0b559eaa11c7e5a6fa3"}, - {file = "coverage-6.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:07e6db90cd9686c767dcc593dff16c8c09f9814f5e9c51034066cad3373b914d"}, - {file = "coverage-6.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2c6dbb42f3ad25760010c45191e9757e7dce981cbfb90e42feef301d71540059"}, - {file = "coverage-6.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c76aeef1b95aff3905fb2ae2d96e319caca5b76fa41d3470b19d4e4a3a313512"}, - {file = "coverage-6.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8cf5cfcb1521dc3255d845d9dca3ff204b3229401994ef8d1984b32746bb45ca"}, - {file = "coverage-6.3.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8fbbdc8d55990eac1b0919ca69eb5a988a802b854488c34b8f37f3e2025fa90d"}, - {file = "coverage-6.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ec6bc7fe73a938933d4178c9b23c4e0568e43e220aef9472c4f6044bfc6dd0f0"}, - {file = "coverage-6.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:9baff2a45ae1f17c8078452e9e5962e518eab705e50a0aa8083733ea7d45f3a6"}, - {file = "coverage-6.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fd9e830e9d8d89b20ab1e5af09b32d33e1a08ef4c4e14411e559556fd788e6b2"}, - {file = "coverage-6.3.2-cp38-cp38-win32.whl", hash = "sha256:f7331dbf301b7289013175087636bbaf5b2405e57259dd2c42fdcc9fcc47325e"}, - {file = "coverage-6.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:68353fe7cdf91f109fc7d474461b46e7f1f14e533e911a2a2cbb8b0fc8613cf1"}, - {file = "coverage-6.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b78e5afb39941572209f71866aa0b206c12f0109835aa0d601e41552f9b3e620"}, - {file = "coverage-6.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4e21876082ed887baed0146fe222f861b5815455ada3b33b890f4105d806128d"}, - {file = "coverage-6.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34626a7eee2a3da12af0507780bb51eb52dca0e1751fd1471d0810539cefb536"}, - {file = "coverage-6.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1ebf730d2381158ecf3dfd4453fbca0613e16eaa547b4170e2450c9707665ce7"}, - {file = "coverage-6.3.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd6fe30bd519694b356cbfcaca9bd5c1737cddd20778c6a581ae20dc8c04def2"}, - {file = "coverage-6.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:96f8a1cb43ca1422f36492bebe63312d396491a9165ed3b9231e778d43a7fca4"}, - {file = "coverage-6.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:dd035edafefee4d573140a76fdc785dc38829fe5a455c4bb12bac8c20cfc3d69"}, - {file = "coverage-6.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5ca5aeb4344b30d0bec47481536b8ba1181d50dbe783b0e4ad03c95dc1296684"}, - {file = "coverage-6.3.2-cp39-cp39-win32.whl", hash = "sha256:f5fa5803f47e095d7ad8443d28b01d48c0359484fec1b9d8606d0e3282084bc4"}, - {file = "coverage-6.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:9548f10d8be799551eb3a9c74bbf2b4934ddb330e08a73320123c07f95cc2d92"}, - {file = "coverage-6.3.2-pp36.pp37.pp38-none-any.whl", hash = "sha256:18d520c6860515a771708937d2f78f63cc47ab3b80cb78e86573b0a760161faf"}, - {file = "coverage-6.3.2.tar.gz", hash = "sha256:03e2a7826086b91ef345ff18742ee9fc47a6839ccd517061ef8fa1976e652ce9"}, + {file = "coverage-6.3.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df32ee0f4935a101e4b9a5f07b617d884a531ed5666671ff6ac66d2e8e8246d8"}, + {file = "coverage-6.3.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:75b5dbffc334e0beb4f6c503fb95e6d422770fd2d1b40a64898ea26d6c02742d"}, + {file = "coverage-6.3.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:114944e6061b68a801c5da5427b9173a0dd9d32cd5fcc18a13de90352843737d"}, + {file = "coverage-6.3.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2ab88a01cd180b5640ccc9c47232e31924d5f9967ab7edd7e5c91c68eee47a69"}, + {file = "coverage-6.3.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad8f9068f5972a46d50fe5f32c09d6ee11da69c560fcb1b4c3baea246ca4109b"}, + {file = "coverage-6.3.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4cd696aa712e6cd16898d63cf66139dc70d998f8121ab558f0e1936396dbc579"}, + {file = "coverage-6.3.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c1a9942e282cc9d3ed522cd3e3cab081149b27ea3bda72d6f61f84eaf88c1a63"}, + {file = "coverage-6.3.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c06455121a089252b5943ea682187a4e0a5cf0a3fb980eb8e7ce394b144430a9"}, + {file = "coverage-6.3.3-cp310-cp310-win32.whl", hash = "sha256:cb5311d6ccbd22578c80028c5e292a7ab9adb91bd62c1982087fad75abe2e63d"}, + {file = "coverage-6.3.3-cp310-cp310-win_amd64.whl", hash = "sha256:6d4a6f30f611e657495cc81a07ff7aa8cd949144e7667c5d3e680d73ba7a70e4"}, + {file = "coverage-6.3.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:79bf405432428e989cad7b8bc60581963238f7645ae8a404f5dce90236cc0293"}, + {file = "coverage-6.3.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:338c417613f15596af9eb7a39353b60abec9d8ce1080aedba5ecee6a5d85f8d3"}, + {file = "coverage-6.3.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:db094a6a4ae6329ed322a8973f83630b12715654c197dd392410400a5bfa1a73"}, + {file = "coverage-6.3.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1414e8b124611bf4df8d77215bd32cba6e3425da8ce9c1f1046149615e3a9a31"}, + {file = "coverage-6.3.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:93b16b08f94c92cab88073ffd185070cdcb29f1b98df8b28e6649145b7f2c90d"}, + {file = "coverage-6.3.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:fbc86ae8cc129c801e7baaafe3addf3c8d49c9c1597c44bdf2d78139707c3c62"}, + {file = "coverage-6.3.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:b5ba058610e8289a07db2a57bce45a1793ec0d3d11db28c047aae2aa1a832572"}, + {file = "coverage-6.3.3-cp37-cp37m-win32.whl", hash = "sha256:8329635c0781927a2c6ae068461e19674c564e05b86736ab8eb29c420ee7dc20"}, + {file = "coverage-6.3.3-cp37-cp37m-win_amd64.whl", hash = "sha256:e5af1feee71099ae2e3b086ec04f57f9950e1be9ecf6c420696fea7977b84738"}, + {file = "coverage-6.3.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e814a4a5a1d95223b08cdb0f4f57029e8eab22ffdbae2f97107aeef28554517e"}, + {file = "coverage-6.3.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:61f4fbf3633cb0713437291b8848634ea97f89c7e849c2be17a665611e433f53"}, + {file = "coverage-6.3.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3401b0d2ed9f726fadbfa35102e00d1b3547b73772a1de5508ef3bdbcb36afe7"}, + {file = "coverage-6.3.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8586b177b4407f988731eb7f41967415b2197f35e2a6ee1a9b9b561f6323c8e9"}, + {file = "coverage-6.3.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:892e7fe32191960da559a14536768a62e83e87bbb867e1b9c643e7e0fbce2579"}, + {file = "coverage-6.3.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:afb03f981fadb5aed1ac6e3dd34f0488e1a0875623d557b6fad09b97a942b38a"}, + {file = "coverage-6.3.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:cbe91bc84be4e5ef0b1480d15c7b18e29c73bdfa33e07d3725da7d18e1b0aff2"}, + {file = "coverage-6.3.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:91502bf27cbd5c83c95cfea291ef387469f2387508645602e1ca0fd8a4ba7548"}, + {file = "coverage-6.3.3-cp38-cp38-win32.whl", hash = "sha256:c488db059848702aff30aa1d90ef87928d4e72e4f00717343800546fdbff0a94"}, + {file = "coverage-6.3.3-cp38-cp38-win_amd64.whl", hash = "sha256:ceb6534fcdfb5c503affb6b1130db7b5bfc8a0f77fa34880146f7a5c117987d0"}, + {file = "coverage-6.3.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cc692c9ee18f0dd3214843779ba6b275ee4bb9b9a5745ba64265bce911aefd1a"}, + {file = "coverage-6.3.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:462105283de203df8de58a68c1bb4ba2a8a164097c2379f664fa81d6baf94b81"}, + {file = "coverage-6.3.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc972d829ad5ef4d4c5fcabd2bbe2add84ce8236f64ba1c0c72185da3a273130"}, + {file = "coverage-6.3.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:06f54765cdbce99901871d50fe9f41d58213f18e98b170a30ca34f47de7dd5e8"}, + {file = "coverage-6.3.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7835f76a081787f0ca62a53504361b3869840a1620049b56d803a8cb3a9eeea3"}, + {file = "coverage-6.3.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:6f5fee77ec3384b934797f1873758f796dfb4f167e1296dc00f8b2e023ce6ee9"}, + {file = "coverage-6.3.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:baa8be8aba3dd1e976e68677be68a960a633a6d44c325757aefaa4d66175050f"}, + {file = "coverage-6.3.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4d06380e777dd6b35ee936f333d55b53dc4a8271036ff884c909cf6e94be8b6c"}, + {file = "coverage-6.3.3-cp39-cp39-win32.whl", hash = "sha256:f8cabc5fd0091976ab7b020f5708335033e422de25e20ddf9416bdce2b7e07d8"}, + {file = "coverage-6.3.3-cp39-cp39-win_amd64.whl", hash = "sha256:9c9441d57b0963cf8340268ad62fc83de61f1613034b79c2b1053046af0c5284"}, + {file = "coverage-6.3.3-pp36.pp37.pp38-none-any.whl", hash = "sha256:d522f1dc49127eab0bfbba4e90fa068ecff0899bbf61bf4065c790ddd6c177fe"}, + {file = "coverage-6.3.3.tar.gz", hash = "sha256:2781c43bffbbec2b8867376d4d61916f5e9c4cc168232528562a61d1b4b01879"}, ] css-html-js-minify = [ {file = "css-html-js-minify-2.5.5.zip", hash = "sha256:4a9f11f7e0496f5284d12111f3ba4ff5ff2023d12f15d195c9c48bd97013746c"}, {file = "css_html_js_minify-2.5.5-py2.py3-none-any.whl", hash = "sha256:3da9d35ac0db8ca648c1b543e0e801d7ca0bab9e6bfd8418fee59d5ae001727a"}, {file = "css_html_js_minify-2.5.5-py3.6.egg", hash = "sha256:4704e04a0cd6dd56d61bbfa3bfffc630da6b2284be33519be0b456672e2a2438"}, ] -ddlparse = [ - {file = "ddlparse-1.10.0-py3-none-any.whl", hash = "sha256:71761b3457c8720853af3aeef266e2da1b6edef50936969492d586d7046a2ac2"}, - {file = "ddlparse-1.10.0.tar.gz", hash = "sha256:6418681baa848eb01251ab79eb3d0ad7e140e6ab1deaae5a019353ddb3a908da"}, -] dictdiffer = [ {file = "dictdiffer-0.9.0-py2.py3-none-any.whl", hash = "sha256:442bfc693cfcadaf46674575d2eba1c53b42f5e404218ca2c2ff549f2df56595"}, {file = "dictdiffer-0.9.0.tar.gz", hash = "sha256:17bacf5fbfe613ccf1b6d512bd766e6b21fb798822a133aa86098b8ac9997578"}, @@ -949,8 +950,8 @@ docutils = [ {file = "docutils-0.17.1.tar.gz", hash = "sha256:686577d2e4c32380bb50cbb22f575ed742d58168cee37e99117a854bcd88f125"}, ] dynaconf = [ - {file = "dynaconf-3.1.7-py2.py3-none-any.whl", hash = "sha256:f52fe5db7622da56a552275e8f64e4df46e3b4ae11158831b042e8ba2f6d1c96"}, - {file = "dynaconf-3.1.7.tar.gz", hash = "sha256:e9d80b46ba4d9372f2f40c812594c963f74178140c0b596e57f2881001fc4d35"}, + {file = "dynaconf-3.1.8-py2.py3-none-any.whl", hash = "sha256:dea41800cf4eef488f49d3b5d1ff6305b85c3c21538f4dcfc39ab34d29606d28"}, + {file = "dynaconf-3.1.8.tar.gz", hash = "sha256:d141a6664fca3648d2d8e84440966af9f58c4f4201ca78353a3f595a67c19ab4"}, ] facebook-sdk = [ {file = "facebook-sdk-3.1.0.tar.gz", hash = "sha256:cabcd2e69ea3d9f042919c99b353df7aa1e2be86d040121f6e9f5e63c1cf0f8d"}, @@ -977,8 +978,8 @@ iso8601 = [ {file = "iso8601-0.1.16.tar.gz", hash = "sha256:36532f77cc800594e8f16641edae7f1baf7932f05d8e508545b95fc53c6dc85b"}, ] jinja2 = [ - {file = "Jinja2-3.0.3-py3-none-any.whl", hash = "sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8"}, - {file = "Jinja2-3.0.3.tar.gz", hash = "sha256:611bb273cd68f3b993fabdc4064fc858c5b47a973cb5aa7999ec1ba405c87cd7"}, + {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"}, + {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"}, ] lxml = [ {file = "lxml-4.8.0-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:e1ab2fac607842ac36864e358c42feb0960ae62c34aa4caaf12ada0a1fb5d99b"}, @@ -1109,17 +1110,54 @@ py = [ {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, ] +pydantic = [ + {file = "pydantic-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cb23bcc093697cdea2708baae4f9ba0e972960a835af22560f6ae4e7e47d33f5"}, + {file = "pydantic-1.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1d5278bd9f0eee04a44c712982343103bba63507480bfd2fc2790fa70cd64cf4"}, + {file = "pydantic-1.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab624700dc145aa809e6f3ec93fb8e7d0f99d9023b713f6a953637429b437d37"}, + {file = "pydantic-1.9.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c8d7da6f1c1049eefb718d43d99ad73100c958a5367d30b9321b092771e96c25"}, + {file = "pydantic-1.9.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:3c3b035103bd4e2e4a28da9da7ef2fa47b00ee4a9cf4f1a735214c1bcd05e0f6"}, + {file = "pydantic-1.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3011b975c973819883842c5ab925a4e4298dffccf7782c55ec3580ed17dc464c"}, + {file = "pydantic-1.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:086254884d10d3ba16da0588604ffdc5aab3f7f09557b998373e885c690dd398"}, + {file = "pydantic-1.9.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:0fe476769acaa7fcddd17cadd172b156b53546ec3614a4d880e5d29ea5fbce65"}, + {file = "pydantic-1.9.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8e9dcf1ac499679aceedac7e7ca6d8641f0193c591a2d090282aaf8e9445a46"}, + {file = "pydantic-1.9.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d1e4c28f30e767fd07f2ddc6f74f41f034d1dd6bc526cd59e63a82fe8bb9ef4c"}, + {file = "pydantic-1.9.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:c86229333cabaaa8c51cf971496f10318c4734cf7b641f08af0a6fbf17ca3054"}, + {file = "pydantic-1.9.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:c0727bda6e38144d464daec31dff936a82917f431d9c39c39c60a26567eae3ed"}, + {file = "pydantic-1.9.0-cp36-cp36m-win_amd64.whl", hash = "sha256:dee5ef83a76ac31ab0c78c10bd7d5437bfdb6358c95b91f1ba7ff7b76f9996a1"}, + {file = "pydantic-1.9.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d9c9bdb3af48e242838f9f6e6127de9be7063aad17b32215ccc36a09c5cf1070"}, + {file = "pydantic-1.9.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ee7e3209db1e468341ef41fe263eb655f67f5c5a76c924044314e139a1103a2"}, + {file = "pydantic-1.9.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0b6037175234850ffd094ca77bf60fb54b08b5b22bc85865331dd3bda7a02fa1"}, + {file = "pydantic-1.9.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b2571db88c636d862b35090ccf92bf24004393f85c8870a37f42d9f23d13e032"}, + {file = "pydantic-1.9.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8b5ac0f1c83d31b324e57a273da59197c83d1bb18171e512908fe5dc7278a1d6"}, + {file = "pydantic-1.9.0-cp37-cp37m-win_amd64.whl", hash = "sha256:bbbc94d0c94dd80b3340fc4f04fd4d701f4b038ebad72c39693c794fd3bc2d9d"}, + {file = "pydantic-1.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e0896200b6a40197405af18828da49f067c2fa1f821491bc8f5bde241ef3f7d7"}, + {file = "pydantic-1.9.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7bdfdadb5994b44bd5579cfa7c9b0e1b0e540c952d56f627eb227851cda9db77"}, + {file = "pydantic-1.9.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:574936363cd4b9eed8acdd6b80d0143162f2eb654d96cb3a8ee91d3e64bf4cf9"}, + {file = "pydantic-1.9.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c556695b699f648c58373b542534308922c46a1cda06ea47bc9ca45ef5b39ae6"}, + {file = "pydantic-1.9.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:f947352c3434e8b937e3aa8f96f47bdfe6d92779e44bb3f41e4c213ba6a32145"}, + {file = "pydantic-1.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5e48ef4a8b8c066c4a31409d91d7ca372a774d0212da2787c0d32f8045b1e034"}, + {file = "pydantic-1.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:96f240bce182ca7fe045c76bcebfa0b0534a1bf402ed05914a6f1dadff91877f"}, + {file = "pydantic-1.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:815ddebb2792efd4bba5488bc8fde09c29e8ca3227d27cf1c6990fc830fd292b"}, + {file = "pydantic-1.9.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6c5b77947b9e85a54848343928b597b4f74fc364b70926b3c4441ff52620640c"}, + {file = "pydantic-1.9.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c68c3bc88dbda2a6805e9a142ce84782d3930f8fdd9655430d8576315ad97ce"}, + {file = "pydantic-1.9.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5a79330f8571faf71bf93667d3ee054609816f10a259a109a0738dac983b23c3"}, + {file = "pydantic-1.9.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f5a64b64ddf4c99fe201ac2724daada8595ada0d102ab96d019c1555c2d6441d"}, + {file = "pydantic-1.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a733965f1a2b4090a5238d40d983dcd78f3ecea221c7af1497b845a9709c1721"}, + {file = "pydantic-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:2cc6a4cb8a118ffec2ca5fcb47afbacb4f16d0ab8b7350ddea5e8ef7bcc53a16"}, + {file = "pydantic-1.9.0-py3-none-any.whl", hash = "sha256:085ca1de245782e9b46cefcf99deecc67d418737a1fd3f6a4f511344b613a5b3"}, + {file = "pydantic-1.9.0.tar.gz", hash = "sha256:742645059757a56ecd886faf4ed2441b9c0cd406079c2b4bee51bcc3fbcd510a"}, +] pygments = [ - {file = "Pygments-2.11.2-py3-none-any.whl", hash = "sha256:44238f1b60a76d78fc8ca0528ee429702aae011c265fe6a8dd8b63049ae41c65"}, - {file = "Pygments-2.11.2.tar.gz", hash = "sha256:4e426f72023d88d03b2fa258de560726ce890ff3b630f88c21cbb8b2503b8c6a"}, + {file = "Pygments-2.12.0-py3-none-any.whl", hash = "sha256:dc9c10fb40944260f6ed4c688ece0cd2048414940f1cea51b8b226318411c519"}, + {file = "Pygments-2.12.0.tar.gz", hash = "sha256:5eb116118f9612ff1ee89ac96437bb6b49e8f04d8a13b514ba26f620208e26eb"}, ] pyparsing = [ - {file = "pyparsing-3.0.7-py3-none-any.whl", hash = "sha256:a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484"}, - {file = "pyparsing-3.0.7.tar.gz", hash = "sha256:18ee9022775d270c55187733956460083db60b37d0d0fb357445f3094eed3eea"}, + {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, + {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, ] pypika-tortoise = [ - {file = "pypika-tortoise-0.1.3.tar.gz", hash = "sha256:ecdf2d6e0aeb0e15880d9e2ead41362ec7320f37fb25a3a71664c2e1105ad218"}, - {file = "pypika_tortoise-0.1.3-py3-none-any.whl", hash = "sha256:28fb2715a94ff2f3bc1c4ef6cc46c385c244c27d100aac760231bf612361d5ba"}, + {file = "pypika-tortoise-0.1.4.tar.gz", hash = "sha256:f4b4e6c72fc13f49058181928e66930b59fee988823c8fd01498f95e2ff788ca"}, + {file = "pypika_tortoise-0.1.4-py3-none-any.whl", hash = "sha256:bdc7e63c88791679a8b3f0b008582b6d3fcd21830650d274db35a7012e7b8bcd"}, ] pytest = [ {file = "pytest-6.2.5-py3-none-any.whl", hash = "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"}, @@ -1142,8 +1180,8 @@ python-dateutil = [ {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, ] python-slugify = [ - {file = "python-slugify-6.1.1.tar.gz", hash = "sha256:00003397f4e31414e922ce567b3a4da28cf1436a53d332c9aeeb51c7d8c469fd"}, - {file = "python_slugify-6.1.1-py2.py3-none-any.whl", hash = "sha256:8c0016b2d74503eb64761821612d58fcfc729493634b1eb0575d8f5b4aa1fbcf"}, + {file = "python-slugify-6.1.2.tar.gz", hash = "sha256:272d106cb31ab99b3496ba085e3fea0e9e76dcde967b5e9992500d1f785ce4e1"}, + {file = "python_slugify-6.1.2-py2.py3-none-any.whl", hash = "sha256:7b2c274c308b62f4269a9ba701aa69a797e9bca41aeee5b3a9e79e36b6656927"}, ] pytz = [ {file = "pytz-2022.1-py2.py3-none-any.whl", hash = "sha256:e68985985296d9a66a881eb3193b0906246245294a881e7c8afe623866ac6a5c"}, @@ -1170,16 +1208,16 @@ snowballstemmer = [ {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, ] soupsieve = [ - {file = "soupsieve-2.3.1-py3-none-any.whl", hash = "sha256:1a3cca2617c6b38c0343ed661b1fa5de5637f257d4fe22bd9f1338010a1efefb"}, - {file = "soupsieve-2.3.1.tar.gz", hash = "sha256:b8d49b1cd4f037c7082a9683dfa1801aa2597fb11c3a1155b7a5b94829b4f1f9"}, + {file = "soupsieve-2.3.2.post1-py3-none-any.whl", hash = "sha256:3b2503d3c7084a42b1ebd08116e5f81aadfaea95863628c80a3b774a11b7c759"}, + {file = "soupsieve-2.3.2.post1.tar.gz", hash = "sha256:fc53893b3da2c33de295667a0e19f078c14bf86544af307354de5fcf12a3f30d"}, ] sphinx = [ {file = "Sphinx-4.4.0-py3-none-any.whl", hash = "sha256:5da895959511473857b6d0200f56865ed62c31e8f82dd338063b84ec022701fe"}, {file = "Sphinx-4.4.0.tar.gz", hash = "sha256:6caad9786055cb1fa22b4a365c1775816b876f91966481765d7d50e9f0dd35cc"}, ] sphinx-autodoc-typehints = [ - {file = "sphinx_autodoc_typehints-1.17.0-py3-none-any.whl", hash = "sha256:081daf53077b4ae1c28347d6d858e13e63aefe3b4aacef79fd717dd60687b470"}, - {file = "sphinx_autodoc_typehints-1.17.0.tar.gz", hash = "sha256:51c7b3f5cb9ccd15d0b52088c62df3094f1abd9612930340365c26def8629a14"}, + {file = "sphinx_autodoc_typehints-1.17.1-py3-none-any.whl", hash = "sha256:f16491cad05a13f4825ecdf9ee4ff02925d9a3b1cf103d4d02f2f81802cce653"}, + {file = "sphinx_autodoc_typehints-1.17.1.tar.gz", hash = "sha256:844d7237d3f6280b0416f5375d9556cfd84df1945356fcc34b82e8aaacab40f3"}, ] sphinx-material = [ {file = "sphinx_material-0.0.35-py3-none-any.whl", hash = "sha256:a62a0a48d4c32edc260f9bdbca658e7d149beb10e1d338848b0076bb13be0775"}, @@ -1222,8 +1260,8 @@ toml = [ {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, ] tomlkit = [ - {file = "tomlkit-0.10.0-py3-none-any.whl", hash = "sha256:cac4aeaff42f18fef6e07831c2c2689a51df76cf2ede07a6a4fa5fcb83558870"}, - {file = "tomlkit-0.10.0.tar.gz", hash = "sha256:d99946c6aed3387c98b89d91fb9edff8f901bf9255901081266a84fb5604adcd"}, + {file = "tomlkit-0.10.2-py3-none-any.whl", hash = "sha256:905cf92c2111ef80d355708f47ac24ad1b6fc2adc5107455940088c9bbecaedb"}, + {file = "tomlkit-0.10.2.tar.gz", hash = "sha256:30d54c0b914e595f3d10a87888599eab5321a2a69abc773bbefff51599b72db6"}, ] tortoise-orm = [ {file = "tortoise-orm-0.18.1.tar.gz", hash = "sha256:537361ce2d0829741afd43afd9bc9413a314a176cb58747d88047c20ccc01db1"}, @@ -1234,8 +1272,8 @@ tweepy = [ {file = "tweepy-4.4.0.tar.gz", hash = "sha256:8d4b4520271b796fa7efc4c5d5ef3228af4d79f6a4d3ace3900b2778ed8f6f1c"}, ] typing-extensions = [ - {file = "typing_extensions-4.1.1-py3-none-any.whl", hash = "sha256:21c85e0fe4b9a155d0799430b0ad741cdce7e359660ccbd8b530613e8df88ce2"}, - {file = "typing_extensions-4.1.1.tar.gz", hash = "sha256:1a9462dcc3347a79b1f1c0271fbe79e844580bb598bafa1ed208b94da3cdcd42"}, + {file = "typing_extensions-4.2.0-py3-none-any.whl", hash = "sha256:6657594ee297170d19f67d55c05852a874e7eb634f4f753dbd667855e07c1708"}, + {file = "typing_extensions-4.2.0.tar.gz", hash = "sha256:f1c24655a0da0d1b67f07e17a5e6b2a105894e6824b92096378bb3668ef02376"}, ] unidecode = [ {file = "Unidecode-1.3.4-py3-none-any.whl", hash = "sha256:afa04efcdd818a93237574791be9b2817d7077c25a068b00f8cff7baa4e59257"}, @@ -1246,6 +1284,6 @@ urllib3 = [ {file = "urllib3-1.26.9.tar.gz", hash = "sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e"}, ] zipp = [ - {file = "zipp-3.7.0-py3-none-any.whl", hash = "sha256:b47250dd24f92b7dd6a0a8fc5244da14608f3ca90a5efcd37a3b1642fac9a375"}, - {file = "zipp-3.7.0.tar.gz", hash = "sha256:9f50f446828eb9d45b267433fd3e9da8d801f614129124863f9c51ebceafb87d"}, + {file = "zipp-3.8.0-py3-none-any.whl", hash = "sha256:c4f6e5bbf48e74f7a38e7cc5b0480ff42b0ae5178957d564d18932525d5cf099"}, + {file = "zipp-3.8.0.tar.gz", hash = "sha256:56bf8aadb83c24db6c4b577e13de374ccfb67da2078beba1d037c17980bf43ad"}, ] diff --git a/pyproject.toml b/pyproject.toml index 32485d5..4e2d53e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,7 +13,7 @@ python = "^3.9" dynaconf = "~3.1" tortoise-orm = "~0.18" aiosqlite = "~0.17" -Jinja2 = "~3.0" +Jinja2 = "~3.1" requests = "~2.26" arrow = "~1.1" click = "~8.0" diff --git a/scripts/generate_completion_scripts.sh b/scripts/generate_completion_scripts.sh index 272753e..dd6f2df 100755 --- a/scripts/generate_completion_scripts.sh +++ b/scripts/generate_completion_scripts.sh @@ -10,3 +10,5 @@ scripts/mobilizon-reshare.sh > etc/fish/completions/mobilizon-reshare.fish export _MOBILIZON_RESHARE_COMPLETE=zsh_source scripts/mobilizon-reshare.sh > etc/zsh/mobilizon-reshare-completion.zsh + +exit 0 \ No newline at end of file diff --git a/tests/commands/conftest.py b/tests/commands/conftest.py index f592964..4d8d5af 100644 --- a/tests/commands/conftest.py +++ b/tests/commands/conftest.py @@ -111,7 +111,7 @@ async def mock_publisher_config(monkeypatch, publisher_class, mock_formatter_cla ) monkeypatch.setattr( - mobilizon_reshare.storage.query.read, "get_active_publishers", _mock_active_pub + mobilizon_reshare.main.publish, "get_active_publishers", _mock_active_pub ) monkeypatch.setattr( diff --git a/tests/commands/test_publish.py b/tests/commands/test_publish.py new file mode 100644 index 0000000..e6278cf --- /dev/null +++ b/tests/commands/test_publish.py @@ -0,0 +1,110 @@ +from logging import DEBUG + +import pytest + +from mobilizon_reshare.main.publish import select_and_publish, publish_event +from mobilizon_reshare.storage.query.converter import event_from_model +from mobilizon_reshare.event.event import EventPublicationStatus +from mobilizon_reshare.models.event import Event +from mobilizon_reshare.models.publication import PublicationStatus +from mobilizon_reshare.storage.query.read import get_all_publications +from tests.conftest import event_0, event_1 + +one_unpublished_event_specification = { + "event": 1, + "publisher": ["telegram", "twitter", "mastodon", "zulip"], +} +three_event_specification = { + "event": 3, + "publications": [ + {"event_idx": 0, "publisher_idx": 0, "status": PublicationStatus.COMPLETED} + ], + "publisher": ["telegram", "twitter", "mastodon", "zulip"], +} + + +@pytest.mark.asyncio +async def test_publish_no_event(caplog): + with caplog.at_level(DEBUG): + assert await select_and_publish() is None + assert "No event to publish found" in caplog.text + + +@pytest.mark.parametrize( + "publisher_class", [pytest.lazy_fixture("mock_publisher_class")] +) +@pytest.mark.asyncio +@pytest.mark.parametrize( + "specification,expected_event", + [ + [one_unpublished_event_specification, event_0], + [three_event_specification, event_1], + ], +) +async def test_select_and_publish_new_event( + generate_models, + caplog, + mock_publisher_config, + message_collector, + specification, + expected_event, +): + await generate_models(specification) + with caplog.at_level(DEBUG): + # calling the publish command without arguments + assert await select_and_publish() is not None + + assert "Event to publish found" in caplog.text + assert message_collector == [ + f"{expected_event.name}|{expected_event.description}", + ] + + event = ( + await Event.filter(mobilizon_id=expected_event.mobilizon_id) + .prefetch_related("publications") + .prefetch_related("publications__publisher") + )[0] + + # it should create a publication for each publisher + publications = event.publications + assert len(publications) == 1, publications + + # all the publications for the first event should be saved as COMPLETED + for p in publications: + assert p.status == PublicationStatus.COMPLETED + + # the derived status for the event should be COMPLETED + assert event_from_model(event).status == EventPublicationStatus.COMPLETED + + +@pytest.mark.asyncio +@pytest.mark.parametrize( + "publisher_class,publishers,expected", + [ + [pytest.lazy_fixture("mock_publisher_class"), None, {"mock"}], + [pytest.lazy_fixture("mock_publisher_class"), [], {"mock"}], + [pytest.lazy_fixture("mock_publisher_class"), [None, None], {"mock"}], + [pytest.lazy_fixture("mock_zulip_publisher_class"), ["zulip"], {"zulip"}], + ], +) +async def test_publish_event( + generate_models, + caplog, + mock_publisher_config, + message_collector, + publishers, + expected, +): + await generate_models(one_unpublished_event_specification) + with caplog.at_level(DEBUG): + # calling mobilizon-reshare publish -E -p + report = await publish_event(event_0, publishers) + assert report is not None + assert report.successful + + # We test whether we published only to the expected platforms + assert {pub.publication.publisher.name for pub in report.reports} == expected + publications = list(await get_all_publications()) + assert len(publications) == len(expected) + assert all(p.status == PublicationStatus.COMPLETED for p in publications) + assert {p.publisher.name for p in publications} == expected diff --git a/tests/conftest.py b/tests/conftest.py index 15429e5..6166e1a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -174,7 +174,9 @@ def event_model_generator(): @pytest.fixture() def publisher_model_generator(): - def _publisher_model_generator(idx=1,): + def _publisher_model_generator( + idx=1, + ): return Publisher(name=f"publisher_{idx}", account_ref=f"account_ref_{idx}") return _publisher_model_generator @@ -377,6 +379,23 @@ def mock_publisher_class(message_collector): return MockPublisher +@pytest.fixture +def mock_zulip_publisher_class(message_collector): + class MockPublisher(AbstractPlatform): + name = "zulip" + + def _send(self, message, event): + message_collector.append(message) + + def _validate_response(self, response): + pass + + def validate_credentials(self) -> None: + pass + + return MockPublisher + + @pytest.fixture def mock_publisher_valid(message_collector, mock_publisher_class): @@ -394,7 +413,10 @@ def mock_mobilizon_success_answer(mobilizon_answer, mobilizon_url): with responses.RequestsMock() as rsps: rsps.add( - responses.POST, mobilizon_url, json=mobilizon_answer, status=200, + responses.POST, + mobilizon_url, + json=mobilizon_answer, + status=200, ) yield @@ -406,7 +428,10 @@ def mock_multiple_success_answer(multiple_answers, mobilizon_url): for answer in multiple_answers: rsps.add( - responses.POST, mobilizon_url, json=answer, status=200, + responses.POST, + mobilizon_url, + json=answer, + status=200, ) yield diff --git a/tests/publishers/conftest.py b/tests/publishers/conftest.py index 0db76cb..eb1abde 100644 --- a/tests/publishers/conftest.py +++ b/tests/publishers/conftest.py @@ -5,9 +5,7 @@ from uuid import UUID import arrow import pytest -import mobilizon_reshare.storage.query.read from mobilizon_reshare.event.event import MobilizonEvent -from mobilizon_reshare.models.publisher import Publisher from mobilizon_reshare.publishers.abstract import ( AbstractPlatform, AbstractEventFormatter, @@ -80,18 +78,3 @@ def mock_publisher_invalid_response(message_collector): pass return MockPublisher() - - -@pytest.fixture() -async def mock_active_publishers_config(monkeypatch): - publisher = Publisher(name="zulip") - await publisher.save() - - def _mock_active_pub(): - return ["zulip"] - - monkeypatch.setattr( - mobilizon_reshare.storage.query.read, "get_active_publishers", _mock_active_pub - ) - - return publisher diff --git a/tests/publishers/test_zulip.py b/tests/publishers/test_zulip.py index 62857be..6037952 100644 --- a/tests/publishers/test_zulip.py +++ b/tests/publishers/test_zulip.py @@ -4,7 +4,6 @@ import responses from mobilizon_reshare.config.config import get_settings from mobilizon_reshare.models.publication import PublicationStatus -from mobilizon_reshare.models.publisher import Publisher from mobilizon_reshare.publishers.coordinator import PublisherCoordinator from mobilizon_reshare.publishers.exceptions import ( InvalidEvent, @@ -14,8 +13,15 @@ from mobilizon_reshare.publishers.exceptions import ( ) from mobilizon_reshare.publishers.platforms.zulip import ZulipFormatter, ZulipPublisher from mobilizon_reshare.storage.query.converter import event_to_model -from mobilizon_reshare.storage.query.read import build_publications +from mobilizon_reshare.storage.query.read import build_publications, get_all_publishers +one_publication_specification = { + "event": 1, + "publications": [ + {"event_idx": 0, "publisher_idx": 0, "status": PublicationStatus.COMPLETED}, + ], + "publisher": ["zulip"], +} api_uri = "https://zulip.twc-italia.org/api/v1/" users_me = { "result": "success", @@ -83,7 +89,7 @@ def mocked_client_error_response(): @pytest.fixture @pytest.mark.asyncio async def setup_db( - mock_active_publishers_config, event_model_generator, publication_model_generator + generate_models ): settings = get_settings() settings["publisher"]["zulip"][ @@ -91,20 +97,15 @@ async def setup_db( ] = "giacomotest2-bot@zulip.twc-italia.org" settings["publisher"]["zulip"]["instance"] = "https://zulip.twc-italia.org" - publisher = await Publisher.filter(name="zulip").first() - event = event_model_generator() - await event.save() - publication = publication_model_generator( - event_id=event.id, publisher_id=publisher.id - ) - await publication.save() + await generate_models(one_publication_specification) @pytest.fixture @pytest.mark.asyncio -async def unsaved_publications(event): +async def unsaved_publications(setup_db, event): await event_to_model(event).save() - return await build_publications(event) + publishers = [p.name for p in await get_all_publishers()] + return await build_publications(event, publishers) @pytest.mark.asyncio diff --git a/tests/storage/conftest.py b/tests/storage/conftest.py index 18d942e..02039d1 100644 --- a/tests/storage/conftest.py +++ b/tests/storage/conftest.py @@ -1,6 +1,5 @@ import pytest -import mobilizon_reshare.storage.query.read from mobilizon_reshare.models.publisher import Publisher @@ -9,11 +8,4 @@ async def mock_active_publishers(request, monkeypatch): for name in request.param: await Publisher.create(name=name) - def _mock_active_pub(): - return request.param - - monkeypatch.setattr( - mobilizon_reshare.storage.query.read, "get_active_publishers", _mock_active_pub - ) - return request.param diff --git a/tests/storage/test_query.py b/tests/storage/test_query.py index 369dbc3..e04e8e9 100644 --- a/tests/storage/test_query.py +++ b/tests/storage/test_query.py @@ -180,7 +180,7 @@ async def test_build_publications( ): await generate_models(spec) - publications = list(await build_publications(event)) + publications = list(await build_publications(event, mock_active_publishers)) assert len(publications) == n_publications