Repository: useblocks/sphinx-needs
Pull request #1313 (2024-10-02 12:54:57)

🔧 Set `env_version` for sphinx extension
See https://www.sphinx-doc.org/en/master/extdev/index.html#extension-metadata

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/useblocks/sphinx-needs/pull/1313?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=useblocks) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 87.74%. Comparing base [(`4e10030`)](https://app.codecov.io/gh/useblocks/sphinx-needs/commit/4e10030581c03c59764e517ab750d3ddbb2695d8?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=useblocks) to head [(`bdc8c94`)](https://app.codecov.io/gh/useblocks/sphinx-needs/commit/bdc8c941077ad2aa43a7c9fbcc2eee83c12820a8?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=useblocks).
> Report is 58 commits behind head on master.

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##           master    #1313      +/-   ##
==========================================
+ Coverage   86.87%   87.74%   +0.86%     
==========================================
  Files          56       60       +4     
  Lines        6532     7035     +503     
==========================================
+ Hits         5675     6173     +498     
- Misses        857      862       +5     
```

| [Flag](https://app.codecov.io/gh/useblocks/sphinx-needs/pull/1313/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=useblocks) | Coverage Δ | |
|---|---|---|
| [pytests](https://app.codecov.io/gh/useblocks/sphinx-needs/pull/1313/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=useblocks) | `87.74% <100.00%> (+0.86%)` | :arrow_up: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=useblocks#carryforward-flags-in-the-pull-request-comment) to find out more.

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/useblocks/sphinx-needs/pull/1313?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=useblocks).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=useblocks).


Patch:
diff --git a/sphinx_needs/builder.py b/sphinx_needs/builder.py
index e8e7ea21..35158d0b 100644
--- a/sphinx_needs/builder.py
+++ b/sphinx_needs/builder.py
@@ -117,12 +117,7 @@ def build_needs_json(app: Sphinx, _exception: Exception) -> None:
     if isinstance(app.builder, NeedsBuilder):
         return
 
-    try:
-        needs_builder = NeedsBuilder(app, env)
-    except TypeError:
-        needs_builder = NeedsBuilder(app)
-        needs_builder.set_environment(env)
-
+    needs_builder = NeedsBuilder(app, env)
     needs_builder.finish()
 
 
@@ -196,12 +191,8 @@ def build_needs_id_json(app: Sphinx, _exception: Exception) -> None:
     # Do not create an additional needs_json for every needs_id, if builder is already "needs_id".
     if isinstance(app.builder, NeedsIdBuilder):
         return
-    try:
-        needs_id_builder = NeedsIdBuilder(app, env)
-    except TypeError:
-        needs_id_builder = NeedsIdBuilder(app)
-        needs_id_builder.set_environment(env)
 
+    needs_id_builder = NeedsIdBuilder(app, env)
     needs_id_builder.finish()
 
 
diff --git a/sphinx_needs/data.py b/sphinx_needs/data.py
index b6b62b55..2f8b099d 100644
--- a/sphinx_needs/data.py
+++ b/sphinx_needs/data.py
@@ -32,6 +32,12 @@ if TYPE_CHECKING:
 
 LOGGER = getLogger(__name__)
 
+ENV_DATA_VERSION: Final = 2
+"""Version of the data stored in the environment.
+
+See https://www.sphinx-doc.org/en/master/extdev/index.html#extension-metadata
+"""
+
 
 class NeedsPartType(TypedDict):
     """Data for a single need part."""
@@ -764,23 +770,23 @@ class SphinxNeedsData:
         This is lazily created and cached in the environment.
         """
         try:
-            return self.env.needs_all_docs
+            return self.env._needs_all_docs
         except AttributeError:
-            self.env.needs_all_docs = {"all": []}
-        return self.env.needs_all_docs
+            self.env._needs_all_docs = {"all": []}
+        return self.env._needs_all_docs
 
     @property
     def needs_is_post_processed(self) -> bool:
         """Whether needs have been post-processed."""
         try:
-            return self.env.needs_is_post_processed
+            return self.env._needs_is_post_processed
         except AttributeError:
-            self.env.needs_is_post_processed = False
-        return self.env.needs_is_post_processed
+            self.env._needs_is_post_processed = False
+        return self.env._needs_is_post_processed
 
     @needs_is_post_processed.setter
     def needs_is_post_processed(self, value: bool) -> None:
-        self.env.needs_is_post_processed = value
+        self.env._needs_is_post_processed = value
 
     def get_or_create_services(self) -> ServiceManager:
         """Get information about services.
@@ -790,10 +796,10 @@ class SphinxNeedsData:
         from sphinx_needs.services.manager import ServiceManager
 
         try:
-            return self.env.app.needs_services
+            return self.env.app._needs_services
         except AttributeError:
-            self.env.app.needs_services = ServiceManager(self.env.app)
-        return self.env.app.needs_services
+            self.env.app._needs_services = ServiceManager(self.env.app)
+        return self.env.app._needs_services
 
     def get_or_create_extends(self) -> dict[str, NeedsExtendType]:
         """Get all need modifications, mapped by ID.
@@ -801,10 +807,10 @@ class SphinxNeedsData:
         This is lazily created and cached in the environment.
         """
         try:
-            return self.env.need_all_needextend
+            return self.env._need_all_needextend
         except AttributeError:
-            self.env.need_all_needextend = {}
-        return self.env.need_all_needextend
+            self.env._need_all_needextend = {}
+        return self.env._need_all_needextend
 
     def get_or_create_umls(self) -> dict[str, NeedsUmlType]:
         """Get all need uml diagrams, mapped by ID.
@@ -812,18 +818,18 @@ class SphinxNeedsData:
         This is lazily created and cached in the environment.
         """
         try:
-            return self.env.needs_all_needumls
+            return self.env._needs_all_needumls
         except AttributeError:
-            self.env.needs_all_needumls = {}
-        return self.env.needs_all_needumls
+            self.env._needs_all_needumls = {}
+        return self.env._needs_all_needumls
 
     @property
     def _needs_all_nodes(self) -> dict[str, Need]:
         try:
-            return self.env.needs_all_nodes
+            return self.env._needs_all_nodes
         except AttributeError:
-            self.env.needs_all_nodes = {}
-        return self.env.needs_all_nodes
+            self.env._needs_all_nodes = {}
+        return self.env._needs_all_nodes
 
     def set_need_node(self, need_id: str, node: Need) -> None:
         """Set a need node in the cache."""
@@ -906,7 +912,7 @@ def merge_data(
                     f"not {type(other_objects)} and {type(objects)}"
                 )
 
-    _merge("needs_all_docs", is_complex_dict=True)
-    _merge("needs_all_nodes")
-    _merge("need_all_needextend")
-    _merge("needs_all_needumls")
+    _merge("_needs_all_docs", is_complex_dict=True)
+    _merge("_needs_all_nodes")
+    _merge("_need_all_needextend")
+    _merge("_needs_all_needumls")
diff --git a/sphinx_needs/needs.py b/sphinx_needs/needs.py
index 74211449..f647079f 100644
--- a/sphinx_needs/needs.py
+++ b/sphinx_needs/needs.py
@@ -22,7 +22,12 @@ from sphinx_needs.builder import (
     build_needumls_pumls,
 )
 from sphinx_needs.config import NEEDS_CONFIG, LinkOptionsType, NeedsSphinxConfig
-from sphinx_needs.data import NeedsCoreFields, SphinxNeedsData, merge_data
+from sphinx_needs.data import (
+    ENV_DATA_VERSION,
+    NeedsCoreFields,
+    SphinxNeedsData,
+    merge_data,
+)
 from sphinx_needs.defaults import (
     GRAPHVIZ_STYLE_DEFAULTS,
     LAYOUTS,
@@ -303,6 +308,7 @@ def setup(app: Sphinx) -> dict[str, Any]:
         "version": VERSION,
         "parallel_read_safe": True,
         "parallel_write_safe": True,
+        "env_version": ENV_DATA_VERSION,
     }
 
 
@@ -499,10 +505,9 @@ def prepare_env(app: Sphinx, env: BuildEnvironment, _docname: str) -> None:
     """
     needs_config = NeedsSphinxConfig(app.config)
     data = SphinxNeedsData(env)
-    data.get_or_create_docs()
-    services = data.get_or_create_services()
 
     # Register embedded services
+    services = data.get_or_create_services()
     services.register("github-issues", GithubService, gh_type="issue")
     services.register("github-prs", GithubService, gh_type="pr")
     services.register("github-commits", GithubService, gh_type="commit")
diff --git a/sphinx_needs/needsfile.json b/sphinx_needs/needsfile.json
index a65453e4..512c5026 100644
--- a/sphinx_needs/needsfile.json
+++ b/sphinx_needs/needsfile.json
@@ -14,8 +14,7 @@
                      "type": "object",
                      "properties": {
                          "created": {"type": "string"},
-                         "filters": {"type": "object"},
-                         "filters_amount": {"type": "number"},
+                         "creator": {"type": "object"},
                          "needs": {
                              "patternProperties": {
                                  "^.*$": {
diff --git a/sphinx_needs/needsfile.py b/sphinx_needs/needsfile.py
index c2d9a92c..c3e65f98 100644
--- a/sphinx_needs/needsfile.py
+++ b/sphinx_needs/needsfile.py
@@ -129,12 +129,16 @@ class NeedsList:
         )
 
     def update_or_add_version(self, version: str) -> None:
+        from sphinx_needs.needs import __version__
+
         if version not in self.needs_list["versions"].keys():
             self.needs_list["versions"][version] = {
                 "needs_amount": 0,
                 "needs": {},
-                "filters_amount": 0,
-                "filters": {},
+                "creator": {
+                    "program": "sphinx_needs",
+                    "version": __version__,
+                },
             }
             if self._schema:
                 self.needs_list["versions"][version]["needs_schema"] = self._schema
diff --git a/sphinx_needs/warnings.py b/sphinx_needs/warnings.py
index 796c727f..5c0e7860 100644
--- a/sphinx_needs/warnings.py
+++ b/sphinx_needs/warnings.py
@@ -45,10 +45,10 @@ def process_warnings(app: Sphinx, exception: Exception | None) -> None:
     # Check if warnings already got executed.
     # Needed because the used event gets executed multiple times, but warnings need to be checked only
     # on first execution
-    if hasattr(env, "needs_warnings_executed") and env.needs_warnings_executed:
+    if hasattr(env, "_needs_warnings_executed") and env._needs_warnings_executed:
         return
 
-    env.needs_warnings_executed = True  # type: ignore[attr-defined]
+    env._needs_warnings_executed = True  # type: ignore[attr-defined]
 
     # Exclude external needs for warnings check
     needs_view = needs_view.filter_is_external(False)


Test patch:
diff --git a/tests/__snapshots__/test_basic_doc.ambr b/tests/__snapshots__/test_basic_doc.ambr
index 543c737e..48b1eefa 100644
--- a/tests/__snapshots__/test_basic_doc.ambr
+++ b/tests/__snapshots__/test_basic_doc.ambr
@@ -3,9 +3,6 @@
     'current_version': '0.1.0',
     'versions': dict({
       '0.1.0': dict({
-        'filters': dict({
-        }),
-        'filters_amount': 0,
         'needs': dict({
           'ST_001': dict({
             'arch': dict({
diff --git a/tests/__snapshots__/test_external.ambr b/tests/__snapshots__/test_external.ambr
index 94255207..5a0034ce 100644
--- a/tests/__snapshots__/test_external.ambr
+++ b/tests/__snapshots__/test_external.ambr
@@ -3,9 +3,6 @@
     'current_version': '1.3',
     'versions': dict({
       '1.3': dict({
-        'filters': dict({
-        }),
-        'filters_amount': 0,
         'needs': dict({
           'EXT_REQ_01': dict({
             'description': '',
@@ -473,9 +470,6 @@
     'current_version': '1.0',
     'versions': dict({
       '1.0': dict({
-        'filters': dict({
-        }),
-        'filters_amount': 0,
         'needs': dict({
           'EXT_TEST_01': dict({
             'arch': dict({
diff --git a/tests/__snapshots__/test_need_constraints.ambr b/tests/__snapshots__/test_need_constraints.ambr
index b63a694b..05ea8d5b 100644
--- a/tests/__snapshots__/test_need_constraints.ambr
+++ b/tests/__snapshots__/test_need_constraints.ambr
@@ -3,9 +3,6 @@
     'current_version': '',
     'versions': dict({
       '': dict({
-        'filters': dict({
-        }),
-        'filters_amount': 0,
         'needs': dict({
           'SECURITY_REQ': dict({
             'arch': dict({
diff --git a/tests/__snapshots__/test_needextend.ambr b/tests/__snapshots__/test_needextend.ambr
index 40a4cd7c..86924f06 100644
--- a/tests/__snapshots__/test_needextend.ambr
+++ b/tests/__snapshots__/test_needextend.ambr
@@ -3,9 +3,6 @@
     'current_version': '',
     'versions': dict({
       '': dict({
-        'filters': dict({
-        }),
-        'filters_amount': 0,
         'needs': dict({
           'REQ_1': dict({
             'arch': dict({
@@ -795,9 +792,6 @@
     'current_version': '',
     'versions': dict({
       '': dict({
-        'filters': dict({
-        }),
-        'filters_amount': 0,
         'needs': dict({
           'extend_test_003': dict({
             'arch': dict({
diff --git a/tests/__snapshots__/test_needimport.ambr b/tests/__snapshots__/test_needimport.ambr
index 7e2e5e47..5a94e8b8 100644
--- a/tests/__snapshots__/test_needimport.ambr
+++ b/tests/__snapshots__/test_needimport.ambr
@@ -3,9 +3,6 @@
     'current_version': '1.0',
     'versions': dict({
       '1.0': dict({
-        'filters': dict({
-        }),
-        'filters_amount': 0,
         'needs': dict({
           'IMPL_01': dict({
             'description': 'Incoming links of this spec: :need_incoming:`IMPL_01`.',
diff --git a/tests/__snapshots__/test_needs_builder.ambr b/tests/__snapshots__/test_needs_builder.ambr
index 4bc9fdaf..1adc9d5b 100644
--- a/tests/__snapshots__/test_needs_builder.ambr
+++ b/tests/__snapshots__/test_needs_builder.ambr
@@ -3,9 +3,6 @@
     'current_version': '1.0',
     'versions': dict({
       '1.0': dict({
-        'filters': dict({
-        }),
-        'filters_amount': 0,
         'needs': dict({
           'TC_001': dict({
             'arch': dict({
@@ -816,9 +813,6 @@
     'current_version': '1.0',
     'versions': dict({
       '1.0': dict({
-        'filters': dict({
-        }),
-        'filters_amount': 0,
         'needs': dict({
           'TC_001': dict({
             'description': '',
@@ -1473,9 +1467,6 @@
     'current_version': '1.0',
     'versions': dict({
       '1.0': dict({
-        'filters': dict({
-        }),
-        'filters_amount': 0,
         'needs': dict({
           'TC_001': dict({
             'arch': dict({
diff --git a/tests/__snapshots__/test_needs_id_builder.ambr b/tests/__snapshots__/test_needs_id_builder.ambr
index 55c14b27..4e339064 100644
--- a/tests/__snapshots__/test_needs_id_builder.ambr
+++ b/tests/__snapshots__/test_needs_id_builder.ambr
@@ -4,9 +4,6 @@
       'current_version': '1.0',
       'versions': dict({
         '1.0': dict({
-          'filters': dict({
-          }),
-          'filters_amount': 0,
           'needs': dict({
             'TC_001': dict({
               'arch': dict({
@@ -87,9 +84,6 @@
       'current_version': '1.0',
       'versions': dict({
         '1.0': dict({
-          'filters': dict({
-          }),
-          'filters_amount': 0,
           'needs': dict({
             'TC_NEG_001': dict({
               'arch': dict({
@@ -170,9 +164,6 @@
       'current_version': '1.0',
       'versions': dict({
         '1.0': dict({
-          'filters': dict({
-          }),
-          'filters_amount': 0,
           'needs': dict({
             'US_63252': dict({
               'arch': dict({
diff --git a/tests/__snapshots__/test_service_github.ambr b/tests/__snapshots__/test_service_github.ambr
index 4999d8f9..6ec20442 100644
--- a/tests/__snapshots__/test_service_github.ambr
+++ b/tests/__snapshots__/test_service_github.ambr
@@ -3,9 +3,6 @@
     'current_version': '1',
     'versions': dict({
       '1': dict({
-        'filters': dict({
-        }),
-        'filters_amount': 0,
         'needs': dict({
           'GITHUB_050bec': dict({
             'arch': dict({
diff --git a/tests/test_basic_doc.py b/tests/test_basic_doc.py
index 7cf49a71..81d5a81e 100644
--- a/tests/test_basic_doc.py
+++ b/tests/test_basic_doc.py
@@ -149,7 +149,7 @@ def test_build_needs(test_app: SphinxTestApp, snapshot):
     json_text = Path(app.outdir, "needs.json").read_text()
     needs_data = json.loads(json_text)
 
-    assert needs_data == snapshot(exclude=props("created", "project"))
+    assert needs_data == snapshot(exclude=props("created", "project", "creator"))
 
 
 # Test with needs_id_required=True and missing ids in docs.
diff --git a/tests/test_external.py b/tests/test_external.py
index 5a5438fc..37e40ed9 100644
--- a/tests/test_external.py
+++ b/tests/test_external.py
@@ -47,7 +47,7 @@ def test_external_json(test_app: SphinxTestApp, snapshot):
     app.build()
     json_data = Path(app.outdir, "needs.json").read_text()
     needs = json.loads(json_data)
-    assert needs == snapshot(exclude=props("created", "project"))
+    assert needs == snapshot(exclude=props("created", "project", "creator"))
 
 
 def test_export_import_round_trip(tmp_path: Path, snapshot):
@@ -136,4 +136,4 @@ def test_export_import_round_trip(tmp_path: Path, snapshot):
 
     json_data = json.loads(Path(str(app.outdir), "needs.json").read_text("utf8"))
 
-    assert json_data == snapshot(exclude=props("created", "project"))
+    assert json_data == snapshot(exclude=props("created", "project", "creator"))
diff --git a/tests/test_need_constraints.py b/tests/test_need_constraints.py
index 31004c2c..febf8760 100644
--- a/tests/test_need_constraints.py
+++ b/tests/test_need_constraints.py
@@ -19,7 +19,7 @@ def test_need_constraints(test_app, snapshot):
 
     json_text = Path(app.outdir, "needs.json").read_text()
     needs_data = json.loads(json_text)
-    assert needs_data == snapshot(exclude=props("created", "project"))
+    assert needs_data == snapshot(exclude=props("created", "project", "creator"))
 
     srcdir = Path(app.srcdir)
     out_dir = srcdir / "_build"
diff --git a/tests/test_needarch.py b/tests/test_needarch.py
index 0d68df36..a6a8467d 100644
--- a/tests/test_needarch.py
+++ b/tests/test_needarch.py
@@ -51,7 +51,7 @@ def test_doc_needarch_jinja_import(test_app, snapshot):
     assert html
 
     # check needarch
-    all_needumls = app.env.needs_all_needumls
+    all_needumls = app.env._needs_all_needumls
     assert all_needumls == snapshot
 
 
@@ -64,7 +64,7 @@ def test_needarch_jinja_func_need(test_app, snapshot):
     app = test_app
     app.build()
 
-    all_needumls = app.env.needs_all_needumls
+    all_needumls = app.env._needs_all_needumls
     assert all_needumls == snapshot
 
     html = Path(app.outdir, "index.html").read_text(encoding="utf8")
diff --git a/tests/test_needextend.py b/tests/test_needextend.py
index c8113426..630f40d3 100644
--- a/tests/test_needextend.py
+++ b/tests/test_needextend.py
@@ -19,7 +19,7 @@ def test_doc_needextend_html(test_app: Sphinx, snapshot):
     app.build()
 
     needs_data = json.loads(Path(app.outdir, "needs.json").read_text())
-    assert needs_data == snapshot(exclude=props("created", "project"))
+    assert needs_data == snapshot(exclude=props("created", "project", "creator"))
 
     index_html = Path(app.outdir, "index.html").read_text()
     assert "extend_test_003" in index_html
@@ -102,4 +102,4 @@ def test_doc_needextend_dynamic(test_app, snapshot):
     # assert app._warning.getvalue() == ""
 
     needs_data = json.loads(Path(app.outdir, "needs.json").read_text())
-    assert needs_data == snapshot(exclude=props("created", "project"))
+    assert needs_data == snapshot(exclude=props("created", "project", "creator"))
diff --git a/tests/test_needimport.py b/tests/test_needimport.py
index bd0649a4..8a0cd5fb 100644
--- a/tests/test_needimport.py
+++ b/tests/test_needimport.py
@@ -141,7 +141,7 @@ def test_import_builder(test_app, snapshot):
     app.build()
     needs_text = Path(app.outdir, "needs.json").read_text()
     needs = json.loads(needs_text)
-    assert needs == snapshot(exclude=props("created", "project"))
+    assert needs == snapshot(exclude=props("created", "project", "creator"))
 
 
 @pytest.mark.parametrize(
diff --git a/tests/test_needs_builder.py b/tests/test_needs_builder.py
index 0de74900..e0e9aaf5 100644
--- a/tests/test_needs_builder.py
+++ b/tests/test_needs_builder.py
@@ -17,7 +17,7 @@ def test_doc_needs_builder(test_app, snapshot):
     app.build()
 
     needs_list = json.loads(Path(app.outdir, "needs.json").read_text())
-    assert needs_list == snapshot(exclude=props("created", "project"))
+    assert needs_list == snapshot(exclude=props("created", "project", "creator"))
 
 
 @pytest.mark.parametrize(
@@ -36,7 +36,7 @@ def test_doc_needs_builder_reproducible(test_app, snapshot):
     app.build()
 
     needs_list = json.loads(Path(app.outdir, "needs.json").read_text())
-    assert needs_list == snapshot(exclude=props("project"))
+    assert needs_list == snapshot(exclude=props("project", "creator"))
 
 
 @pytest.mark.parametrize(
@@ -55,7 +55,7 @@ def test_doc_needs_builder_remove_defaults(test_app, snapshot):
     app.build()
 
     needs_list = json.loads(Path(app.outdir, "needs.json").read_text())
-    assert needs_list == snapshot(exclude=props("created", "project"))
+    assert needs_list == snapshot(exclude=props("created", "project", "creator"))
 
 
 @pytest.mark.parametrize(
diff --git a/tests/test_needs_id_builder.py b/tests/test_needs_id_builder.py
index 7cf7d697..5ae01a95 100644
--- a/tests/test_needs_id_builder.py
+++ b/tests/test_needs_id_builder.py
@@ -22,4 +22,4 @@ def test_doc_needs_id_builder(test_app, snapshot):
     data = {
         path.name: json.loads(path.read_text()) for path in needs_id_path.glob("*.json")
     }
-    assert data == snapshot(exclude=props("created", "project"))
+    assert data == snapshot(exclude=props("created", "project", "creator"))
diff --git a/tests/test_needuml.py b/tests/test_needuml.py
index 41f166fd..2e8ca0c0 100644
--- a/tests/test_needuml.py
+++ b/tests/test_needuml.py
@@ -20,7 +20,7 @@ def test_doc_build_html(test_app, snapshot):
     all_needs = dict(SphinxNeedsData(app.env).get_needs_view())
     assert all_needs == snapshot()
 
-    all_needumls = app.env.needs_all_needumls
+    all_needumls = app.env._needs_all_needumls
     assert all_needumls == snapshot
 
 
@@ -169,7 +169,7 @@ def test_needuml_filter(test_app, snapshot):
     app = test_app
     app.build()
 
-    all_needumls = app.env.needs_all_needumls
+    all_needumls = app.env._needs_all_needumls
     assert all_needumls == snapshot
 
     html = Path(app.outdir, "index.html").read_text(encoding="utf8")
@@ -193,7 +193,7 @@ def test_needuml_jinja_func_flow(test_app, snapshot):
     app = test_app
     app.build()
 
-    all_needumls = app.env.needs_all_needumls
+    all_needumls = app.env._needs_all_needumls
     assert all_needumls == snapshot
 
     html = Path(app.outdir, "index.html").read_text(encoding="utf8")
@@ -267,7 +267,7 @@ def test_needuml_jinja_func_ref(test_app, snapshot):
     app = test_app
     app.build()
 
-    all_needumls = app.env.needs_all_needumls
+    all_needumls = app.env._needs_all_needumls
     assert all_needumls == snapshot
 
     html = Path(app.outdir, "index.html").read_text(encoding="utf8")
diff --git a/tests/test_open_needs_service.py b/tests/test_open_needs_service.py
index 0f0592e2..211eff3e 100644
--- a/tests/test_open_needs_service.py
+++ b/tests/test_open_needs_service.py
@@ -91,9 +91,9 @@ def test_ons_service(test_app):
     )
 
     test_app.build()
-    assert isinstance(test_app.needs_services, ServiceManager)
+    assert isinstance(test_app._needs_services, ServiceManager)
 
-    manager = test_app.needs_services
+    manager = test_app._needs_services
     service = manager.get("open-needs")
     assert hasattr(service, "content")
 
diff --git a/tests/test_service_github.py b/tests/test_service_github.py
index 8055f864..17b0539b 100644
--- a/tests/test_service_github.py
+++ b/tests/test_service_github.py
@@ -97,7 +97,9 @@ def test_build(test_app, snapshot):
     assert warnings.splitlines() == expected_warnings
 
     needs_data = json.loads((Path(app.outdir) / "needs.json").read_text("utf8"))
-    assert needs_data == snapshot(exclude=props("created", "project", "avatar"))
+    assert needs_data == snapshot(
+        exclude=props("created", "project", "avatar", "creator")
+    )
 
 
 ISSUE_RESPONSE = {
diff --git a/tests/test_services/test_service_basics.py b/tests/test_services/test_service_basics.py
index f0b3254f..89e8e052 100644
--- a/tests/test_services/test_service_basics.py
+++ b/tests/test_services/test_service_basics.py
@@ -61,9 +61,9 @@ class NoDebugService(BaseService):
 def test_service_creation(test_app):
     app = test_app
     app.build()
-    assert isinstance(app.needs_services, ServiceManager)
+    assert isinstance(app._needs_services, ServiceManager)
 
-    manager = app.needs_services
+    manager = app._needs_services
     service = manager.get("testservice")
     assert hasattr(service, "custom_option")