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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: ursaproxy
3
- Version: 0.1.2
3
+ Version: 0.2.0
4
4
  Summary: A Bearblog-to-Gemini proxy showcasing Xitzin
5
5
  Author: Alan Velasco
6
6
  Author-email: Alan Velasco <ursaproxy@alanbato.com>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "ursaproxy"
3
- version = "0.1.2"
3
+ version = "0.2.0"
4
4
  description = "A Bearblog-to-Gemini proxy showcasing Xitzin"
5
5
  readme = "README.md"
6
6
  authors = [
@@ -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