Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ jobs:
args: check --target-version ${{ env.PYTHON_TARGET }}

- name: Tests and coverage
run: hatch run cov
run: hatch test -p -c

- name: Codecov - Upload coverage
uses: codecov/codecov-action@v4
Expand Down
62 changes: 59 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -452,14 +452,70 @@ For this flow the `user` field will be ignored.

## Testing

The tests uses twisted's testing framework trial, with the development
enviroment managed by hatch. Running the tests and generating a coverage report
To create virtual development env and install dependencies:
```console
hatch shell
```

The tests use pytest, with the development environment managed by hatch. Running the tests
can be done like this:

```console
hatch run cov
hatch test
```

#### Additional optional testing arguments:
Run the tests in parallel: `-p`

Collect coverage data(automatically output as `lcov.info`): `-c`

#### Running a specific test:
Selecting a specific test to run can be as easy as providing the path to the test. All tests start from
the base test directory, `tests`. If running all tests, this can be left out. For specific tests, see
the [pytest usage docs](https://docs.pytest.org/en/stable/how-to/usage.html#specifying-which-tests-to-run) for more information

## Code Quality

Use `hatch fmt` to automatically format code, enforce style rules, and check types using:

- `black` and `isort` for formatting
- `ruff` for linting
- `mypy` for static type checking

### Check Code Without Modifying It

To check code quality without modifying files:

- Check formatting with `isort` and `black`:
```console
hatch fmt --check -f
```
- Check types and linting with `mypy` and `ruff`:
```console
hatch fmt --check -l
```
- Check all of above, formatting, linting, and typing:
```console
hatch fmt --check
```

### Auto-formatting Code

To automatically fix issues in the code:

- Format only using `black` and `isort`:
```console
hatch fmt -f
```
- Type checks(`mypy`) and lint, fixing autofixable `ruff` issues:
```console
hatch fmt -l
```
- Run all tools, format, lint, type-check:
```console
hatch fmt
```

## Releasing

After tagging a new version, manually create a Github release based on the tag. This will publish the package on PyPI.
Expand Down
121 changes: 113 additions & 8 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ classifiers = [
"Programming Language :: Python :: Implementation :: PyPy",
]
dependencies = [
"jwcrypto",
"jwcrypto<=1.5.6",
Comment thread
nico-famedly marked this conversation as resolved.
"twisted",
]
version = "0.13.0"
Expand All @@ -41,14 +41,14 @@ dependencies = [
"mock",
"matrix-synapse",
"ruff",
"mypy",
"mypy-zope",
"types-PyYAML",
"types-bleach",
"types-cachetools",
"types-requests",
"types-pyOpenSSL"
]
[tool.hatch.envs.default.scripts]
cov = "pytest --cov-report=term-missing --cov-config=pyproject.toml --cov=synapse_token_authenticator --cov=tests {args}"
format = "black ."
lint = "ruff check ."

[tool.hatch.envs.ci.scripts]
cov = "pytest --cov-report=lcov:lcov.info --cov-config=pyproject.toml --cov=synapse_token_authenticator --cov=tests"

[tool.coverage.run]
branch = true
Expand All @@ -57,3 +57,108 @@ omit = []

[tool.coverage.report]
exclude_lines = ["no cov", "if __name__ == .__main__.:", "if TYPE_CHECKING:"]

[tool.hatch.envs.hatch-static-analysis]
dependencies = [
"black",
"isort",
"ruff",
"mypy",
"mypy-zope",
"types-PyYAML",
"types-bleach",
"types-cachetools",
"types-jwcrypto",
"types-requests",
"types-pyOpenSSL"
]

[tool.hatch.envs.hatch-static-analysis.scripts]
format-check = [
"isort . --check --diff",
"black . --check --diff"
]
format-fix = [
"isort .",
"black ."
]
lint-check = [
"mypy",
"ruff check"
]
lint-fix = [
"mypy",
"ruff check --fix"
]
[tool.ruff]
target-version = "py310"
line-length = 88

[tool.mypy]
python_version = "3.10"
ignore_missing_imports = true
install_types = true
plugins = [
"mypy_zope:plugin"
]
files = ["synapse_token_authenticator", "tests"]

[tool.isort]
profile = "black"
src_paths = ["synapse_token_authenticator", "tests"]

[tool.hatch.envs.hatch-test]
# These below are installed by default. This list is to help not reinstall something.
# Updating hatch will change the version numbers, so ignore the pinned versions.
#dependencies = [
# "coverage-enable-subprocess==1.0",
# "coverage[toml]~=7.11",
# "pytest~=9.0",
# "pytest-mock~=3.12",
# "pytest-randomly~=3.15",
# "pytest-rerunfailures~=14.0",
# "pytest-xdist[psutil]~=3.5",
#]

extra-dependencies = [
"pytest-cov",
"matrix-synapse",
]
extra-args = [
# use the loadscope dist method when running tests parallel. This keeps grouped tests
# together instead of splitting them up, which tends to get "stuck" and not finish
# the testing(have to use ^C to exit). Has no effect when tests are not parallelized.
"--dist=loadscope"
]

# The 'hatch test ...' command has the built-in scripts that define its invocation.
# Override these scripts so coverage works as expected.
#
# In particular, the 'coverage run -m pytest ...' command does not work correctly.
# In CI, it was not producing the subprocess-enabled coverage files, even though it
# worked locally (there should have been 4 files, but only 1 was produced, and it had
# no data). Using the pytest-cov plugin does seem to produce these files, and the
# missing-lines display format is also correct. Since it handles the internal
# combine/report commands, set those scripts below to do nothing (or CI will report
# fake errors).
[tool.hatch.envs.hatch-test.scripts]
# The HATCH_TEST_ARGS environment variable is how the `test` command's flags are
# translated and internally populated without affecting the user's arguments. This is
# also the way that "extra arguments" are passed. Leave it there
run = "pytest{env:HATCH_TEST_ARGS:} {args}"
# The original 'run-cov' is below; this is overridden to produce coverage properly.
#run-cov = "coverage run -m pytest{env:HATCH_TEST_ARGS:} {args}"
# Notes for this command line: using --cov=synapse_token_authenticator instead of having
# that directory in the 'coverage.run' config above actually produces the correct
# coverage files (the ones that were missing, as mentioned above). The 'cov-report'
# options both produce useful output (one for the codecov file and the other displays
# the missing coverage lines).
run-cov = "pytest{env:HATCH_TEST_ARGS:} --cov=synapse_token_authenticator --cov-report=lcov:lcov.info --cov-report=term-missing --cov-config=pyproject.toml {args}"

# As mentioned above, the defaults for these scripts are commented out as they will
# produce fake errors in CI. They attempt to run but the result of those commands
# already exists. This raises error codes and fails the test.
#cov-combine = "coverage combine"
#cov-report = "coverage report"
cov-combine = ""
cov-report = ""
4 changes: 2 additions & 2 deletions synapse_token_authenticator/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
from synapse_token_authenticator.token_authenticator import (
TokenAuthenticator, # noqa: F401
from synapse_token_authenticator.token_authenticator import ( # noqa: F401
TokenAuthenticator,
)
5 changes: 3 additions & 2 deletions synapse_token_authenticator/claims_validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@
more complicated, we better switch to another engine/DSL
"""

import re
from dataclasses import dataclass
from typing import List, Optional, Any, TypeAlias, Union
from typing import Any, List, Optional, TypeAlias, Union

from synapse_token_authenticator.utils import get_path_in_dict
import re

Validator: TypeAlias = Union[
"Exist",
Expand Down
10 changes: 6 additions & 4 deletions synapse_token_authenticator/config.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import os
from dataclasses import dataclass, field
from typing import List, Literal, Union, TypeAlias, Any
from typing import Any, List, Literal, TypeAlias, Union

from jwcrypto.jwk import JWK, JWKSet

from synapse_token_authenticator.claims_validator import (
parse_validator,
Validator,
Exist,
Validator,
parse_validator,
)
from synapse_token_authenticator.utils import bearer_auth, basic_auth
from synapse_token_authenticator.utils import basic_auth, bearer_auth


class TokenAuthenticatorConfig:
Expand Down
5 changes: 3 additions & 2 deletions synapse_token_authenticator/utils.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import json
from base64 import b64encode
from typing import Any, List, Optional
from urllib.parse import urljoin
from typing import List, Optional, Any
import json

from twisted.web import resource


Expand Down
5 changes: 3 additions & 2 deletions tests/test_epa.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,14 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

from copy import deepcopy
from unittest import mock

from jwcrypto import jwk

import tests.unittest as synapsetest

from . import ModuleApiTestCase, get_enc_jwk, get_jwe_token, get_jwk, get_jwt_token
from copy import deepcopy
from jwcrypto import jwk


def get_default_claims() -> dict:
Expand Down
7 changes: 4 additions & 3 deletions tests/test_oauth.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,14 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

from copy import deepcopy
from unittest import mock

from jwcrypto.jwk import JWKSet

import tests.unittest as synapsetest

from . import ModuleApiTestCase, get_jwt_token, get_jwk, mock_for_oauth
from copy import deepcopy
from jwcrypto.jwk import JWKSet
from . import ModuleApiTestCase, get_jwk, get_jwt_token, mock_for_oauth

default_claims = {
"urn:messaging:matrix:localpart": "alice",
Expand Down
4 changes: 2 additions & 2 deletions tests/test_sta_utils.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from synapse_token_authenticator.utils import (
all_list_elems_are_equal_return_the_elem,
get_path_in_dict,
validate_scopes,
if_not_none,
all_list_elems_are_equal_return_the_elem,
validate_scopes,
)


Expand Down
1 change: 1 addition & 0 deletions tests/test_utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"""
Utilities for running the unit tests
"""

import json
import sys
import warnings
Expand Down
3 changes: 2 additions & 1 deletion tests/test_validators.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from synapse_token_authenticator.claims_validator import parse_validator
from pytest import fixture

from synapse_token_authenticator.claims_validator import parse_validator


def test_validator_exists():
assert parse_validator(["exist"]).validate(None)
Expand Down
Loading