platzky 1.4.1__py3-none-any.whl → 1.4.2__py3-none-any.whl

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.
platzky/__init__.py CHANGED
@@ -1,4 +1,5 @@
1
1
  from platzky.engine import Engine as Engine
2
+ from platzky.feature_flags import BUILTIN_FLAGS as BUILTIN_FLAGS
2
3
  from platzky.feature_flags import FakeLogin as FakeLogin
3
4
  from platzky.feature_flags import FeatureFlag as FeatureFlag
4
5
  from platzky.feature_flags import all_flags as all_flags
platzky/config.py CHANGED
@@ -12,7 +12,6 @@ from pydantic import BaseModel, ConfigDict, Field, field_validator
12
12
  from platzky.attachment.constants import BLOCKED_EXTENSIONS, DEFAULT_MAX_ATTACHMENT_SIZE
13
13
  from platzky.db.db import DBConfig
14
14
  from platzky.db.db_loader import get_db_module
15
- from platzky.feature_flags import build_flag_set
16
15
  from platzky.feature_flags_wrapper import FeatureFlagSet
17
16
 
18
17
 
@@ -257,7 +256,7 @@ class Config(BaseModel):
257
256
  debug: bool = Field(default=False, alias="DEBUG")
258
257
  testing: bool = Field(default=False, alias="TESTING")
259
258
  feature_flags: FeatureFlagSet = Field(
260
- default_factory=build_flag_set,
259
+ default_factory=lambda: FeatureFlagSet({}),
261
260
  alias="FEATURE_FLAGS",
262
261
  )
263
262
  telemetry: TelemetryConfig = Field(default_factory=TelemetryConfig, alias="TELEMETRY")
@@ -270,9 +269,9 @@ class Config(BaseModel):
270
269
  if isinstance(v, FeatureFlagSet):
271
270
  return v
272
271
  if isinstance(v, dict):
273
- return build_flag_set(v)
272
+ return FeatureFlagSet(v)
274
273
  if v is None:
275
- return build_flag_set()
274
+ return FeatureFlagSet({})
276
275
  return v
277
276
 
278
277
  @classmethod
@@ -286,8 +285,7 @@ class Config(BaseModel):
286
285
  ) -> "Config":
287
286
  """Validate and construct Config from dictionary.
288
287
 
289
- Parses the raw FEATURE_FLAGS dict into a frozenset of enabled
290
- FeatureFlag types via ``parse_flags()``.
288
+ Parses the raw FEATURE_FLAGS dict into a ``FeatureFlagSet``.
291
289
 
292
290
  Args:
293
291
  obj: Configuration dictionary
platzky/feature_flags.py CHANGED
@@ -1,8 +1,9 @@
1
- """Feature flags system with instance-based registration.
1
+ """Feature flags system for Platzky.
2
2
 
3
- Flags are created as instances of ``FeatureFlag``. Each instance is
4
- automatically registered and discovered via ``all_flags()``. The primary
5
- API is ``engine.is_enabled(flag_instance)``.
3
+ Flags are created as instances of ``FeatureFlag``. The primary API is
4
+ ``engine.is_enabled(flag_instance)``. Resolution is dynamic — the
5
+ ``FeatureFlagSet`` checks the raw config dict using each flag's ``alias``
6
+ and ``default`` at lookup time. No global registry is needed.
6
7
 
7
8
  Example::
8
9
 
@@ -16,11 +17,11 @@ from __future__ import annotations
16
17
 
17
18
  from typing import TYPE_CHECKING
18
19
 
20
+ import deprecation
21
+
19
22
  if TYPE_CHECKING:
20
23
  from platzky.feature_flags_wrapper import FeatureFlagSet
21
24
 
22
- _registry: set[FeatureFlag] = set()
23
-
24
25
 
25
26
  class FeatureFlag:
26
27
  """A feature flag.
@@ -52,7 +53,6 @@ class FeatureFlag:
52
53
  default: bool = False,
53
54
  description: str = "",
54
55
  production_warning: bool = False,
55
- register: bool = True,
56
56
  ) -> None:
57
57
  if not alias:
58
58
  raise ValueError("FeatureFlag requires a non-empty 'alias'")
@@ -60,8 +60,6 @@ class FeatureFlag:
60
60
  self.default = default
61
61
  self.description = description
62
62
  self.production_warning = production_warning
63
- if register:
64
- _registry.add(self)
65
63
 
66
64
  def __repr__(self) -> str:
67
65
  return f"FeatureFlag(alias={self.alias!r})"
@@ -82,60 +80,63 @@ FakeLogin = FeatureFlag(
82
80
  production_warning=True,
83
81
  )
84
82
 
83
+ BUILTIN_FLAGS: tuple[FeatureFlag, ...] = (FakeLogin,)
85
84
 
86
- def all_flags() -> frozenset[FeatureFlag]:
87
- """Return all registered feature flags.
88
85
 
89
- Note: The returned frozenset has no guaranteed iteration order.
90
- Use ``sorted(all_flags(), key=lambda f: f.alias)`` when
91
- deterministic ordering is needed (e.g., documentation generation).
92
- """
93
- return frozenset(_registry)
86
+ # ---------------------------------------------------------------------------
87
+ # Deprecated shims will be removed in 2.0.0
88
+ # ---------------------------------------------------------------------------
94
89
 
95
90
 
96
- def unregister(flag: FeatureFlag) -> None:
97
- """Remove a flag from the registry."""
98
- _registry.discard(flag)
99
-
100
-
101
- def clear_registry() -> None:
102
- """Remove all flags from the registry. Intended for test isolation."""
103
- _registry.clear()
91
+ @deprecation.deprecated(
92
+ deprecated_in="1.5.0",
93
+ removed_in="2.0.0",
94
+ details="Use BUILTIN_FLAGS instead.",
95
+ )
96
+ def all_flags() -> frozenset[FeatureFlag]:
97
+ """Return all built-in feature flags."""
98
+ return frozenset(BUILTIN_FLAGS)
104
99
 
105
100
 
101
+ @deprecation.deprecated(
102
+ deprecated_in="1.5.0",
103
+ removed_in="2.0.0",
104
+ details="Use FeatureFlagSet(raw_data) and check membership with 'flag in flag_set' instead.",
105
+ )
106
106
  def parse_flags(
107
107
  raw_data: dict[str, bool] | None = None,
108
108
  ) -> frozenset[FeatureFlag]:
109
- """Build a frozenset of *enabled* flags from raw config data.
110
-
111
- Uses ``all_flags()`` for discovery. Unknown keys in *raw_data* are
112
- silently ignored.
113
-
114
- Args:
115
- raw_data: Dict of flag alias -> value from config / YAML.
116
-
117
- Returns:
118
- A frozenset containing the enabled FeatureFlag instances.
119
- """
109
+ """Build a frozenset of enabled flags from raw config data."""
120
110
  if raw_data is None:
121
111
  raw_data = {}
122
-
123
- return frozenset(flag for flag in all_flags() if raw_data.get(flag.alias, flag.default))
112
+ return frozenset(flag for flag in BUILTIN_FLAGS if raw_data.get(flag.alias, flag.default))
124
113
 
125
114
 
115
+ @deprecation.deprecated(
116
+ deprecated_in="1.5.0",
117
+ removed_in="2.0.0",
118
+ details="Use FeatureFlagSet(raw_data) directly.",
119
+ )
126
120
  def build_flag_set(raw_data: dict[str, bool] | None = None) -> FeatureFlagSet:
127
- """Build a FeatureFlagSet from raw config data.
128
-
129
- Preserves ALL keys (including unregistered ones) for backward
130
- compatibility with consumers that use dict-like access.
131
- """
121
+ """Build a FeatureFlagSet from raw config data."""
132
122
  from platzky.feature_flags_wrapper import FeatureFlagSet
133
123
 
134
- if raw_data is None:
135
- raw_data = {}
124
+ return FeatureFlagSet(raw_data or {})
125
+
126
+
127
+ @deprecation.deprecated(
128
+ deprecated_in="1.5.0",
129
+ removed_in="2.0.0",
130
+ details="No replacement needed — the global registry has been removed.",
131
+ )
132
+ def unregister(_flag: FeatureFlag) -> None:
133
+ """No-op. The global registry has been removed."""
136
134
 
137
- enabled_flags = frozenset(
138
- flag for flag in all_flags() if raw_data.get(flag.alias, flag.default)
139
- )
140
135
 
141
- return FeatureFlagSet(enabled_flags, raw_data)
136
+ @deprecation.deprecated(
137
+ deprecated_in="1.5.0",
138
+ removed_in="2.0.0",
139
+ details="No replacement needed — the global registry has been removed.",
140
+ )
141
+ def clear_registry() -> None:
142
+ """No-op. The global registry has been removed."""
@@ -42,16 +42,8 @@ class FeatureFlagSet(dict[str, bool]):
42
42
  - ``flag_set.KEY`` -- deprecated Jinja2 attribute access.
43
43
  """
44
44
 
45
- _enabled_flags: frozenset[FeatureFlag]
46
-
47
- def __init__(
48
- self,
49
- enabled_flags: frozenset[FeatureFlag],
50
- raw_data: dict[str, bool],
51
- ) -> None:
45
+ def __init__(self, raw_data: dict[str, bool]) -> None:
52
46
  super().__init__(raw_data)
53
- # Use object.__setattr__ to bypass __getattr__ override
54
- object.__setattr__(self, "_enabled_flags", enabled_flags)
55
47
 
56
48
  def __getitem__(self, key: str) -> bool:
57
49
  """Dict bracket access with deprecation warning."""
@@ -77,7 +69,9 @@ class FeatureFlagSet(dict[str, bool]):
77
69
  def __contains__(self, item: object) -> bool:
78
70
  """Support both FeatureFlag membership and string key lookup."""
79
71
  if isinstance(item, FeatureFlag):
80
- return item in self._enabled_flags
72
+ if super().__contains__(item.alias):
73
+ return bool(super().__getitem__(item.alias))
74
+ return item.default
81
75
  return super().__contains__(item)
82
76
 
83
77
  def __getattr__(self, name: str) -> bool:
@@ -86,8 +80,3 @@ class FeatureFlagSet(dict[str, bool]):
86
80
  return self[name]
87
81
  except KeyError:
88
82
  raise AttributeError(f"'{type(self).__name__}' has no attribute {name!r}") from None
89
-
90
- @property
91
- def enabled_flags(self) -> frozenset[FeatureFlag]:
92
- """The set of enabled typed FeatureFlag instances."""
93
- return self._enabled_flags
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: platzky
3
- Version: 1.4.1
3
+ Version: 1.4.2
4
4
  Summary: Not only blog engine
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -1,4 +1,4 @@
1
- platzky/__init__.py,sha256=jn2Ua0ZpKBI3Fb5tFYcRm3kEaR0SytlNBh6guUtO2jg,558
1
+ platzky/__init__.py,sha256=kqK72dPH79dNogz8yB5K8XnwNM3PTC7rd-tCVgULks0,623
2
2
  platzky/admin/admin.py,sha256=_4Q1nId_QGrbSMaAZzl7ziquza3syQxXlBYYXjD_4XM,1660
3
3
  platzky/admin/templates/admin.html,sha256=zgjROhSezayZqnNFezvVa0MEfgmXLvOM8HRRaZemkQw,688
4
4
  platzky/admin/templates/login.html,sha256=oBNuv130iMTwXrtRnDUDcGIGvu0O2VsIbjQxw-Tjd7Y,380
@@ -10,7 +10,7 @@ platzky/attachment/mime_validation.py,sha256=VO272nF7K_Mx_Zefuw-10M-Tapj0ZxX197s
10
10
  platzky/blog/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  platzky/blog/blog.py,sha256=UaAS7QpcEsMswMrdAcyoSyuDX1NNQX05ll8D7MKSR3w,5468
12
12
  platzky/blog/comment_form.py,sha256=yOuXvX9PZLc6qQLIWZWLFcbwFQD4a849X82PlXKUzdk,805
13
- platzky/config.py,sha256=vldHCB6C_Y9NllkacSJ0-jd3vo3eIw9sG6eDpGQpyOU,11589
13
+ platzky/config.py,sha256=Op4Bbrqvny48JKL7mWQRCP7aCSppTcysAkSgAtB75kc,11504
14
14
  platzky/db/README.md,sha256=IO-LoDsd4dLBZenaz423EZjvEOQu_8m2OC0G7du170w,1753
15
15
  platzky/db/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
16
  platzky/db/db.py,sha256=gi5uxvY8Ww8O4y2rxaH1Zj_12Yno8SbILvIaWnQPbYQ,4778
@@ -25,8 +25,8 @@ platzky/debug/__init__.py,sha256=5VUFjOOJzuXTuCgzQRe9aNjXHoCJSVUerR3RLKCTZC0,301
25
25
  platzky/debug/blueprint.py,sha256=_rtrtrOOsj4Pz8AKE_5kLFVedEtipAyN42j-pBVZqnM,1893
26
26
  platzky/debug/fake_login.py,sha256=3AmS11Kb4h5gDwWjUY26iDMif0b0x69S97veotnXUp4,3390
27
27
  platzky/engine.py,sha256=JeyRS-A0R0fK2BLude_Y4U8G3d-7nRUkuu4OeX86sRI,7400
28
- platzky/feature_flags.py,sha256=BD-DcPDYfYr2xuMrc61qyw5s6QQBqI1ro_H3-h3vWeo,3947
29
- platzky/feature_flags_wrapper.py,sha256=NqBoix90VODiILEkO6esRMRKsKZQVHgOa3VUWV3PPmU,3138
28
+ platzky/feature_flags.py,sha256=6y5ErUgTAiKYNyvbUkGMVJl15sc7ouOvrqnMVIRCbuc,4095
29
+ platzky/feature_flags_wrapper.py,sha256=_tH4aeAx33Czv7gvPEyYYLbiSRhWYiRooAFEtoikeF4,2822
30
30
  platzky/locale/en/LC_MESSAGES/messages.po,sha256=WaZGlFAegKRq7CSz69dWKic-mKvQFhVvssvExxNmGaU,1400
31
31
  platzky/locale/pl/LC_MESSAGES/messages.po,sha256=sUPxMKDeEOoZ5UIg94rGxZD06YVWiAMWIby2XE51Hrc,1624
32
32
  platzky/models.py,sha256=Ws5ZSWf5EhcpFxl3Yeze2pQiesjnjAA_haBJ90bN6lk,7435
@@ -50,7 +50,7 @@ platzky/templates/post.html,sha256=GSgjIZsOQKtNx3cEbquSjZ5L4whPnG6MzRyoq9k4B8Q,1
50
50
  platzky/templates/robots.txt,sha256=2_j2tiYtYJnzZUrANiX9pvBxyw5Dp27fR_co18BPEJ0,116
51
51
  platzky/templates/sitemap.xml,sha256=iIJZ91_B5ZuNLCHsRtsGKZlBAXojOTP8kffqKLacgvs,578
52
52
  platzky/www_handler.py,sha256=pF6Rmvem1sdVqHD7z3RLrDuG-CwAqfGCti50_NPsB2w,725
53
- platzky-1.4.1.dist-info/METADATA,sha256=7sZy3c0h0DRh_uEVwK1t_hqrV8XLaWarDbpLj2SA4xM,2595
54
- platzky-1.4.1.dist-info/WHEEL,sha256=3ny-bZhpXrU6vSQ1UPG34FoxZBp3lVcvK0LkgUz6VLk,88
55
- platzky-1.4.1.dist-info/licenses/LICENSE,sha256=wCdfk-qEosi6BDwiBulMfKMi0hxp1UXV0DdjLrRm788,1077
56
- platzky-1.4.1.dist-info/RECORD,,
53
+ platzky-1.4.2.dist-info/METADATA,sha256=TeusSpm8WupVralLVXnSzZ_UxPefW0AIdbevUTWW4yg,2595
54
+ platzky-1.4.2.dist-info/WHEEL,sha256=kJCRJT_g0adfAJzTx2GUMmS80rTJIVHRCfG0DQgLq3o,88
55
+ platzky-1.4.2.dist-info/licenses/LICENSE,sha256=wCdfk-qEosi6BDwiBulMfKMi0hxp1UXV0DdjLrRm788,1077
56
+ platzky-1.4.2.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.3.0
2
+ Generator: poetry-core 2.3.1
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any