ursaproxy 0.1.2__tar.gz → 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ursaproxy-0.1.2 → ursaproxy-0.2.0}/PKG-INFO +1 -1
- {ursaproxy-0.1.2 → ursaproxy-0.2.0}/pyproject.toml +1 -1
- ursaproxy-0.2.0/src/ursaproxy/config.py +98 -0
- ursaproxy-0.1.2/src/ursaproxy/config.py +0 -39
- {ursaproxy-0.1.2 → ursaproxy-0.2.0}/README.md +0 -0
- {ursaproxy-0.1.2 → ursaproxy-0.2.0}/src/ursaproxy/__init__.py +0 -0
- {ursaproxy-0.1.2 → ursaproxy-0.2.0}/src/ursaproxy/cache.py +0 -0
- {ursaproxy-0.1.2 → ursaproxy-0.2.0}/src/ursaproxy/converter.py +0 -0
- {ursaproxy-0.1.2 → ursaproxy-0.2.0}/src/ursaproxy/fetcher.py +0 -0
- {ursaproxy-0.1.2 → ursaproxy-0.2.0}/src/ursaproxy/templates/about.gmi +0 -0
- {ursaproxy-0.1.2 → ursaproxy-0.2.0}/src/ursaproxy/templates/feed.xml +0 -0
- {ursaproxy-0.1.2 → ursaproxy-0.2.0}/src/ursaproxy/templates/index.gmi +0 -0
- {ursaproxy-0.1.2 → ursaproxy-0.2.0}/src/ursaproxy/templates/post.gmi +0 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
from pydantic import field_validator
|
|
2
|
+
from pydantic_settings import (
|
|
3
|
+
BaseSettings,
|
|
4
|
+
PydanticBaseSettingsSource,
|
|
5
|
+
SettingsConfigDict,
|
|
6
|
+
TomlConfigSettingsSource,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Settings(BaseSettings):
|
|
11
|
+
"""Configuration from ursaproxy.toml file and/or environment variables.
|
|
12
|
+
|
|
13
|
+
Settings are loaded in this priority order (highest to lowest):
|
|
14
|
+
1. Environment variables (e.g., BEARBLOG_URL)
|
|
15
|
+
2. ursaproxy.toml file in current directory
|
|
16
|
+
3. Default values
|
|
17
|
+
|
|
18
|
+
Example ursaproxy.toml:
|
|
19
|
+
bearblog_url = "https://example.bearblog.dev"
|
|
20
|
+
blog_name = "My Blog"
|
|
21
|
+
pages = { about = "About Me", now = "Now" }
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
model_config = SettingsConfigDict(
|
|
25
|
+
toml_file="ursaproxy.toml",
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
# Required: the Bearblog URL to proxy
|
|
29
|
+
bearblog_url: str
|
|
30
|
+
blog_name: str
|
|
31
|
+
|
|
32
|
+
cache_ttl_feed: int = 300 # 5 minutes
|
|
33
|
+
cache_ttl_post: int = 1800 # 30 minutes
|
|
34
|
+
|
|
35
|
+
# Static pages (slug -> title) - pages not in RSS feed
|
|
36
|
+
# Override via PAGES='{"about": "About Me", "now": "Now"}'
|
|
37
|
+
pages: dict[str, str] = {}
|
|
38
|
+
|
|
39
|
+
# Gemini capsule hostname (for feed URLs)
|
|
40
|
+
# e.g., "gemini.example.com" -> gemini://gemini.example.com/post/...
|
|
41
|
+
gemini_host: str | None = None
|
|
42
|
+
|
|
43
|
+
# Server settings
|
|
44
|
+
host: str = "localhost"
|
|
45
|
+
port: int = 1965
|
|
46
|
+
cert_file: str | None = None
|
|
47
|
+
key_file: str | None = None
|
|
48
|
+
|
|
49
|
+
@classmethod
|
|
50
|
+
def settings_customise_sources(
|
|
51
|
+
cls,
|
|
52
|
+
settings_cls: type[BaseSettings],
|
|
53
|
+
init_settings: PydanticBaseSettingsSource,
|
|
54
|
+
env_settings: PydanticBaseSettingsSource,
|
|
55
|
+
dotenv_settings: PydanticBaseSettingsSource,
|
|
56
|
+
file_secret_settings: PydanticBaseSettingsSource,
|
|
57
|
+
) -> tuple[PydanticBaseSettingsSource, ...]:
|
|
58
|
+
"""Configure settings sources with TOML file support.
|
|
59
|
+
|
|
60
|
+
Priority (highest to lowest): env vars -> TOML file -> defaults.
|
|
61
|
+
"""
|
|
62
|
+
return (
|
|
63
|
+
env_settings,
|
|
64
|
+
TomlConfigSettingsSource(settings_cls),
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
@field_validator("bearblog_url")
|
|
68
|
+
@classmethod
|
|
69
|
+
def normalize_url(cls, v: str) -> str:
|
|
70
|
+
"""Remove trailing slash to prevent double slashes in URLs."""
|
|
71
|
+
v = v.rstrip("/")
|
|
72
|
+
if not v.startswith(("http://", "https://")):
|
|
73
|
+
raise ValueError("bearblog_url must start with http:// or https://")
|
|
74
|
+
return v
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _load_settings() -> Settings:
|
|
78
|
+
"""Load settings, handling missing TOML file gracefully."""
|
|
79
|
+
try:
|
|
80
|
+
return Settings() # type: ignore[call-arg]
|
|
81
|
+
except FileNotFoundError:
|
|
82
|
+
# No TOML file - disable TOML source and rely on env vars only
|
|
83
|
+
class _EnvOnlySettings(Settings):
|
|
84
|
+
@classmethod
|
|
85
|
+
def settings_customise_sources(
|
|
86
|
+
cls,
|
|
87
|
+
settings_cls: type[BaseSettings],
|
|
88
|
+
init_settings: PydanticBaseSettingsSource,
|
|
89
|
+
env_settings: PydanticBaseSettingsSource,
|
|
90
|
+
dotenv_settings: PydanticBaseSettingsSource,
|
|
91
|
+
file_secret_settings: PydanticBaseSettingsSource,
|
|
92
|
+
) -> tuple[PydanticBaseSettingsSource, ...]:
|
|
93
|
+
return (env_settings,)
|
|
94
|
+
|
|
95
|
+
return _EnvOnlySettings() # type: ignore[call-arg]
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
settings = _load_settings()
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
from pydantic import field_validator
|
|
2
|
-
from pydantic_settings import BaseSettings
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
class Settings(BaseSettings):
|
|
6
|
-
"""Configuration from environment variables."""
|
|
7
|
-
|
|
8
|
-
# Required: the Bearblog URL to proxy
|
|
9
|
-
bearblog_url: str
|
|
10
|
-
blog_name: str
|
|
11
|
-
|
|
12
|
-
cache_ttl_feed: int = 300 # 5 minutes
|
|
13
|
-
cache_ttl_post: int = 1800 # 30 minutes
|
|
14
|
-
|
|
15
|
-
# Static pages (slug -> title) - pages not in RSS feed
|
|
16
|
-
# Override via PAGES='{"about": "About Me", "now": "Now"}'
|
|
17
|
-
pages: dict[str, str] = {}
|
|
18
|
-
|
|
19
|
-
# Gemini capsule hostname (for feed URLs)
|
|
20
|
-
# e.g., "gemini.example.com" -> gemini://gemini.example.com/post/...
|
|
21
|
-
gemini_host: str | None = None
|
|
22
|
-
|
|
23
|
-
# Server settings
|
|
24
|
-
host: str = "localhost"
|
|
25
|
-
port: int = 1965
|
|
26
|
-
cert_file: str | None = None
|
|
27
|
-
key_file: str | None = None
|
|
28
|
-
|
|
29
|
-
@field_validator("bearblog_url")
|
|
30
|
-
@classmethod
|
|
31
|
-
def normalize_url(cls, v: str) -> str:
|
|
32
|
-
"""Remove trailing slash to prevent double slashes in URLs."""
|
|
33
|
-
v = v.rstrip("/")
|
|
34
|
-
if not v.startswith(("http://", "https://")):
|
|
35
|
-
raise ValueError("bearblog_url must start with http:// or https://")
|
|
36
|
-
return v
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
settings = Settings() # type: ignore[call-arg] # pydantic-settings reads from env
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|