Skip to content

Commit 19677fa

Browse files
authored
Merge pull request #10 from signnow/feat/docker-build-and-config-oneof
feat: add version file and update config with OneOf validation
2 parents e62d479 + c4a9117 commit 19677fa

File tree

5 files changed

+2031
-23
lines changed

5 files changed

+2031
-23
lines changed

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,4 @@ packages = [
7979
"src/sn_mcp_server",
8080
"src/signnow_client",
8181
]
82+
sources = ["src"]

src/signnow_client/config.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,70 +36,70 @@ class SignNowConfig(BaseSettings):
3636

3737
@field_validator("api_base", mode="before")
3838
@classmethod
39-
def validate_api_base(cls, v):
39+
def validate_api_base(cls: type["SignNowConfig"], v: str | None) -> AnyHttpUrl:
4040
"""Handle empty string for api_base"""
4141
if v == "" or v is None:
4242
return AnyHttpUrl("https://api.signnow.com")
4343
return v
4444

4545
@field_validator("app_base", mode="before")
4646
@classmethod
47-
def validate_app_base(cls, v):
47+
def validate_app_base(cls: type["SignNowConfig"], v: str | None) -> AnyHttpUrl:
4848
"""Handle empty string for app_base"""
4949
if v == "" or v is None:
5050
return AnyHttpUrl("https://app.signnow.com")
5151
return v
5252

5353
@field_validator("client_id", mode="before")
5454
@classmethod
55-
def validate_client_id(cls, v):
55+
def validate_client_id(cls: type["SignNowConfig"], v: str | None) -> str | None:
5656
"""Handle empty string for client_id"""
5757
if v == "":
5858
return None
5959
return v
6060

6161
@field_validator("client_secret", mode="before")
6262
@classmethod
63-
def validate_client_secret(cls, v):
63+
def validate_client_secret(cls: type["SignNowConfig"], v: str | None) -> str | None:
6464
"""Handle empty string for client_secret"""
6565
if v == "":
6666
return None
6767
return v
6868

6969
@field_validator("basic_token", mode="before")
7070
@classmethod
71-
def validate_basic_token(cls, v):
71+
def validate_basic_token(cls: type["SignNowConfig"], v: str | None) -> str | None:
7272
"""Handle empty string for basic_token"""
7373
if v == "":
7474
return None
7575
return v
7676

7777
@field_validator("user_email", mode="before")
7878
@classmethod
79-
def validate_user_email(cls, v):
79+
def validate_user_email(cls: type["SignNowConfig"], v: str | None) -> str | None:
8080
"""Handle empty string for user_email"""
8181
if v == "":
8282
return None
8383
return v
8484

8585
@field_validator("password", mode="before")
8686
@classmethod
87-
def validate_password(cls, v):
87+
def validate_password(cls: type["SignNowConfig"], v: str | None) -> str | None:
8888
"""Handle empty string for password"""
8989
if v == "":
9090
return None
9191
return v
9292

9393
@field_validator("default_scope", mode="before")
9494
@classmethod
95-
def validate_default_scope(cls, v):
95+
def validate_default_scope(cls: type["SignNowConfig"], v: str | None) -> str:
9696
"""Handle empty string for default_scope"""
9797
if v == "" or v is None:
9898
return "*"
9999
return v
100100

101101
@model_validator(mode="after")
102-
def validate_one_of_credentials(self) -> "SignNowConfig":
102+
def validate_one_of_credentials(self: "SignNowConfig") -> "SignNowConfig":
103103
"""Ensure that either password grant set or client credentials set is fully provided.
104104
105105
Option A (password grant): SIGNNOW_USER_EMAIL, SIGNNOW_PASSWORD, SIGNNOW_API_BASIC_TOKEN

src/sn_mcp_server/_version.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# file generated by setuptools-scm
2+
# don't change, don't track in version control
3+
4+
__all__ = [
5+
"__version__",
6+
"__version_tuple__",
7+
"version",
8+
"version_tuple",
9+
"__commit_id__",
10+
"commit_id",
11+
]
12+
13+
TYPE_CHECKING = False
14+
if TYPE_CHECKING:
15+
from typing import Union
16+
17+
VERSION_TUPLE = tuple[int | str, ...]
18+
COMMIT_ID = str | None
19+
else:
20+
VERSION_TUPLE = object
21+
COMMIT_ID = object
22+
23+
version: str
24+
__version__: str
25+
__version_tuple__: VERSION_TUPLE
26+
version_tuple: VERSION_TUPLE
27+
commit_id: COMMIT_ID
28+
__commit_id__: COMMIT_ID
29+
30+
__version__ = version = "0.1.5.dev16+g4f99697d7.d20251007"
31+
__version_tuple__ = version_tuple = (0, 1, 5, "dev16", "g4f99697d7.d20251007")
32+
33+
__commit_id__ = commit_id = None

src/sn_mcp_server/config.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,31 +23,31 @@ class Settings(BaseSettings):
2323

2424
@field_validator("oauth_issuer", mode="before")
2525
@classmethod
26-
def validate_oauth_issuer(cls, v):
26+
def validate_oauth_issuer(cls: type["Settings"], v: str | None) -> AnyHttpUrl:
2727
"""Handle empty string for oauth_issuer"""
2828
if v == "" or v is None:
2929
return AnyHttpUrl("http://localhost:8000")
3030
return v
3131

3232
@field_validator("access_ttl", mode="before")
3333
@classmethod
34-
def validate_access_ttl(cls, v):
34+
def validate_access_ttl(cls: type["Settings"], v: str | None) -> int:
3535
"""Handle empty string for access_ttl"""
3636
if v == "" or v is None:
3737
return 3600
3838
return v
3939

4040
@field_validator("refresh_ttl", mode="before")
4141
@classmethod
42-
def validate_refresh_ttl(cls, v):
42+
def validate_refresh_ttl(cls: type["Settings"], v: str | None) -> int:
4343
"""Handle empty string for refresh_ttl"""
4444
if v == "" or v is None:
4545
return 2592000
4646
return v
4747

4848
@field_validator("allowed_redirects")
4949
@classmethod
50-
def validate_redirects(cls, v: str) -> str:
50+
def validate_redirects(cls: type["Settings"], v: str) -> str:
5151
"""Validate that all redirect URIs are valid"""
5252
if not v:
5353
return v
@@ -57,29 +57,29 @@ def validate_redirects(cls, v: str) -> str:
5757
try:
5858
AnyHttpUrl(uri)
5959
except ValueError as e:
60-
raise ValueError(f"Invalid redirect URI '{uri}': {e}")
60+
raise ValueError(f"Invalid redirect URI '{uri}': {e}") from e
6161
return v
6262

6363
@property
64-
def allowed_redirects_list(self) -> list[str]:
64+
def allowed_redirects_list(self: "Settings") -> list[str]:
6565
"""Convert comma-separated redirects string to list"""
6666
return [uri.strip() for uri in self.allowed_redirects.split(",") if uri.strip()]
6767

6868
@property
69-
def effective_resource_http_url(self) -> str:
69+
def effective_resource_http_url(self: "Settings") -> str:
7070
"""Get resource HTTP URL, auto-generated from oauth_issuer"""
7171
if not self.oauth_issuer:
7272
raise ValueError("OAUTH_ISSUER is required to generate resource URLs")
7373
return f"{str(self.oauth_issuer).rstrip('/')}/mcp"
7474

7575
@property
76-
def effective_resource_sse_url(self) -> str:
76+
def effective_resource_sse_url(self: "Settings") -> str:
7777
"""Get resource SSE URL, auto-generated from oauth_issuer"""
7878
if not self.oauth_issuer:
7979
raise ValueError("OAUTH_ISSUER is required to generate resource URLs")
8080
return f"{str(self.oauth_issuer).rstrip('/')}/sse"
8181

82-
def get_rsa_private_key(self) -> rsa.RSAPrivateKey:
82+
def get_rsa_private_key(self: "Settings") -> rsa.RSAPrivateKey:
8383
"""Get RSA private key - either from config or generate new one"""
8484
if self.oauth_rsa_private_pem:
8585
try:

0 commit comments

Comments
 (0)