Skip to content

Commit

Permalink
Linting (#24)
Browse files Browse the repository at this point in the history
* Running lint and fixed small test error on Python 3.10

* more linting

* A lot more linting.
  • Loading branch information
nigini authored Oct 30, 2024
1 parent b1bc72b commit 39c00e0
Show file tree
Hide file tree
Showing 13 changed files with 791 additions and 738 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ __pycache__/
docs/dist/
requirements.txt
app/static/favicon.ico
misc/dev-supervisord.conf
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Instances in the wild:
- [blog.joaocosta.eu](https://blog.joaocosta.eu/)
- [bw3.dev](https://bw3.dev/)
- [blog.nigini.me](https://blog.nigini.me)
- [chrichri.ween.de](chrichri.ween.de)


## Features
Expand Down
2 changes: 1 addition & 1 deletion app/boxes.py
Original file line number Diff line number Diff line change
Expand Up @@ -821,7 +821,7 @@ async def send_vote(

# commit db session
await db_session.commit()

return vote_id


Expand Down
5 changes: 4 additions & 1 deletion app/customization.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,10 @@ def get_custom_router() -> APIRouter | None:
for path, handler in _CUSTOM_ROUTES.items():
if isinstance(handler, HTMLPage):
router.add_api_route(
path, _custom_page_handler(path, handler), methods=["GET"], response_model=None
path,
_custom_page_handler(path, handler),
methods=["GET"],
response_model=None,
)
else:
router.add_api_route(path, handler.handler)
Expand Down
4 changes: 2 additions & 2 deletions app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,13 @@

# TODO(ts):
# Next:
# - CustomMiddleware??? Check is issues with Starlette were resolved!!!
# - self-destruct + move support and actions/tasks for
# - doc for prune/move/delete
# - fix issue with followers from a blocked server (skip it?)
# - allow to share old notes
# - only show 10 most recent threads in DMs
# - prevent double accept/double follow
# - UI support for updating posts
# - indieauth tweaks
# - support update post with history?

Expand All @@ -102,7 +102,7 @@ class CustomMiddleware:
"""Raw ASGI middleware as using starlette base middleware causes issues
with both:
- Jinja2: https://github.com/encode/starlette/issues/472
- async SQLAchemy: https://github.com/tiangolo/fastapi/issues/4719
- async SQLAlchemy: https://github.com/tiangolo/fastapi/issues/4719
"""

def __init__(
Expand Down
5 changes: 3 additions & 2 deletions app/micropub.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ def _prop_get(dat: dict[str, Any], key: str) -> str:
return val


# TODO: Refactor this method... break it down in its supported 'actions' and supported formats
@router.post("/micropub", response_model=None)
async def post_micropub_endpoint(
request: Request,
Expand All @@ -84,7 +85,7 @@ async def post_micropub_endpoint(

if "action" in form_data:
if form_data["action"] in ["delete", "update"]:
url = form_data["url"]
url = str(form_data["url"])
outbox_object = await get_outbox_object_by_ap_id(db_session, url)
if not outbox_object:
return JSONResponse(
Expand All @@ -111,7 +112,7 @@ async def post_micropub_endpoint(
if "replace" in form_data:
logger.info(f"Updating object {outbox_object.ap_id}: {form_data}")
await send_update(
db_session, outbox_object.ap_id, form_data["replace"]["content"]
db_session, outbox_object.ap_id, form_data["replace"]["content"] # type: ignore
)
return JSONResponse(content={}, status_code=200)
else:
Expand Down
1,421 changes: 734 additions & 687 deletions poetry.lock

Large diffs are not rendered by default.

5 changes: 2 additions & 3 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import os

os.environ["MICROBLOGPUB_CONFIG_FILE"] = "tests.toml"

from typing import Generator

import pytest
Expand All @@ -15,6 +12,8 @@
from app.main import app
from tests.factories import _Session

os.environ["MICROBLOGPUB_CONFIG_FILE"] = "tests.toml"


@pytest_asyncio.fixture
async def async_db_session():
Expand Down
6 changes: 2 additions & 4 deletions tests/test_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@
import starlette
from fastapi.testclient import TestClient

from app import activitypub as ap
from app.config import generate_csrf_token
from app.main import app
from tests.utils import generate_admin_session_cookies

from app import activitypub as ap



def test_admin_endpoints_are_authenticated(client: TestClient) -> None:
routes_tested = []
Expand Down Expand Up @@ -45,5 +43,5 @@ def test_public_works_authenticated(client: TestClient) -> None:
follow_redirects=False,
)
assert response.status_code == 302
resp = client.get("/",cookies=generate_admin_session_cookies())
resp = client.get("/", cookies=generate_admin_session_cookies())
assert resp.status_code == 200
23 changes: 15 additions & 8 deletions tests/test_customization.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,34 @@
from fastapi.testclient import TestClient
from unittest.mock import MagicMock

from app.main import app
from app.customization import get_custom_router, register_html_page, _CUSTOM_ROUTES
from fastapi.testclient import TestClient

from app.customization import _CUSTOM_ROUTES
from app.customization import HTMLPage
from app.customization import get_custom_router
from app.customization import register_html_page
from app.main import app


def test_html_route(client: TestClient) -> None:
test_path = "/test_registered_html"
mock_file_contents = '<h1 class="test">This is test file content</h1>'

# Test that we can register a HTML page
register_html_page(test_path,title="my mock html page", html_file="test.txt",show_in_navbar=True)
register_html_page(
test_path, title="my mock html page", html_file="test.txt", show_in_navbar=True
)

# And that it gets added correctly as a route in the app
app.include_router(get_custom_router())
custom_router = get_custom_router()
assert custom_router is not None
app.include_router(custom_router)
assert test_path in _CUSTOM_ROUTES

# confirm that the route also leads to the file being returned successfully.
m = MagicMock(read_text=MagicMock(return_value=mock_file_contents))
_CUSTOM_ROUTES[test_path].html_file = m

html_page = _CUSTOM_ROUTES[test_path]
assert isinstance(html_page, HTMLPage)
html_page.html_file = m
response = client.get(test_path)
assert response.status_code == 200
assert mock_file_contents in response.text

13 changes: 5 additions & 8 deletions tests/test_ioauth.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import pytest
from fastapi.responses import JSONResponse
from fastapi.testclient import TestClient
from sqlalchemy.orm import Session
from sqlalchemy.ext.asyncio import AsyncSession

from app import models
from app.config import generate_csrf_token
from app.config import session_serializer
from tests.utils import setup_auth_application_client
Expand Down Expand Up @@ -32,7 +30,7 @@ def test_oauth_registration(
@pytest.mark.asyncio
async def test_oauth_authorize(
client: TestClient,
async_db_session: Session,
async_db_session: AsyncSession,
):
# test that when logged in, we can see the authorize app page with all the relevant good bits
await setup_auth_application_client(async_db_session)
Expand Down Expand Up @@ -63,14 +61,14 @@ async def test_oauth_authorize(
cookies=logged_in_cookie,
data=confirmation,
)
assert response.status_code is 200
assert response.status_code == 200
assert "code=" in response.headers.get("refresh")


@pytest.mark.asyncio
async def test_oauth_access_token(
client: TestClient,
async_db_session: Session,
async_db_session: AsyncSession,
):
# test that we can get an access token
await setup_auth_auth_token(async_db_session)
Expand All @@ -81,11 +79,10 @@ async def test_oauth_access_token(
"redirect_uri": "testuri",
}

logged_in_cookie = {"session": session_serializer.dumps({"is_logged_in": True})}
response = client.post("/token", data=token_request)

data = response.json()
assert response.status_code is 200
assert response.status_code == 200
assert "access_token" in data
assert "refresh_token" in data

Expand Down
32 changes: 17 additions & 15 deletions tests/test_micropub.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import json

import pytest
from fastapi.testclient import TestClient
from sqlalchemy.orm import Session
from sqlalchemy.ext.asyncio import AsyncSession

from tests.utils import setup_auth_access_token, setup_outbox_note
from tests.utils import setup_auth_access_token
from tests.utils import setup_outbox_note


@pytest.mark.asyncio
async def test_micropub_create(
client: TestClient,
async_db_session: Session,
async_db_session: AsyncSession,
):
# test that we create a note via micropub
await setup_auth_access_token(async_db_session)
Expand All @@ -21,15 +20,13 @@ async def test_micropub_create(
}

body = {"type": ["h-entry"], "properties": {"content": ["Hello, World!"]}}
response = client.post("/micropub", data=json.dumps(body), headers=headers)

data = response.json()
response = client.post("/micropub", json=body, headers=headers)

# assert success and the location of the new note
assert response.status_code is 201
assert response.status_code == 201
assert "location" in response.headers

new_path = f"/o/{response.headers.get("Location").split("/")[-1]}"
new_path = f"/o/{response.headers.get('Location').split('/')[-1]}"
res = client.get(new_path)

# assert the new note is actually at the location
Expand All @@ -39,7 +36,7 @@ async def test_micropub_create(
@pytest.mark.asyncio
async def test_micropub_update(
client: TestClient,
async_db_session: Session,
async_db_session: AsyncSession,
):
# create and confirm note to update
hello_note = setup_outbox_note("123hello123")
Expand All @@ -58,13 +55,18 @@ async def test_micropub_update(
"Authorization": "Bearer accesstoken",
}

body = { "action":"update","type": ["h-entry"], "url":hello_note.ap_id, "replace": { "content": "potato"}}

client.post("/micropub", data=json.dumps(body), headers=headers)
body = {
"action": "update",
"type": ["h-entry"],
"url": hello_note.ap_id,
"replace": {"content": "potato"},
}

client.post("/micropub", json=body, headers=headers)

# confirm update
note_path = f"/o/{hello_note.public_id}"
response = client.get(note_path)

assert "123hello123" not in response.text
assert "potato" in response.text
assert "potato" in response.text
11 changes: 4 additions & 7 deletions tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
import fastapi
import httpx
import respx
from sqlalchemy.orm import Session


from app import activitypub as ap
from app import actor
Expand Down Expand Up @@ -252,11 +250,11 @@ def run_process_next_incoming_activity() -> None:
run_async(_process_next_incoming_activity)


async def setup_auth_application_client(db: Session):
async def setup_auth_application_client(db: AsyncSession):
# adds auth app client to db
client = models.OAuthClient(
client_name="testclient",
redirect_uris="testuri",
redirect_uris=["testuri"],
client_id="testclientid",
client_secret="testclientsecret",
)
Expand All @@ -265,7 +263,7 @@ async def setup_auth_application_client(db: Session):
await db.commit()


async def setup_auth_auth_token(db: Session):
async def setup_auth_auth_token(db: AsyncSession):
# adds authorized access token to DB
await setup_auth_application_client(db)
auth_request = models.IndieAuthAuthorizationRequest(
Expand All @@ -278,11 +276,10 @@ async def setup_auth_auth_token(db: Session):
)

db.add(auth_request)

await db.commit()


async def setup_auth_access_token(db: Session):
async def setup_auth_access_token(db: AsyncSession):
# adds authorized access token to DB
await setup_auth_auth_token(db)
access_token = models.IndieAuthAccessToken(
Expand Down

0 comments on commit 39c00e0

Please sign in to comment.