Skip to content

Commit

Permalink
✨ NEW: needs_reproducible_json config option (#1065)
Browse files Browse the repository at this point in the history
Setting ``needs_reproducible_json = True`` will ensure the JSON output is reproducible, e.g. by removing timestamps from the output.
  • Loading branch information
chrisjsewell committed Nov 8, 2023
1 parent 2140da0 commit 40856b2
Show file tree
Hide file tree
Showing 7 changed files with 437 additions and 18 deletions.
5 changes: 5 additions & 0 deletions docs/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1792,6 +1792,11 @@ Example:
The created ``needs.json`` file gets stored in the ``outdir`` of the current builder.
So if ``html`` is used as builder, the final location is e.g. ``_build/html/needs.json``.
.. versionadded:: 1.4.0
Setting ``needs_reproducible_json = True`` will ensure the JSON output is reproducible,
e.g. by removing timestamps from the output.
.. _needs_build_json_per_id:
Expand Down
8 changes: 4 additions & 4 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ lxml = { version = "^4.6.5", optional = true }
requests-mock = { version = ">=1.9.3", optional = true }
responses = { version = "^0.22.0", optional = true }
sphinxcontrib-plantuml = { version = "^0", optional = true }
syrupy = { version = ">=3,<5", optional = true }
syrupy = { version = "^3", optional = true }
pytest-xprocess = { version = "^0.22.2", optional = true }

# [project.optional-dependencies.test-parallel]
Expand Down
3 changes: 3 additions & 0 deletions sphinx_needs/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,9 @@ def __setattr__(self, name: str, value: Any) -> None:
default_factory=dict, metadata={"rebuild": "html", "types": (dict,)}
)
build_json: bool = field(default=False, metadata={"rebuild": "html", "types": (bool,)})
"""If True, the JSON needs file should be built."""
reproducible_json: bool = field(default=False, metadata={"rebuild": "html", "types": (bool,)})
"""If True, the JSON needs file should be idempotent for multiple builds fo the same documentation."""
build_needumls: str = field(default="", metadata={"rebuild": "html", "types": (str,)})
permalink_file: str = field(default="permalink.html", metadata={"rebuild": "html", "types": (str,)})
"""Permalink related config values.
Expand Down
17 changes: 12 additions & 5 deletions sphinx_needs/needsfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,36 +54,40 @@ class NeedsList:

def __init__(self, config: Config, outdir: str, confdir: str) -> None:
self.config = config
self.needs_config = NeedsSphinxConfig(config)
self.outdir = outdir
self.confdir = confdir
self.current_version = config.version
self.project = config.project
self.needs_list = {
"project": self.project,
"current_version": self.current_version,
"created": "",
"versions": {},
}
if not self.needs_config.reproducible_json:
self.needs_list["created"] = ""
self.log = log
# also exclude back links for link types dynamically set by the user
back_link_keys = {x["option"] + "_back" for x in NeedsSphinxConfig(config).extra_links}
back_link_keys = {x["option"] + "_back" for x in self.needs_config.extra_links}
self._exclude_need_keys = self.JSON_KEY_EXCLUSIONS_NEEDS | back_link_keys
self._exclude_filter_keys = self.JSON_KEY_EXCLUSIONS_FILTERS | back_link_keys

def update_or_add_version(self, version: str) -> None:
if version not in self.needs_list["versions"].keys():
self.needs_list["versions"][version] = {
"created": "",
"needs_amount": 0,
"needs": {},
"filters_amount": 0,
"filters": {},
}
if not self.needs_config.reproducible_json:
self.needs_list["versions"][version]["created"] = ""

if "needs" not in self.needs_list["versions"][version].keys():
self.needs_list["versions"][version]["needs"] = {}

self.needs_list["versions"][version]["created"] = datetime.now().isoformat()
if not self.needs_config.reproducible_json:
self.needs_list["versions"][version]["created"] = datetime.now().isoformat()

def add_need(self, version: str, need_info: NeedsInfoType) -> None:
self.update_or_add_version(version)
Expand All @@ -104,7 +108,10 @@ def wipe_version(self, version: str) -> None:

def write_json(self, needs_file: str = "needs.json", needs_path: str = "") -> None:
# We need to rewrite some data, because this kind of data gets overwritten during needs.json import.
self.needs_list["created"] = datetime.now().isoformat()
if not self.needs_config.reproducible_json:
self.needs_list["created"] = datetime.now().isoformat()
else:
self.needs_list.pop("created", None)
self.needs_list["current_version"] = self.current_version
self.needs_list["project"] = self.project
if needs_path:
Expand Down
Loading

0 comments on commit 40856b2

Please sign in to comment.