envproof 0.1.0__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.
@@ -0,0 +1,48 @@
1
+ # Contributing to envproof
2
+
3
+ Thanks for taking the time to contribute!
4
+
5
+ ## Getting started
6
+
7
+ ```bash
8
+ git clone https://github.com/CoderSufiyan/envguard.git
9
+ cd envguard
10
+ python3 -m venv .venv
11
+ source .venv/bin/activate
12
+ pip install -e ".[dev]"
13
+ ```
14
+
15
+ ## Running tests
16
+
17
+ ```bash
18
+ pytest
19
+ ```
20
+
21
+ All tests must pass before submitting a PR.
22
+
23
+ ## How to contribute
24
+
25
+ - **Bug fix** — open an issue first describing the bug, then submit a PR
26
+ - **New feature** — open an issue first so we can discuss before you build it
27
+ - **Docs improvement** — go ahead and submit a PR directly
28
+
29
+ ## What we welcome
30
+
31
+ - New supported types (e.g. `dict`, `Path`, `Enum`)
32
+ - Better error messages
33
+ - Framework integrations (FastAPI, Flask, Django startup hooks)
34
+ - Performance improvements
35
+ - More test coverage
36
+
37
+ ## Pull request checklist
38
+
39
+ - [ ] Tests added or updated
40
+ - [ ] All 28+ tests pass (`pytest`)
41
+ - [ ] Code follows existing style (no external formatter required)
42
+ - [ ] PR description explains what and why
43
+
44
+ ## Code style
45
+
46
+ - No external dependencies in `envguard/` — keep it zero-dep
47
+ - One function does one thing
48
+ - Clear variable names over comments
envproof-0.2.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sufiyan Khan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,195 @@
1
+ Metadata-Version: 2.4
2
+ Name: envproof
3
+ Version: 0.2.0
4
+ Summary: Validate environment variables at startup with typed, clear error messages. Zero dependencies.
5
+ Project-URL: Homepage, https://github.com/CoderSufiyan/envguard
6
+ Project-URL: Repository, https://github.com/CoderSufiyan/envguard
7
+ Project-URL: Issues, https://github.com/CoderSufiyan/envguard/issues
8
+ License: MIT
9
+ License-File: LICENSE
10
+ Keywords: config,dotenv,env,environment,settings,validation
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.8
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
+ Requires-Python: >=3.8
22
+ Description-Content-Type: text/markdown
23
+
24
+ # envproof
25
+
26
+ > Validate environment variables at startup with typed, clear error messages. Zero dependencies. Production-ready.
27
+
28
+ [![PyPI version](https://img.shields.io/pypi/v/envproof.svg)](https://pypi.org/project/envproof/)
29
+ [![Python versions](https://img.shields.io/pypi/pyversions/envproof.svg)](https://pypi.org/project/envproof/)
30
+ [![CI](https://github.com/CoderSufiyan/envguard/actions/workflows/ci.yml/badge.svg)](https://github.com/CoderSufiyan/envguard/actions)
31
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://github.com/CoderSufiyan/envguard/blob/main/LICENSE)
32
+ [![Open Source](https://img.shields.io/badge/Open%20Source-%E2%9D%A4-red)](https://github.com/CoderSufiyan/envguard)
33
+
34
+ ---
35
+
36
+ Every backend app reads environment variables. The standard way fails silently or crashes with a cryptic error deep inside your app at runtime:
37
+
38
+ ```python
39
+ # Crashes 10 minutes in, on an obscure code path
40
+ db = connect(os.environ["DATABASE_URL"]) # KeyError: DATABASE_URL
41
+
42
+ # PORT is a string — breaks math silently
43
+ port = os.environ["PORT"] # "8080", not 8080
44
+ ```
45
+
46
+ **envproof catches all of this at startup**, before your app serves a single request:
47
+
48
+ ```python
49
+ from envproof import EnvGuard
50
+
51
+ class Env(EnvGuard):
52
+ DATABASE_URL: str
53
+ PORT: int = 8080
54
+ DEBUG: bool = False
55
+ ALLOWED_HOSTS: list = []
56
+
57
+ env = Env()
58
+ print(env.PORT) # 8080 — already an int
59
+ ```
60
+
61
+ If anything is wrong, you get a clear error immediately:
62
+
63
+ ```
64
+ EnvProofError:
65
+ Missing required environment variables:
66
+ - DATABASE_URL (str): not set
67
+
68
+ Invalid environment variable values:
69
+ - PORT: expected int, got 'abc'
70
+ - DEBUG: expected bool, got 'maybe'
71
+ ```
72
+
73
+ All errors reported at once — not one at a time.
74
+
75
+ ---
76
+
77
+ ## Install
78
+
79
+ ```bash
80
+ pip install envproof
81
+ ```
82
+
83
+ ---
84
+
85
+ ## Usage
86
+
87
+ ### Recommended: one `env.py` file in your project
88
+
89
+ ```python
90
+ # env.py
91
+ from envproof import EnvGuard
92
+
93
+ class Env(EnvGuard):
94
+ # Required — raises EnvProofError at startup if not set
95
+ DATABASE_URL: str
96
+ SECRET_KEY: str
97
+ API_KEY: str
98
+
99
+ # Optional — uses default if not set
100
+ PORT: int = 8080
101
+ DEBUG: bool = False
102
+ LOG_LEVEL: str = "INFO"
103
+ ALLOWED_HOSTS: list = []
104
+
105
+ env = Env()
106
+ ```
107
+
108
+ Then import `env` anywhere in your app:
109
+
110
+ ```python
111
+ # app.py
112
+ from env import env
113
+
114
+ app.run(port=env.PORT, debug=env.DEBUG)
115
+ ```
116
+
117
+ ```python
118
+ # database.py
119
+ from env import env
120
+
121
+ db = connect(env.DATABASE_URL)
122
+ ```
123
+
124
+ ### One-liner style (no subclass needed)
125
+
126
+ ```python
127
+ from envproof import guard
128
+
129
+ env = guard(DATABASE_URL=str, PORT=int, DEBUG=bool)
130
+ print(env.DATABASE_URL)
131
+ ```
132
+
133
+ ### Works great with python-dotenv
134
+
135
+ ```python
136
+ from dotenv import load_dotenv
137
+ load_dotenv() # loads .env file into environment
138
+
139
+ from env import env # envproof validates it
140
+ ```
141
+
142
+ ---
143
+
144
+ ## Supported types
145
+
146
+ | Type | Example env value | Python value |
147
+ |---------|--------------------------------|---------------------|
148
+ | `str` | `hello` | `"hello"` |
149
+ | `int` | `8080` | `8080` |
150
+ | `float` | `3.14` | `3.14` |
151
+ | `bool` | `true`, `1`, `yes`, `on` | `True` |
152
+ | `bool` | `false`, `0`, `no`, `off` | `False` |
153
+ | `list` | `localhost,example.com` | `["localhost", "example.com"]` |
154
+
155
+ ---
156
+
157
+ ## Why envproof?
158
+
159
+ | | envproof | `os.environ` | `pydantic-settings` |
160
+ |---|---|---|---|
161
+ | Type coercion | Yes | No | Yes |
162
+ | Clear error messages | Yes | No | Partial |
163
+ | Zero dependencies | Yes | Yes | No (~2MB) |
164
+ | Fail fast at startup | Yes | No | Yes |
165
+ | Works anywhere | Yes | Yes | Pydantic only |
166
+
167
+ **vs `pydantic-settings`:** great library, but pulls in Pydantic (~2MB). envproof is a single file with zero dependencies — ideal for serverless functions, lightweight containers, or any project that doesn't already use Pydantic.
168
+
169
+ ---
170
+
171
+ ## Production use
172
+
173
+ envproof is designed for production. The "fail fast" pattern — crashing at startup rather than during a request — is standard practice in production backend systems. Your app either starts correctly or doesn't start at all. No surprises mid-flight.
174
+
175
+ Used in: FastAPI apps, Flask apps, Django projects, CLI tools, serverless functions, Docker containers.
176
+
177
+ ---
178
+
179
+ ## Open Source
180
+
181
+ envproof is MIT licensed and open for contributions. See [CONTRIBUTING.md](CONTRIBUTING.md) for how to get started.
182
+
183
+ Things we'd love help with:
184
+ - New types: `dict`, `Path`, `Enum`
185
+ - Framework integrations (FastAPI lifespan hooks, Django `AppConfig.ready()`)
186
+ - Better error formatting
187
+ - More test coverage
188
+
189
+ [Open an issue](https://github.com/CoderSufiyan/envguard/issues) or submit a PR — all contributions welcome.
190
+
191
+ ---
192
+
193
+ ## License
194
+
195
+ [MIT](LICENSE) © Sufiyan Khan
@@ -0,0 +1,172 @@
1
+ # envproof
2
+
3
+ > Validate environment variables at startup with typed, clear error messages. Zero dependencies. Production-ready.
4
+
5
+ [![PyPI version](https://img.shields.io/pypi/v/envproof.svg)](https://pypi.org/project/envproof/)
6
+ [![Python versions](https://img.shields.io/pypi/pyversions/envproof.svg)](https://pypi.org/project/envproof/)
7
+ [![CI](https://github.com/CoderSufiyan/envguard/actions/workflows/ci.yml/badge.svg)](https://github.com/CoderSufiyan/envguard/actions)
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://github.com/CoderSufiyan/envguard/blob/main/LICENSE)
9
+ [![Open Source](https://img.shields.io/badge/Open%20Source-%E2%9D%A4-red)](https://github.com/CoderSufiyan/envguard)
10
+
11
+ ---
12
+
13
+ Every backend app reads environment variables. The standard way fails silently or crashes with a cryptic error deep inside your app at runtime:
14
+
15
+ ```python
16
+ # Crashes 10 minutes in, on an obscure code path
17
+ db = connect(os.environ["DATABASE_URL"]) # KeyError: DATABASE_URL
18
+
19
+ # PORT is a string — breaks math silently
20
+ port = os.environ["PORT"] # "8080", not 8080
21
+ ```
22
+
23
+ **envproof catches all of this at startup**, before your app serves a single request:
24
+
25
+ ```python
26
+ from envproof import EnvGuard
27
+
28
+ class Env(EnvGuard):
29
+ DATABASE_URL: str
30
+ PORT: int = 8080
31
+ DEBUG: bool = False
32
+ ALLOWED_HOSTS: list = []
33
+
34
+ env = Env()
35
+ print(env.PORT) # 8080 — already an int
36
+ ```
37
+
38
+ If anything is wrong, you get a clear error immediately:
39
+
40
+ ```
41
+ EnvProofError:
42
+ Missing required environment variables:
43
+ - DATABASE_URL (str): not set
44
+
45
+ Invalid environment variable values:
46
+ - PORT: expected int, got 'abc'
47
+ - DEBUG: expected bool, got 'maybe'
48
+ ```
49
+
50
+ All errors reported at once — not one at a time.
51
+
52
+ ---
53
+
54
+ ## Install
55
+
56
+ ```bash
57
+ pip install envproof
58
+ ```
59
+
60
+ ---
61
+
62
+ ## Usage
63
+
64
+ ### Recommended: one `env.py` file in your project
65
+
66
+ ```python
67
+ # env.py
68
+ from envproof import EnvGuard
69
+
70
+ class Env(EnvGuard):
71
+ # Required — raises EnvProofError at startup if not set
72
+ DATABASE_URL: str
73
+ SECRET_KEY: str
74
+ API_KEY: str
75
+
76
+ # Optional — uses default if not set
77
+ PORT: int = 8080
78
+ DEBUG: bool = False
79
+ LOG_LEVEL: str = "INFO"
80
+ ALLOWED_HOSTS: list = []
81
+
82
+ env = Env()
83
+ ```
84
+
85
+ Then import `env` anywhere in your app:
86
+
87
+ ```python
88
+ # app.py
89
+ from env import env
90
+
91
+ app.run(port=env.PORT, debug=env.DEBUG)
92
+ ```
93
+
94
+ ```python
95
+ # database.py
96
+ from env import env
97
+
98
+ db = connect(env.DATABASE_URL)
99
+ ```
100
+
101
+ ### One-liner style (no subclass needed)
102
+
103
+ ```python
104
+ from envproof import guard
105
+
106
+ env = guard(DATABASE_URL=str, PORT=int, DEBUG=bool)
107
+ print(env.DATABASE_URL)
108
+ ```
109
+
110
+ ### Works great with python-dotenv
111
+
112
+ ```python
113
+ from dotenv import load_dotenv
114
+ load_dotenv() # loads .env file into environment
115
+
116
+ from env import env # envproof validates it
117
+ ```
118
+
119
+ ---
120
+
121
+ ## Supported types
122
+
123
+ | Type | Example env value | Python value |
124
+ |---------|--------------------------------|---------------------|
125
+ | `str` | `hello` | `"hello"` |
126
+ | `int` | `8080` | `8080` |
127
+ | `float` | `3.14` | `3.14` |
128
+ | `bool` | `true`, `1`, `yes`, `on` | `True` |
129
+ | `bool` | `false`, `0`, `no`, `off` | `False` |
130
+ | `list` | `localhost,example.com` | `["localhost", "example.com"]` |
131
+
132
+ ---
133
+
134
+ ## Why envproof?
135
+
136
+ | | envproof | `os.environ` | `pydantic-settings` |
137
+ |---|---|---|---|
138
+ | Type coercion | Yes | No | Yes |
139
+ | Clear error messages | Yes | No | Partial |
140
+ | Zero dependencies | Yes | Yes | No (~2MB) |
141
+ | Fail fast at startup | Yes | No | Yes |
142
+ | Works anywhere | Yes | Yes | Pydantic only |
143
+
144
+ **vs `pydantic-settings`:** great library, but pulls in Pydantic (~2MB). envproof is a single file with zero dependencies — ideal for serverless functions, lightweight containers, or any project that doesn't already use Pydantic.
145
+
146
+ ---
147
+
148
+ ## Production use
149
+
150
+ envproof is designed for production. The "fail fast" pattern — crashing at startup rather than during a request — is standard practice in production backend systems. Your app either starts correctly or doesn't start at all. No surprises mid-flight.
151
+
152
+ Used in: FastAPI apps, Flask apps, Django projects, CLI tools, serverless functions, Docker containers.
153
+
154
+ ---
155
+
156
+ ## Open Source
157
+
158
+ envproof is MIT licensed and open for contributions. See [CONTRIBUTING.md](CONTRIBUTING.md) for how to get started.
159
+
160
+ Things we'd love help with:
161
+ - New types: `dict`, `Path`, `Enum`
162
+ - Framework integrations (FastAPI lifespan hooks, Django `AppConfig.ready()`)
163
+ - Better error formatting
164
+ - More test coverage
165
+
166
+ [Open an issue](https://github.com/CoderSufiyan/envguard/issues) or submit a PR — all contributions welcome.
167
+
168
+ ---
169
+
170
+ ## License
171
+
172
+ [MIT](LICENSE) © Sufiyan Khan
@@ -0,0 +1,4 @@
1
+ from .core import EnvProof, EnvProofError, guard
2
+
3
+ __all__ = ["EnvProof", "EnvProofError", "guard"]
4
+ __version__ = "0.2.0"
@@ -4,11 +4,11 @@ from typing import Any, get_type_hints
4
4
  _MISSING = object()
5
5
 
6
6
 
7
- class EnvGuardError(Exception):
7
+ class EnvProofError(Exception):
8
8
  pass
9
9
 
10
10
 
11
- class EnvGuard:
11
+ class EnvProof:
12
12
  """
13
13
  Subclass this and declare your env vars as type-annotated class attributes.
14
14
 
@@ -54,7 +54,7 @@ class EnvGuard:
54
54
  errors.append(f" - {name}: expected {type_name}, got '{raw}'")
55
55
 
56
56
  if errors:
57
- raise EnvGuardError("\n" + "\n".join(errors))
57
+ raise EnvProofError("\n" + "\n".join(errors))
58
58
 
59
59
 
60
60
  def _coerce(value: str, type_: type) -> Any:
@@ -77,7 +77,7 @@ def guard(**schema) -> Any:
77
77
  print(env.DATABASE_URL)
78
78
  """
79
79
 
80
- class _Env(EnvGuard):
80
+ class _Env(EnvProof):
81
81
  pass
82
82
 
83
83
  _Env.__annotations__ = schema
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "envproof"
7
- version = "0.1.0"
7
+ version = "0.2.0"
8
8
  description = "Validate environment variables at startup with typed, clear error messages. Zero dependencies."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.8"
@@ -30,7 +30,7 @@ Repository = "https://github.com/CoderSufiyan/envguard"
30
30
  Issues = "https://github.com/CoderSufiyan/envguard/issues"
31
31
 
32
32
  [tool.hatch.build.targets.wheel]
33
- packages = ["envguard"]
33
+ packages = ["envproof"]
34
34
 
35
35
  [tool.pytest.ini_options]
36
36
  testpaths = ["tests"]
@@ -1,6 +1,6 @@
1
1
  import os
2
2
  import pytest
3
- from envguard import EnvGuard, EnvGuardError, guard
3
+ from envproof import EnvProof, EnvProofError, guard
4
4
 
5
5
 
6
6
  def set_env(**kwargs):
@@ -13,13 +13,13 @@ def clear_env(*keys):
13
13
  os.environ.pop(k, None)
14
14
 
15
15
 
16
- # --- EnvGuard subclass style ---
16
+ # --- EnvProof subclass style ---
17
17
 
18
18
  class TestRequired:
19
19
  def test_loads_required_str(self):
20
20
  set_env(APP_NAME="myapp")
21
21
 
22
- class Env(EnvGuard):
22
+ class Env(EnvProof):
23
23
  APP_NAME: str
24
24
 
25
25
  env = Env()
@@ -29,7 +29,7 @@ class TestRequired:
29
29
  def test_loads_required_int(self):
30
30
  set_env(PORT="9000")
31
31
 
32
- class Env(EnvGuard):
32
+ class Env(EnvProof):
33
33
  PORT: int
34
34
 
35
35
  env = Env()
@@ -39,7 +39,7 @@ class TestRequired:
39
39
  def test_loads_required_float(self):
40
40
  set_env(RATE="3.14")
41
41
 
42
- class Env(EnvGuard):
42
+ class Env(EnvProof):
43
43
  RATE: float
44
44
 
45
45
  env = Env()
@@ -49,10 +49,10 @@ class TestRequired:
49
49
  def test_raises_on_missing_required(self):
50
50
  clear_env("DATABASE_URL")
51
51
 
52
- class Env(EnvGuard):
52
+ class Env(EnvProof):
53
53
  DATABASE_URL: str
54
54
 
55
- with pytest.raises(EnvGuardError) as exc:
55
+ with pytest.raises(EnvProofError) as exc:
56
56
  Env()
57
57
  assert "DATABASE_URL" in str(exc.value)
58
58
  assert "Missing" in str(exc.value)
@@ -60,11 +60,11 @@ class TestRequired:
60
60
  def test_raises_on_multiple_missing(self):
61
61
  clear_env("DB_URL", "API_KEY")
62
62
 
63
- class Env(EnvGuard):
63
+ class Env(EnvProof):
64
64
  DB_URL: str
65
65
  API_KEY: str
66
66
 
67
- with pytest.raises(EnvGuardError) as exc:
67
+ with pytest.raises(EnvProofError) as exc:
68
68
  Env()
69
69
  assert "DB_URL" in str(exc.value)
70
70
  assert "API_KEY" in str(exc.value)
@@ -74,7 +74,7 @@ class TestOptional:
74
74
  def test_uses_default_when_not_set(self):
75
75
  clear_env("PORT")
76
76
 
77
- class Env(EnvGuard):
77
+ class Env(EnvProof):
78
78
  PORT: int = 8080
79
79
 
80
80
  env = Env()
@@ -83,7 +83,7 @@ class TestOptional:
83
83
  def test_overrides_default_when_set(self):
84
84
  set_env(PORT="9000")
85
85
 
86
- class Env(EnvGuard):
86
+ class Env(EnvProof):
87
87
  PORT: int = 8080
88
88
 
89
89
  env = Env()
@@ -93,7 +93,7 @@ class TestOptional:
93
93
  def test_optional_str_default(self):
94
94
  clear_env("LOG_LEVEL")
95
95
 
96
- class Env(EnvGuard):
96
+ class Env(EnvProof):
97
97
  LOG_LEVEL: str = "INFO"
98
98
 
99
99
  env = Env()
@@ -105,7 +105,7 @@ class TestBoolCoercion:
105
105
  def test_truthy_values(self, value):
106
106
  set_env(DEBUG=value)
107
107
 
108
- class Env(EnvGuard):
108
+ class Env(EnvProof):
109
109
  DEBUG: bool
110
110
 
111
111
  assert Env().DEBUG is True
@@ -115,7 +115,7 @@ class TestBoolCoercion:
115
115
  def test_falsy_values(self, value):
116
116
  set_env(DEBUG=value)
117
117
 
118
- class Env(EnvGuard):
118
+ class Env(EnvProof):
119
119
  DEBUG: bool
120
120
 
121
121
  assert Env().DEBUG is False
@@ -124,10 +124,10 @@ class TestBoolCoercion:
124
124
  def test_invalid_bool_raises(self):
125
125
  set_env(DEBUG="maybe")
126
126
 
127
- class Env(EnvGuard):
127
+ class Env(EnvProof):
128
128
  DEBUG: bool
129
129
 
130
- with pytest.raises(EnvGuardError) as exc:
130
+ with pytest.raises(EnvProofError) as exc:
131
131
  Env()
132
132
  assert "DEBUG" in str(exc.value)
133
133
  clear_env("DEBUG")
@@ -137,7 +137,7 @@ class TestListCoercion:
137
137
  def test_comma_separated_list(self):
138
138
  set_env(ALLOWED_HOSTS="localhost,example.com,api.example.com")
139
139
 
140
- class Env(EnvGuard):
140
+ class Env(EnvProof):
141
141
  ALLOWED_HOSTS: list
142
142
 
143
143
  env = Env()
@@ -147,7 +147,7 @@ class TestListCoercion:
147
147
  def test_list_strips_whitespace(self):
148
148
  set_env(HOSTS=" a , b , c ")
149
149
 
150
- class Env(EnvGuard):
150
+ class Env(EnvProof):
151
151
  HOSTS: list
152
152
 
153
153
  env = Env()
@@ -159,10 +159,10 @@ class TestInvalidType:
159
159
  def test_invalid_int_raises(self):
160
160
  set_env(PORT="not-a-number")
161
161
 
162
- class Env(EnvGuard):
162
+ class Env(EnvProof):
163
163
  PORT: int
164
164
 
165
- with pytest.raises(EnvGuardError) as exc:
165
+ with pytest.raises(EnvProofError) as exc:
166
166
  Env()
167
167
  assert "PORT" in str(exc.value)
168
168
  assert "int" in str(exc.value)
@@ -171,11 +171,11 @@ class TestInvalidType:
171
171
  def test_reports_all_invalid_at_once(self):
172
172
  set_env(PORT="bad", WORKERS="also-bad")
173
173
 
174
- class Env(EnvGuard):
174
+ class Env(EnvProof):
175
175
  PORT: int
176
176
  WORKERS: int
177
177
 
178
- with pytest.raises(EnvGuardError) as exc:
178
+ with pytest.raises(EnvProofError) as exc:
179
179
  Env()
180
180
  assert "PORT" in str(exc.value)
181
181
  assert "WORKERS" in str(exc.value)
@@ -193,7 +193,7 @@ class TestGuard:
193
193
 
194
194
  def test_guard_raises_on_missing(self):
195
195
  clear_env("SECRET_KEY")
196
- with pytest.raises(EnvGuardError):
196
+ with pytest.raises(EnvProofError):
197
197
  guard(SECRET_KEY=str)
198
198
 
199
199
  def test_guard_int(self):
envproof-0.1.0/PKG-INFO DELETED
@@ -1,116 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: envproof
3
- Version: 0.1.0
4
- Summary: Validate environment variables at startup with typed, clear error messages. Zero dependencies.
5
- Project-URL: Homepage, https://github.com/CoderSufiyan/envguard
6
- Project-URL: Repository, https://github.com/CoderSufiyan/envguard
7
- Project-URL: Issues, https://github.com/CoderSufiyan/envguard/issues
8
- License: MIT
9
- Keywords: config,dotenv,env,environment,settings,validation
10
- Classifier: Intended Audience :: Developers
11
- Classifier: License :: OSI Approved :: MIT License
12
- Classifier: Operating System :: OS Independent
13
- Classifier: Programming Language :: Python :: 3
14
- Classifier: Programming Language :: Python :: 3.8
15
- Classifier: Programming Language :: Python :: 3.9
16
- Classifier: Programming Language :: Python :: 3.10
17
- Classifier: Programming Language :: Python :: 3.11
18
- Classifier: Programming Language :: Python :: 3.12
19
- Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
- Requires-Python: >=3.8
21
- Description-Content-Type: text/markdown
22
-
23
- # envguard
24
-
25
- Validate environment variables at startup with typed, clear error messages. Zero dependencies.
26
-
27
- ```python
28
- from envguard import EnvGuard
29
-
30
- class Env(EnvGuard):
31
- DATABASE_URL: str
32
- PORT: int = 8080
33
- DEBUG: bool = False
34
- ALLOWED_HOSTS: list = []
35
-
36
- env = Env()
37
- print(env.PORT) # 8080 (int, not string)
38
- ```
39
-
40
- If `DATABASE_URL` is missing, you get this instead of a cryptic `KeyError` somewhere deep in your app:
41
-
42
- ```
43
- EnvGuardError:
44
- Missing required environment variables:
45
- - DATABASE_URL (str): not set
46
- ```
47
-
48
- ## Install
49
-
50
- ```bash
51
- pip install envguard
52
- ```
53
-
54
- ## Usage
55
-
56
- ### Subclass style (recommended)
57
-
58
- ```python
59
- from envguard import EnvGuard
60
-
61
- class Env(EnvGuard):
62
- # Required — raises if not set
63
- DATABASE_URL: str
64
- API_KEY: str
65
-
66
- # Optional — uses default if not set
67
- PORT: int = 8080
68
- DEBUG: bool = False
69
- LOG_LEVEL: str = "INFO"
70
- ALLOWED_HOSTS: list = []
71
-
72
- env = Env()
73
- ```
74
-
75
- ### One-liner style
76
-
77
- ```python
78
- from envguard import guard
79
-
80
- env = guard(DATABASE_URL=str, PORT=int, DEBUG=bool)
81
- print(env.DATABASE_URL)
82
- ```
83
-
84
- ## Supported types
85
-
86
- | Type | Example env value | Python value |
87
- |---------|---------------------------|--------------------------|
88
- | `str` | `"hello"` | `"hello"` |
89
- | `int` | `"8080"` | `8080` |
90
- | `float` | `"3.14"` | `3.14` |
91
- | `bool` | `"true"`, `"1"`, `"yes"` | `True` |
92
- | `bool` | `"false"`, `"0"`, `"no"` | `False` |
93
- | `list` | `"a,b,c"` | `["a", "b", "c"]` |
94
-
95
- ## Error messages
96
-
97
- All errors are collected and reported together — you won't fix one missing var only to discover another:
98
-
99
- ```
100
- EnvGuardError:
101
- Missing required environment variables:
102
- - DATABASE_URL (str): not set
103
- - API_KEY (str): not set
104
-
105
- Invalid environment variable values:
106
- - PORT: expected int, got 'abc'
107
- - DEBUG: expected bool, got 'maybe'
108
- ```
109
-
110
- ## Why not pydantic-settings?
111
-
112
- `pydantic-settings` is great but pulls in Pydantic as a dependency (~2MB). `envguard` is a single file with zero dependencies — useful when you want validation without adding weight to your project.
113
-
114
- ## License
115
-
116
- MIT
envproof-0.1.0/README.md DELETED
@@ -1,94 +0,0 @@
1
- # envguard
2
-
3
- Validate environment variables at startup with typed, clear error messages. Zero dependencies.
4
-
5
- ```python
6
- from envguard import EnvGuard
7
-
8
- class Env(EnvGuard):
9
- DATABASE_URL: str
10
- PORT: int = 8080
11
- DEBUG: bool = False
12
- ALLOWED_HOSTS: list = []
13
-
14
- env = Env()
15
- print(env.PORT) # 8080 (int, not string)
16
- ```
17
-
18
- If `DATABASE_URL` is missing, you get this instead of a cryptic `KeyError` somewhere deep in your app:
19
-
20
- ```
21
- EnvGuardError:
22
- Missing required environment variables:
23
- - DATABASE_URL (str): not set
24
- ```
25
-
26
- ## Install
27
-
28
- ```bash
29
- pip install envguard
30
- ```
31
-
32
- ## Usage
33
-
34
- ### Subclass style (recommended)
35
-
36
- ```python
37
- from envguard import EnvGuard
38
-
39
- class Env(EnvGuard):
40
- # Required — raises if not set
41
- DATABASE_URL: str
42
- API_KEY: str
43
-
44
- # Optional — uses default if not set
45
- PORT: int = 8080
46
- DEBUG: bool = False
47
- LOG_LEVEL: str = "INFO"
48
- ALLOWED_HOSTS: list = []
49
-
50
- env = Env()
51
- ```
52
-
53
- ### One-liner style
54
-
55
- ```python
56
- from envguard import guard
57
-
58
- env = guard(DATABASE_URL=str, PORT=int, DEBUG=bool)
59
- print(env.DATABASE_URL)
60
- ```
61
-
62
- ## Supported types
63
-
64
- | Type | Example env value | Python value |
65
- |---------|---------------------------|--------------------------|
66
- | `str` | `"hello"` | `"hello"` |
67
- | `int` | `"8080"` | `8080` |
68
- | `float` | `"3.14"` | `3.14` |
69
- | `bool` | `"true"`, `"1"`, `"yes"` | `True` |
70
- | `bool` | `"false"`, `"0"`, `"no"` | `False` |
71
- | `list` | `"a,b,c"` | `["a", "b", "c"]` |
72
-
73
- ## Error messages
74
-
75
- All errors are collected and reported together — you won't fix one missing var only to discover another:
76
-
77
- ```
78
- EnvGuardError:
79
- Missing required environment variables:
80
- - DATABASE_URL (str): not set
81
- - API_KEY (str): not set
82
-
83
- Invalid environment variable values:
84
- - PORT: expected int, got 'abc'
85
- - DEBUG: expected bool, got 'maybe'
86
- ```
87
-
88
- ## Why not pydantic-settings?
89
-
90
- `pydantic-settings` is great but pulls in Pydantic as a dependency (~2MB). `envguard` is a single file with zero dependencies — useful when you want validation without adding weight to your project.
91
-
92
- ## License
93
-
94
- MIT
@@ -1,4 +0,0 @@
1
- from .core import EnvGuard, EnvGuardError, guard
2
-
3
- __all__ = ["EnvGuard", "EnvGuardError", "guard"]
4
- __version__ = "0.1.0"
File without changes
File without changes