Skip to content

Instantly share code, notes, and snippets.

@jacobtylerwalls
Last active October 9, 2025 10:48
Show Gist options
  • Select an option

  • Save jacobtylerwalls/2bcd3db07a129e2a6f8d07c94bac1d30 to your computer and use it in GitHub Desktop.

Select an option

Save jacobtylerwalls/2bcd3db07a129e2a6f8d07c94bac1d30 to your computer and use it in GitHub Desktop.
Report feature flag values per database
import ast
from dataclasses import dataclass
from typing import Any
import django.db.backends.base.features as BaseFeatureModule
from django.utils.functional import cached_property
from django.db.backends.base.features import BaseDatabaseFeatures
from django.db.backends.mysql.features import DatabaseFeatures as MySqlFeatures
from django.db.backends.oracle.features import DatabaseFeatures as OracleFeatures
from django.db.backends.postgresql.features import DatabaseFeatures as PostgresFeatures
import django.db.backends.sqlite3.base # to avoid partial import
from django.db.backends.sqlite3.features import DatabaseFeatures as SqliteFeatures
BACKENDS = {
"postgres": PostgresFeatures,
"sqlite": SqliteFeatures,
"oracle": OracleFeatures,
"mysql": MySqlFeatures,
}
MAYBE = "maybe"
NOT_FLAGS = {
"minimum_database_version",
}
def is_supported(value):
match value:
case int():
return value > 0
case bool():
return value
case property():
return MAYBE
case _:
return bool(value)
# consider cached_property
@dataclass
class DatabaseFeatureFlag():
attribute_name: str
description: str
value: Any
min_version: tuple[int, ...]
# details: ...
def __get__(self):
return self.value
def parse_ast():
with open(BaseFeatureModule.__file__, 'r') as module_file:
module_text = module_file.read()
module = ast.parse(module_text)
klass = [elem for elem in module.body if isinstance(elem, ast.ClassDef)][0]
return klass
def get_comment_for_feature_flag(class_node, feature_flag):
"""If a docstring exists underneath the feature flag, return the value."""
# searches every time...
found = False
for body_node in class_node.body:
if found:
if isinstance(body_node, ast.Expr):
return body_node.value.value
if isinstance(body_node, ast.Assign):
if body_node.targets[0].id == feature_flag:
if hasattr(body_node.value, "value"):
found = True
def report_features(class_node):
for feature_flag, default_value in vars(BaseDatabaseFeatures).items():
if (
not (
isinstance(default_value, (list, set, tuple, bool, int, property))
or default_value is None
)
or feature_flag.startswith("__")
or "test" in feature_flag
or feature_flag in NOT_FLAGS
):
# skipping methods for now
continue
print(feature_flag, ": ", get_comment_for_feature_flag(class_node, feature_flag))
for name, backend in BACKENDS.items():
got = getattr(backend, feature_flag)
print("\t", f"{name}: ", is_supported(got))
if __name__ == "__main__":
class_node = parse_ast()
report_features(class_node=class_node)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment