Skip to content

Commit

Permalink
Update documentation, type annotations + other PR feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
pi-sigma committed Jun 28, 2024
1 parent 33a4532 commit af06d8f
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 172 deletions.
69 changes: 35 additions & 34 deletions django_setup_configuration/config_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,28 +24,32 @@ class ConfigField:

class ConfigSettings:
"""
Settings for configuration steps, used to generate documentation.
Settings for configuration steps, also used to generate documentation.
Attributes:
enable_setting (`str`): the setting for enabling the associated configuration
step
namespace (`str`): the namespace of configuration variables for a given
configuration
file_name (`str`): the name of the file where the documentation is stored
models (`list`): a list of models from which documentation is retrieved
required_settings (`list`): required settings for a configuration step
optional_settings (`list`): optional settings for a configuration step
update_field_descriptions (`bool`): if `True`, custom model fields
(along with their descriptions) are loaded via the settings variable
`DJANGO_SETUP_CONFIG_CUSTOM_FIELDS`
required_settings (`list`): required settings for a configuration step
optional_settings (`list`): optional settings for a configuration step
detailed_info (`dict`): information for configuration settings which are
additional_info (`dict`): information for configuration settings which are
not associated with a particular model field
config_fields (`list`): a list of `ConfigField` objects containing information
about Django model fields
Example:
Given a configuration step `FooConfigurationStep`: ::
FooConfigurationStep(BaseConfigurationStep):
verbose_name = "Configuration step for Foo"
enable_setting = "FOO_CONFIG_ENABLE"
config_settings = ConfigSettings(
enable_setting = "FOO_CONFIG_ENABLE"
namespace="FOO",
file_name="foo",
models=["FooConfigurationModel"],
Expand All @@ -57,34 +61,43 @@ class ConfigSettings:
"FOO_SOME_OPT_SETTING",
"FOO_SOME_OTHER_OPT_SETTING",
],
detailed_info={
additional_info={
"example_non_model_field": {
"variable": "FOO_EXAMPLE_NON_MODEL_FIELD",
"description": "Documentation for a field that could not
"description": "Documentation for a field that cannot
be retrievend from a model",
"possible_values": "string (URL)",
},
},
)
"""

namespace: str
file_name: str
models: list[Type[models.Model]] | None
required_settings: list[str] = []
optional_settings: list[str] = []
detailed_info: dict[str, dict[str, str]] | None

def __init__(self, *args, update_field_descriptions: bool = False, **kwargs):
def __init__(
self,
*args,
enable_setting: str,
namespace: str,
file_name: str | None = None,
models: list[Type[models.Model]] | None = None,
required_settings: list[str],
optional_settings: list[str] | None = None,
additional_info: dict[str, dict[str, str]] | None = None,
update_field_descriptions: bool = False,
**kwargs,
):
self.enable_setting = enable_setting
self.namespace = namespace
self.file_name = file_name or self.namespace.lower()
self.models = models
self.required_settings = required_settings
self.optional_settings = optional_settings or []
self.additional_info = additional_info or {}
self.update_field_descriptions = update_field_descriptions
self.config_fields: list[ConfigField] = []

for key, value in kwargs.items():
setattr(self, key, value)

if not getattr(self, "models", None):
if not self.models:
return

# add support for custom fields like PrivateMediaField
if update_field_descriptions:
self.update_field_descriptions()

Expand Down Expand Up @@ -155,7 +168,7 @@ def get_field_description(field: models.Field) -> str:
# other fields
field_type = type(field)
if field_type in basic_field_descriptions.keys():
return basic_field_descriptions.get(field_type)
return basic_field_descriptions.get(field_type, "")

return "No information available"

Expand Down Expand Up @@ -212,16 +225,4 @@ def create_config_fields(
# convenience methods/properties for formatting
#
def get_config_variable(self, setting: str) -> str:
return f"{self.namespace}_" + setting.upper()

@property
def file_name(self) -> str:
"""
Use `self.namespace` in lower case as default file name of the documentation
if `file_name` is not provided when instantiating the class
"""
return getattr(self, "_file_name", None) or self.namespace.lower()

@file_name.setter
def file_name(self, val) -> None:
self._file_name = val
return f"{self.namespace}_{setting.upper()}"
6 changes: 2 additions & 4 deletions django_setup_configuration/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@

class BaseConfigurationStep(ABC):
verbose_name: str
required_settings: list[str] = []
enable_setting: str = ""
config_settings: ConfigSettings

def __repr__(self):
Expand Down Expand Up @@ -38,10 +36,10 @@ def is_enabled(self) -> bool:
By default all steps are enabled
"""
if not self.enable_setting:
if not self.config_settings.enable_setting:
return True

return getattr(settings, self.enable_setting, True)
return getattr(settings, self.config_settings.enable_setting, True)

@abstractmethod
def is_configured(self) -> bool:
Expand Down
12 changes: 3 additions & 9 deletions django_setup_configuration/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,16 @@
models.EmailField: "string representing an Email address ([email protected])",
models.FileField: (
"string representing the (absolute) path to a file, "
"including file extension: {example}".format(
example="/absolute/path/to/file.xml"
)
"including file extension: /absolute/path/to/file.xml"
),
models.ImageField: (
"string representing the (absolute) path to an image file, "
"including file extension: {example}".format(
example="/absolute/path/to/image.png"
)
"including file extension: /absolute/path/to/image.png"
),
models.IntegerField: "string representing an integer",
models.JSONField: "Mapping: {example}".format(example="{'some_key': 'Some value'}"),
models.PositiveIntegerField: "string representing a positive integer",
models.TextField: "text (string)",
models.URLField: "string (URL)",
models.UUIDField: "UUID string {example}".format(
example="(e.g. f6b45142-0c60-4ec7-b43d-28ceacdc0b34)"
),
models.UUIDField: "UUID string (e.g. f6b45142-0c60-4ec7-b43d-28ceacdc0b34)",
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@ class ConfigDocBase:
"""

@staticmethod
def _add_detailed_info(config_settings: ConfigSettings, result: list[str]) -> None:
def _add_additional_info(
config_settings: ConfigSettings, result: list[str]
) -> None:
"""Convenience/helper function to retrieve additional documentation info"""

if not (info := getattr(config_settings, "detailed_info", None)):
return
additional_info = config_settings.additional_info

for key, value in info.items():
for key, value in additional_info.items():
part = []
part.append(f"{'Variable':<20}{value['variable']}")
part.append(
Expand Down Expand Up @@ -61,10 +62,10 @@ def get_detailed_info(
part.append(f"{'Default value':<20}{field.default_value}")
ret.append(part)

self._add_detailed_info(config, ret)
self._add_additional_info(config, ret)

for step in related_steps:
self._add_detailed_info(step.config_settings, ret)
self._add_additional_info(step.config_settings, ret)

return ret

Expand All @@ -75,7 +76,7 @@ def format_display_name(self, display_name: str) -> str:
display_name_formatted = f"{heading_bar}\n{display_name}\n{heading_bar}"
return display_name_formatted

def render_doc(self, config_settings: ConfigSettings, config_step) -> None:
def render_doc(self, config_settings: ConfigSettings, config_step) -> str:
"""
Render a `ConfigSettings` documentation template with the following variables:
1. enable_setting
Expand All @@ -93,7 +94,8 @@ def render_doc(self, config_settings: ConfigSettings, config_step) -> None:
name for name in getattr(config_settings, "required_settings", [])
]

# additional requirements from related configuration steps
# additional requirements from related configuration steps to embed
# the documentation of several steps into one
related_steps = [step for step in getattr(config_step, "related_steps", [])]
related_requirements_lists = [
step.config_settings.required_settings for step in related_steps
Expand Down Expand Up @@ -156,7 +158,7 @@ def content_is_up_to_date(self, rendered_content: str, doc_path: str) -> bool:

return True

def handle(self, *args, **kwargs) -> str:
def handle(self, *args, **kwargs) -> None:
target_dir = settings.DJANGO_SETUP_CONFIG_DOC_PATH

# create directory for docs if it doesn't exist
Expand Down
Loading

0 comments on commit af06d8f

Please sign in to comment.