Skip to content

Commit

Permalink
Merge pull request #52 from smkent/manage-cookie
Browse files Browse the repository at this point in the history
Update project template cruft, dependencies
  • Loading branch information
smkent authored Jan 15, 2025
2 parents 6e6eb8c + 0759e32 commit 039b232
Show file tree
Hide file tree
Showing 14 changed files with 778 additions and 567 deletions.
2 changes: 1 addition & 1 deletion .cruft.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"template": "https://github.com/smkent/cookie-python",
"commit": "dee411e1e91b735d5df2ca480c611b21a4d371be",
"commit": "7025e55adab820dd8e63d8be0e0ec0cabad0d830",
"context": {
"cookiecutter": {
"project_name": "wafflesbot",
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/actions/python-poetry/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ runs:
# https://github.com/actions/runner-images/issues/6185
PYTHON_KEYRING_BACKEND: "keyring.backends.null.Keyring"
run: |
poetry install
poetry lock --check
poetry check --lock
poetry sync
PROJECT_VERSION=$(poetry version -s)
[ "${PROJECT_VERSION}" != "0.0.0" ] \
|| { echo "Versioning broken"; exit 1; }
Expand Down
17 changes: 9 additions & 8 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,26 @@ name: Release

env:
ENABLE_PYPI_PUBLISH: true
ENABLE_TEST_PYPI_PUBLISH: true
ENABLE_TEST_PYPI_PUBLISH: false
RELEASE_PYTHON_VERSION: "3.12"
RELEASE_POETRY_VERSION: "1.8"
RELEASE_POETRY_VERSION: "2.0"

on:
push:
tags:
- '*'
workflow_dispatch:

jobs:
Publish:
name: Publish package for ${{ github.ref_name }}

if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/p/wafflesbot
permissions:
id-token: write

steps:
- name: 💾 Check out repository
Expand Down Expand Up @@ -49,15 +53,12 @@ jobs:
uses: pypa/gh-action-pypi-publish@release/v1
if: ${{ env.ENABLE_TEST_PYPI_PUBLISH == 'true' }}
with:
password: ${{ secrets.TEST_PYPI_API_TOKEN }}
repository_url: https://test.pypi.org/legacy/
skip_existing: true
repository-url: https://test.pypi.org/legacy/
skip-existing: true

- name: ☢️ Publish to PyPI
if: ${{ env.ENABLE_PYPI_PUBLISH == 'true' }}
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.PYPI_API_TOKEN }}

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ jobs:
os:
- Ubuntu
python-version:
- "3.8"
- "3.9"
- "3.10"
- "3.11"
- "3.12"
- "3.13"
poetry-version:
- "1.8"
- "2.0"

runs-on: ${{ matrix.os }}-latest
steps:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/container.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
RELEASE_PYTHON_VERSION: "3.12"
RELEASE_POETRY_VERSION: "1.8"
RELEASE_POETRY_VERSION: "2.0"

on:
pull_request:
Expand Down
12 changes: 6 additions & 6 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
rev: v5.0.0
hooks:
- id: check-yaml
- id: check-merge-conflict
- id: debug-statements
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/psf/black
rev: 24.4.2
rev: 24.10.0
hooks:
- id: black
args: ["--config", "pyproject.toml"]
Expand All @@ -18,14 +18,14 @@ repos:
- id: isort
args: ["--show-config"]
- repo: https://github.com/pycqa/bandit
rev: 1.7.9
rev: 1.8.2
hooks:
- id: bandit
additional_dependencies: ['.[toml]']
args: ["--configfile", "pyproject.toml"]
exclude: '^tests/'
- repo: https://github.com/pycqa/flake8
rev: 7.1.0
rev: 7.1.1
hooks:
- id: flake8
additional_dependencies:
Expand All @@ -38,10 +38,10 @@ repos:
hooks:
- id: autoflake
- repo: https://github.com/asottile/pyupgrade
rev: v3.16.0
rev: v3.19.1
hooks:
- id: pyupgrade
args: ["--keep-runtime-typing"]
args: ["--py39-plus", "--keep-runtime-typing"]
- repo: local
hooks:
- id: mypy
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,14 +131,14 @@ Via [`pipx`][pipx]:
```console
pip install pipx
pipx install poetry
pipx inject poetry poetry-dynamic-versioning poetry-pre-commit-plugin
pipx inject poetry poetry-pre-commit-plugin
```

Via `pip`:

```console
pip install poetry
poetry self add poetry-dynamic-versioning poetry-pre-commit-plugin
poetry self add poetry-pre-commit-plugin
```

### Development tasks
Expand Down
1,185 changes: 693 additions & 492 deletions poetry.lock

Large diffs are not rendered by default.

33 changes: 20 additions & 13 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
[build-system]
requires = ["poetry-core>=1.2.0", "poetry-dynamic-versioning"]
build-backend = "poetry_dynamic_versioning.backend"
requires = ["poetry-core>=2.0.0,<3.0.0", "poetry-dynamic-versioning"]
build-backend = "poetry.core.masonry.api"

[tool.poetry]
[project]
name = "wafflesbot"
version = "0.0.0"
description = "Tech recruiter auto reply bot using JMAP"
license = "GPL-3.0-or-later"
authors = ["Stephen Kent <[email protected]>"]
authors = [ { name = "Stephen Kent", email = "[email protected]" } ]
readme = "README.md"
repository = "https://github.com/smkent/waffles"
classifiers = [
Expand All @@ -18,13 +17,24 @@ classifiers = [
"Topic :: Software Development :: Libraries :: Python Modules",
"Typing :: Typed",
]
requires-python = ">=3.9,<4.0"
dynamic = [ "version" ]
dependencies = [
"jmapc (>=0.2.0)",
"replyowl (>=0.1.0)",
]

[project.scripts]
wafflesbot = "wafflesbot.main:main"

[tool.poetry.dependencies]
python = "^3.8"
replyowl = ">=0.1.0"
jmapc = ">=0.2.0"
[tool.poetry]
requires-poetry = ">=2.0"
version = "0.0.0"

[tool.poetry.requires-plugins]
poetry-dynamic-versioning = { version = ">=1.0.0,<2.0.0", extras = ["plugin"] }

[tool.poetry.dev-dependencies]
[tool.poetry.group.dev.dependencies]
bandit = {extras = ["toml"], version = "*"}
black = "*"
cruft = "*"
Expand All @@ -44,9 +54,6 @@ pytest-sugar = "*"
freezegun = "*"
types-freezegun = "*"

[tool.poetry.scripts]
wafflesbot = "wafflesbot.main:main"

[tool.poetry-dynamic-versioning]
enable = true
vcs = "git"
Expand Down
12 changes: 6 additions & 6 deletions tests/method_utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import json
from datetime import datetime, timezone
from typing import Dict, List, Optional
from typing import Optional
from unittest import mock

import sseclient
Expand Down Expand Up @@ -93,7 +93,7 @@ def make_mailbox_get_call(name: str) -> mock._Call:
)


def make_mailbox_get_response(id: str, name: str) -> List[InvocationResponse]:
def make_mailbox_get_response(id: str, name: str) -> list[InvocationResponse]:
return [
InvocationResponse(id="0.Mailbox/query", response=Response()),
InvocationResponse(
Expand Down Expand Up @@ -155,7 +155,7 @@ def make_thread_search_call() -> mock._Call:
)


def make_thread_search_response() -> List[InvocationResponse]:
def make_thread_search_response() -> list[InvocationResponse]:
return [
InvocationResponse(id="0.Email/query", response=Response()),
InvocationResponse(id="1.Email/get", response=Response()),
Expand Down Expand Up @@ -200,7 +200,7 @@ def make_email_changes_response() -> EmailChangesResponse:


def make_email_get_call(
properties: Optional[List[str]] = None,
properties: Optional[list[str]] = None,
fetch_all_body_values: Optional[bool] = None,
) -> mock._Call:
return mock.call(
Expand Down Expand Up @@ -355,7 +355,7 @@ def make_email_send_call() -> mock._Call:
)


def make_email_send_response() -> List[InvocationResponse]:
def make_email_send_response() -> list[InvocationResponse]:
return [
InvocationResponse(id="0.Email/set", response=Response()),
InvocationResponse(
Expand All @@ -382,7 +382,7 @@ def make_email_send_response() -> List[InvocationResponse]:
def make_email_archive_call(
is_read: bool, is_in_inbox: bool
) -> Optional[mock._Call]:
updates: Dict[str, Optional[bool]] = {}
updates: dict[str, Optional[bool]] = {}
if not is_read:
updates["keywords/$seen"] = True
if is_in_inbox:
Expand Down
40 changes: 21 additions & 19 deletions tests/test_waffles.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from typing import Any, Iterable, List
from typing import Any
from collections.abc import Iterable
from unittest import mock

import pytest
Expand Down Expand Up @@ -50,21 +51,22 @@ def mock_request(wafflesbot: Waffles) -> Iterable[mock.MagicMock]:
primary_accounts=dict(mail="u1138"),
event_source_url="https://jmap-example.localhost/events/",
)
with mock.patch(
"jmapc.client.Client.jmap_session", session_mock
), mock.patch.object(wafflesbot.client, "request", request_mock):
with (
mock.patch("jmapc.client.Client.jmap_session", session_mock),
mock.patch.object(wafflesbot.client, "request", request_mock),
):
yield request_mock


@pytest.fixture(autouse=True)
def mock_events(wafflesbot: Waffles) -> Iterable[List[sseclient.Event]]:
mock_events_data: List[sseclient.Event] = []
def mock_events(wafflesbot: Waffles) -> Iterable[list[sseclient.Event]]:
mock_events_data: list[sseclient.Event] = []
with mock.patch.object(wafflesbot.client, "_events", mock_events_data):
yield mock_events_data


def assert_or_debug_calls(
call_args_list: mock._CallList, expected_calls: List[mock._Call]
call_args_list: mock._CallList, expected_calls: list[mock._Call]
) -> None:
try:
assert call_args_list == expected_calls
Expand Down Expand Up @@ -97,7 +99,7 @@ def assert_or_debug_calls(
def test_wafflesbot(
wafflesbot: Waffles,
mock_request: mock.MagicMock,
mock_events: List[sseclient.Event],
mock_events: list[sseclient.Event],
dry_run: bool,
events: bool,
original_email_read: bool,
Expand All @@ -106,7 +108,7 @@ def test_wafflesbot(
wafflesbot.client.live_mode = not dry_run
mock_events.append(make_email_event(email_state="1118"))
mock_events.append(make_email_event(email_state="1119"))
expected_calls: List[mock._Call] = []
expected_calls: list[mock._Call] = []
expected_calls.append(make_mailbox_get_call("pigeonhole"))
if events:
expected_calls.append(make_email_changes_call(since_state="1118"))
Expand All @@ -131,7 +133,7 @@ def test_wafflesbot(
)
if archive_call:
expected_calls.append(archive_call)
mock_responses: List[Any] = []
mock_responses: list[Any] = []
mock_responses.append(make_mailbox_get_response("MBX50", "pigeonhole"))
if events:
mock_responses.append(make_email_changes_response())
Expand Down Expand Up @@ -179,14 +181,14 @@ def test_wafflesbot(
def test_wafflesbot_no_matching_identity(
wafflesbot: Waffles,
mock_request: mock.MagicMock,
mock_events: List[sseclient.Event],
mock_events: list[sseclient.Event],
) -> None:
original_email_read = False
original_email_in_inbox = True
wafflesbot.client.live_mode = True
mock_events.append(make_email_event(email_state="1118"))
mock_events.append(make_email_event(email_state="1119"))
expected_calls: List[mock._Call] = []
expected_calls: list[mock._Call] = []
expected_calls.append(make_mailbox_get_call("pigeonhole"))
expected_calls.append(make_email_changes_call(since_state="1118"))
expected_calls.append(
Expand All @@ -195,7 +197,7 @@ def test_wafflesbot_no_matching_identity(
expected_calls.append(make_thread_get_call())
expected_calls.append(make_email_get_call(fetch_all_body_values=True))
expected_calls.append(mock.call(IdentityGet()))
mock_responses: List[Any] = []
mock_responses: list[Any] = []
mock_responses.append(make_mailbox_get_response("MBX50", "pigeonhole"))
mock_responses.append(make_email_changes_response())
mock_responses.append(
Expand Down Expand Up @@ -235,7 +237,7 @@ def test_wafflesbot_no_matching_identity(
def test_wafflesbot_ignore_event(
wafflesbot: Waffles,
mock_request: mock.MagicMock,
mock_events: List[sseclient.Event],
mock_events: list[sseclient.Event],
original_email_read: bool,
original_email_in_inbox: bool,
dry_run: bool,
Expand All @@ -244,13 +246,13 @@ def test_wafflesbot_ignore_event(
wafflesbot.client.live_mode = not dry_run
mock_events.append(make_email_event(email_state="1118"))
mock_events.append(make_email_event(email_state="1119"))
expected_calls: List[mock._Call] = []
expected_calls: list[mock._Call] = []
expected_calls.append(make_mailbox_get_call("pigeonhole"))
expected_calls.append(make_email_changes_call(since_state="1118"))
expected_calls.append(
make_email_get_call(properties=["threadId", "mailboxIds"])
)
mock_responses: List[Any] = []
mock_responses: list[Any] = []
mock_responses.append(make_mailbox_get_response("MBX50", "pigeonhole"))
mock_responses.append(make_email_changes_response())
mock_responses.append(
Expand All @@ -274,15 +276,15 @@ def test_wafflesbot_ignore_event(
def test_wafflesbot_event_error(
wafflesbot: Waffles,
mock_request: mock.MagicMock,
mock_events: List[sseclient.Event],
mock_events: list[sseclient.Event],
dry_run: bool,
) -> None:
wafflesbot.client.live_mode = not dry_run
mock_events.append(make_email_event(email_state="1118"))
mock_events.append(make_email_event(email_state="1119"))
expected_calls: List[mock._Call] = []
expected_calls: list[mock._Call] = []
expected_calls.append(make_mailbox_get_call("pigeonhole"))
mock_responses: List[Any] = []
mock_responses: list[Any] = []
mock_responses.append(Exception)
mock_request.side_effect = mock_responses
wafflesbot.run(events=True) # Should not raise an exception
Expand Down
Loading

0 comments on commit 039b232

Please sign in to comment.