devpi-web 4.3.0__tar.gz → 5.0.0__tar.gz
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.
- {devpi-web-4.3.0 → devpi_web-5.0.0}/CHANGELOG +58 -0
- devpi_web-5.0.0/CHANGELOG.short.rst +119 -0
- {devpi-web-4.3.0 → devpi_web-5.0.0}/PKG-INFO +85 -44
- devpi_web-5.0.0/devpi_web/__init__.py +1 -0
- {devpi-web-4.3.0 → devpi_web-5.0.0}/devpi_web/clear_index.py +4 -3
- devpi_web-5.0.0/devpi_web/compat.py +9 -0
- {devpi-web-4.3.0 → devpi_web-5.0.0}/devpi_web/doczip.py +81 -87
- {devpi-web-4.3.0 → devpi_web-5.0.0}/devpi_web/indexing.py +1 -0
- devpi_web-5.0.0/devpi_web/macroregistry.py +362 -0
- devpi_web-5.0.0/devpi_web/macros.py +121 -0
- {devpi-web-4.3.0 → devpi_web-5.0.0}/devpi_web/main.py +49 -25
- devpi_web-5.0.0/devpi_web/static/search.js +25 -0
- {devpi-web-4.3.0 → devpi_web-5.0.0}/devpi_web/static/style.css +4 -0
- devpi_web-5.0.0/devpi_web/templates/favicon.pt +1 -0
- devpi_web-5.0.0/devpi_web/templates/footer.pt +4 -0
- devpi_web-5.0.0/devpi_web/templates/footer_versions.pt +3 -0
- devpi_web-5.0.0/devpi_web/templates/head.pt +3 -0
- devpi_web-5.0.0/devpi_web/templates/header.pt +9 -0
- devpi_web-5.0.0/devpi_web/templates/header_breadcrumbs.pt +3 -0
- devpi_web-5.0.0/devpi_web/templates/header_search.pt +14 -0
- devpi_web-5.0.0/devpi_web/templates/header_status.pt +11 -0
- devpi_web-5.0.0/devpi_web/templates/html_head_css.pt +4 -0
- devpi_web-5.0.0/devpi_web/templates/html_head_scripts.pt +4 -0
- devpi_web-5.0.0/devpi_web/templates/logo.pt +1 -0
- devpi_web-5.0.0/devpi_web/templates/query_docs.pt +1 -0
- devpi_web-5.0.0/devpi_web/templates/root_above_user_index_list.pt +0 -0
- devpi_web-5.0.0/devpi_web/templates/root_below_user_index_list.pt +0 -0
- devpi_web-5.0.0/devpi_web/templates/status_badge.pt +4 -0
- {devpi-web-4.3.0 → devpi_web-5.0.0}/devpi_web/views.py +66 -40
- {devpi-web-4.3.0 → devpi_web-5.0.0}/devpi_web/whoosh_index.py +5 -9
- {devpi-web-4.3.0 → devpi_web-5.0.0}/devpi_web.egg-info/PKG-INFO +85 -44
- {devpi-web-4.3.0 → devpi_web-5.0.0}/devpi_web.egg-info/SOURCES.txt +21 -5
- {devpi-web-4.3.0 → devpi_web-5.0.0}/devpi_web.egg-info/requires.txt +7 -4
- devpi_web-5.0.0/mypy.ini +42 -0
- devpi_web-5.0.0/pyproject.toml +195 -0
- devpi_web-5.0.0/setup.cfg +4 -0
- devpi_web-5.0.0/tests/conftest.py +60 -0
- {devpi-web-4.3.0 → devpi_web-5.0.0}/tests/test_indexing.py +15 -17
- devpi_web-5.0.0/tests/test_macro_registry.py +30 -0
- {devpi-web-4.3.0 → devpi_web-5.0.0}/tests/test_main.py +37 -14
- devpi_web-5.0.0/tests/test_theme.py +204 -0
- {devpi-web-4.3.0 → devpi_web-5.0.0}/tests/test_views_docs.py +3 -2
- {devpi-web-4.3.0 → devpi_web-5.0.0}/tests/test_views_misc.py +14 -6
- {devpi-web-4.3.0 → devpi_web-5.0.0}/tests/test_views_search.py +2 -3
- {devpi-web-4.3.0 → devpi_web-5.0.0}/tests/test_views_toxresults.py +1 -2
- {devpi-web-4.3.0 → devpi_web-5.0.0}/tox.ini +15 -10
- devpi-web-4.3.0/AUTHORS +0 -7
- devpi-web-4.3.0/devpi_web/__init__.py +0 -1
- devpi-web-4.3.0/devpi_web/compat.py +0 -42
- devpi-web-4.3.0/devpi_web/templates/macros.pt +0 -114
- devpi-web-4.3.0/devpi_web.egg-info/not-zip-safe +0 -1
- devpi-web-4.3.0/pyproject.toml +0 -83
- devpi-web-4.3.0/setup.cfg +0 -7
- devpi-web-4.3.0/setup.py +0 -77
- devpi-web-4.3.0/tests/conftest.py +0 -65
- devpi-web-4.3.0/tests/test_theme.py +0 -47
- {devpi-web-4.3.0 → devpi_web-5.0.0}/.flake8 +0 -0
- {devpi-web-4.3.0 → devpi_web-5.0.0}/LICENSE +0 -0
- {devpi-web-4.3.0 → devpi_web-5.0.0}/MANIFEST.in +0 -0
- {devpi-web-4.3.0 → devpi_web-5.0.0}/README.rst +0 -0
- {devpi-web-4.3.0 → devpi_web-5.0.0}/devpi_web/config.py +0 -0
- {devpi-web-4.3.0 → devpi_web-5.0.0}/devpi_web/description.py +0 -0
- {devpi-web-4.3.0 → devpi_web-5.0.0}/devpi_web/hookspecs.py +0 -0
- {devpi-web-4.3.0 → devpi_web-5.0.0}/devpi_web/null_index.py +0 -0
- {devpi-web-4.3.0 → devpi_web-5.0.0}/devpi_web/static/common.js +0 -0
- {devpi-web-4.3.0 → devpi_web-5.0.0}/devpi_web/static/docview.js +0 -0
- {devpi-web-4.3.0 → devpi_web-5.0.0}/devpi_web/static/favicon.ico +0 -0
- {devpi-web-4.3.0 → devpi_web-5.0.0}/devpi_web/static/jquery-3.6.0.min.js +0 -0
- {devpi-web-4.3.0 → devpi_web-5.0.0}/devpi_web/templates/doc.pt +0 -0
- {devpi-web-4.3.0 → devpi_web-5.0.0}/devpi_web/templates/error.pt +0 -0
- {devpi-web-4.3.0 → devpi_web-5.0.0}/devpi_web/templates/index.pt +0 -0
- {devpi-web-4.3.0 → devpi_web-5.0.0}/devpi_web/templates/notfound.pt +0 -0
- {devpi-web-4.3.0 → devpi_web-5.0.0}/devpi_web/templates/project.pt +0 -0
- {devpi-web-4.3.0 → devpi_web-5.0.0}/devpi_web/templates/root.pt +0 -0
- {devpi-web-4.3.0 → devpi_web-5.0.0}/devpi_web/templates/search.pt +0 -0
- {devpi-web-4.3.0 → devpi_web-5.0.0}/devpi_web/templates/search_help.pt +0 -0
- {devpi-web-4.3.0 → devpi_web-5.0.0}/devpi_web/templates/status.pt +0 -0
- {devpi-web-4.3.0 → devpi_web-5.0.0}/devpi_web/templates/toxresult.pt +0 -0
- {devpi-web-4.3.0 → devpi_web-5.0.0}/devpi_web/templates/toxresults.pt +0 -0
- {devpi-web-4.3.0 → devpi_web-5.0.0}/devpi_web/templates/user.pt +0 -0
- {devpi-web-4.3.0 → devpi_web-5.0.0}/devpi_web/templates/version.pt +0 -0
- {devpi-web-4.3.0 → devpi_web-5.0.0}/devpi_web.egg-info/dependency_links.txt +0 -0
- {devpi-web-4.3.0 → devpi_web-5.0.0}/devpi_web.egg-info/entry_points.txt +0 -0
- {devpi-web-4.3.0 → devpi_web-5.0.0}/devpi_web.egg-info/top_level.txt +0 -0
- {devpi-web-4.3.0 → devpi_web-5.0.0}/tests/test_views.py +0 -0
- {devpi-web-4.3.0 → devpi_web-5.0.0}/tests/test_whoosh_index.py +0 -0
|
@@ -2,6 +2,64 @@
|
|
|
2
2
|
|
|
3
3
|
.. towncrier release notes start
|
|
4
4
|
|
|
5
|
+
5.0.0 (2025-06-12)
|
|
6
|
+
==================
|
|
7
|
+
|
|
8
|
+
Deprecations and Removals
|
|
9
|
+
-------------------------
|
|
10
|
+
|
|
11
|
+
- Removed ``macros.pt``, the contained macros have all been moved to separate templates. See other news entries for details.
|
|
12
|
+
|
|
13
|
+
- Remove support for Python below 3.9. In the future end of life Python 3 versions aren't supported anymore.
|
|
14
|
+
|
|
15
|
+
- Future releases will more often require newer devpi-server than before.
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
Bug Fixes
|
|
20
|
+
---------
|
|
21
|
+
|
|
22
|
+
- Fix #930: remove remaining uses of unmaintained py library.
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
Other Changes
|
|
27
|
+
-------------
|
|
28
|
+
|
|
29
|
+
- style.css: Added styling for readme/description code block / literals.
|
|
30
|
+
|
|
31
|
+
- macros.pt (``navigation`` macro): Move ``breadcrumbs`` out of ``navigation`` macro to separate ``header_breadcrumbs.pt`` template.
|
|
32
|
+
|
|
33
|
+
- macros.pt (``head`` macro): Move ``favicon`` out of ``head`` macro to separate ``favicon.pt`` template.
|
|
34
|
+
|
|
35
|
+
- macros.pt: Move ``footer`` macro to separate ``footer.pt`` template.
|
|
36
|
+
|
|
37
|
+
- macros.pt: Move ``head`` macro to separate ``head.pt`` template.
|
|
38
|
+
|
|
39
|
+
- macros.pt: Move ``headcss`` macro to separate ``html_head_css.pt`` template.
|
|
40
|
+
|
|
41
|
+
- macros.pt: Move ``headscript`` macro to separate ``html_head_scripts.pt`` template.
|
|
42
|
+
|
|
43
|
+
- macros.pt: Move ``logo`` macro to separate ``logo.pt`` template.
|
|
44
|
+
|
|
45
|
+
- macros.pt: Move ``navigation`` macro to separate ``header.pt`` template.
|
|
46
|
+
|
|
47
|
+
- macros.pt: Move ``query_doc`` macro to separate ``query_doc.pt`` template.
|
|
48
|
+
|
|
49
|
+
- macros.pt: Move ``rootaboveuserindexlist`` macro to separate ``root_above_user_index_list.pt`` template.
|
|
50
|
+
|
|
51
|
+
- macros.pt: Move ``rootbelowuserindexlist`` macro to separate ``root_below_user_index_list.pt`` template.
|
|
52
|
+
|
|
53
|
+
- macros.pt: Move ``search`` macro to separate ``header_search.pt`` template.
|
|
54
|
+
|
|
55
|
+
- macros.pt: Move ``status`` macro to separate ``header_status.pt`` template.
|
|
56
|
+
|
|
57
|
+
- macros.pt: Move ``statusbadge`` macro to separate ``status_badge.pt`` template.
|
|
58
|
+
|
|
59
|
+
- macros.pt: Move ``versions`` macro to separate ``footer_versions.pt`` template.
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
|
|
5
63
|
4.3.0 (2024-10-16)
|
|
6
64
|
==================
|
|
7
65
|
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
=========
|
|
4
|
+
Changelog
|
|
5
|
+
=========
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
.. towncrier release notes start
|
|
11
|
+
|
|
12
|
+
5.0.0 (2025-06-12)
|
|
13
|
+
==================
|
|
14
|
+
|
|
15
|
+
Deprecations and Removals
|
|
16
|
+
-------------------------
|
|
17
|
+
|
|
18
|
+
- Removed ``macros.pt``, the contained macros have all been moved to separate templates. See other news entries for details.
|
|
19
|
+
|
|
20
|
+
- Remove support for Python below 3.9. In the future end of life Python 3 versions aren't supported anymore.
|
|
21
|
+
|
|
22
|
+
- Future releases will more often require newer devpi-server than before.
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
Bug Fixes
|
|
27
|
+
---------
|
|
28
|
+
|
|
29
|
+
- Fix #930: remove remaining uses of unmaintained py library.
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
Other Changes
|
|
34
|
+
-------------
|
|
35
|
+
|
|
36
|
+
- style.css: Added styling for readme/description code block / literals.
|
|
37
|
+
|
|
38
|
+
- macros.pt (``navigation`` macro): Move ``breadcrumbs`` out of ``navigation`` macro to separate ``header_breadcrumbs.pt`` template.
|
|
39
|
+
|
|
40
|
+
- macros.pt (``head`` macro): Move ``favicon`` out of ``head`` macro to separate ``favicon.pt`` template.
|
|
41
|
+
|
|
42
|
+
- macros.pt: Move ``footer`` macro to separate ``footer.pt`` template.
|
|
43
|
+
|
|
44
|
+
- macros.pt: Move ``head`` macro to separate ``head.pt`` template.
|
|
45
|
+
|
|
46
|
+
- macros.pt: Move ``headcss`` macro to separate ``html_head_css.pt`` template.
|
|
47
|
+
|
|
48
|
+
- macros.pt: Move ``headscript`` macro to separate ``html_head_scripts.pt`` template.
|
|
49
|
+
|
|
50
|
+
- macros.pt: Move ``logo`` macro to separate ``logo.pt`` template.
|
|
51
|
+
|
|
52
|
+
- macros.pt: Move ``navigation`` macro to separate ``header.pt`` template.
|
|
53
|
+
|
|
54
|
+
- macros.pt: Move ``query_doc`` macro to separate ``query_doc.pt`` template.
|
|
55
|
+
|
|
56
|
+
- macros.pt: Move ``rootaboveuserindexlist`` macro to separate ``root_above_user_index_list.pt`` template.
|
|
57
|
+
|
|
58
|
+
- macros.pt: Move ``rootbelowuserindexlist`` macro to separate ``root_below_user_index_list.pt`` template.
|
|
59
|
+
|
|
60
|
+
- macros.pt: Move ``search`` macro to separate ``header_search.pt`` template.
|
|
61
|
+
|
|
62
|
+
- macros.pt: Move ``status`` macro to separate ``header_status.pt`` template.
|
|
63
|
+
|
|
64
|
+
- macros.pt: Move ``statusbadge`` macro to separate ``status_badge.pt`` template.
|
|
65
|
+
|
|
66
|
+
- macros.pt: Move ``versions`` macro to separate ``footer_versions.pt`` template.
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
4.3.0 (2024-10-16)
|
|
71
|
+
==================
|
|
72
|
+
|
|
73
|
+
Features
|
|
74
|
+
--------
|
|
75
|
+
|
|
76
|
+
- index.pt, project.pt, version.pt: Fix #1062: Added a link to download the documentation as zip-file to the index, project and version view.
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
4.2.3 (2024-09-19)
|
|
81
|
+
==================
|
|
82
|
+
|
|
83
|
+
Bug Fixes
|
|
84
|
+
---------
|
|
85
|
+
|
|
86
|
+
- Fix deprecation warnings from devpi-server 6.13.0.
|
|
87
|
+
|
|
88
|
+
- Lazily evaluate file information. Especially with devpi-postgresql this safes many database accesses on most pages.
|
|
89
|
+
|
|
90
|
+
- Guard against missing doczip files, which can happen on replicas during replication.
|
|
91
|
+
|
|
92
|
+
- Increase threshold for index status from 60 s to 300 s for warnings and from 300 s to 3600 s for fatal.
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
4.2.2 (2024-04-20)
|
|
97
|
+
==================
|
|
98
|
+
|
|
99
|
+
Bug Fixes
|
|
100
|
+
---------
|
|
101
|
+
|
|
102
|
+
- style.css: Always let content be full browser height. This also gives more height with some documentation themes when content is short.
|
|
103
|
+
|
|
104
|
+
- style.css: set ``scrollbar-gutter: stable`` on ``body`` to prevent jumping content in documentation iframe.
|
|
105
|
+
|
|
106
|
+
- Fix #970: overwrite fixed html/body heights like ``100%`` in documentation iframe content.
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
4.2.1 (2023-07-02)
|
|
111
|
+
==================
|
|
112
|
+
|
|
113
|
+
Bug Fixes
|
|
114
|
+
---------
|
|
115
|
+
|
|
116
|
+
- Fix #953: Exception when browsers send ETag for documentation pages.
|
|
117
|
+
|
|
118
|
+
- Fix #980: Remove long deprecated backward compatibility for old pluggy versions to fix error with pluggy 1.1.0.
|
|
119
|
+
|
|
@@ -1,36 +1,44 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: devpi-web
|
|
3
|
-
Version:
|
|
3
|
+
Version: 5.0.0
|
|
4
4
|
Summary: devpi-web: a web view for devpi-server
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Maintainer-email: mail@pyfidelity.com
|
|
8
|
-
License: MIT
|
|
5
|
+
Maintainer-email: Florian Schulze <mail@pyfidelity.com>
|
|
6
|
+
License-Expression: MIT
|
|
9
7
|
Project-URL: Bug Tracker, https://github.com/devpi/devpi/issues
|
|
10
8
|
Project-URL: Changelog, https://github.com/devpi/devpi/blob/main/web/CHANGELOG
|
|
11
9
|
Project-URL: Documentation, https://doc.devpi.net
|
|
10
|
+
Project-URL: Homepage, https://devpi.net
|
|
12
11
|
Project-URL: Source Code, https://github.com/devpi/devpi
|
|
13
12
|
Classifier: Development Status :: 5 - Production/Stable
|
|
14
13
|
Classifier: Environment :: Web Environment
|
|
15
14
|
Classifier: Intended Audience :: Developers
|
|
16
15
|
Classifier: Intended Audience :: System Administrators
|
|
17
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
18
16
|
Classifier: Programming Language :: Python
|
|
19
|
-
Classifier:
|
|
20
|
-
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
21
|
-
Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application
|
|
22
|
-
Classifier: Programming Language :: Python :: 3.4
|
|
23
|
-
Classifier: Programming Language :: Python :: 3.5
|
|
24
|
-
Classifier: Programming Language :: Python :: 3.6
|
|
25
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
26
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
17
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
27
18
|
Classifier: Programming Language :: Python :: 3.9
|
|
28
19
|
Classifier: Programming Language :: Python :: 3.10
|
|
29
20
|
Classifier: Programming Language :: Python :: 3.11
|
|
30
21
|
Classifier: Programming Language :: Python :: 3.12
|
|
31
|
-
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
24
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
25
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application
|
|
26
|
+
Requires-Python: >=3.9
|
|
27
|
+
Description-Content-Type: text/x-rst
|
|
32
28
|
License-File: LICENSE
|
|
33
|
-
|
|
29
|
+
Requires-Dist: Whoosh<3
|
|
30
|
+
Requires-Dist: attrs>=22.2.0
|
|
31
|
+
Requires-Dist: beautifulsoup4!=4.12.1,>=4.3.2
|
|
32
|
+
Requires-Dist: defusedxml
|
|
33
|
+
Requires-Dist: devpi-server>=6.13.0
|
|
34
|
+
Requires-Dist: devpi-common>=4.0.0
|
|
35
|
+
Requires-Dist: docutils>=0.11
|
|
36
|
+
Requires-Dist: pygments>=1.6
|
|
37
|
+
Requires-Dist: pyramid>=2
|
|
38
|
+
Requires-Dist: pyramid-chameleon
|
|
39
|
+
Requires-Dist: readme-renderer[md]>=23.0
|
|
40
|
+
Requires-Dist: tomli; python_version < "3.11"
|
|
41
|
+
Dynamic: license-file
|
|
34
42
|
|
|
35
43
|
================================================
|
|
36
44
|
devpi-web: web interface plugin for devpi-server
|
|
@@ -69,14 +77,74 @@ For support contracts and paid help contact ``mail at pyfidelity.com``.
|
|
|
69
77
|
.. _GitHub Discussions: https://github.com/devpi/devpi/discussions
|
|
70
78
|
|
|
71
79
|
|
|
80
|
+
|
|
72
81
|
=========
|
|
73
82
|
Changelog
|
|
74
83
|
=========
|
|
75
84
|
|
|
76
85
|
|
|
77
86
|
|
|
87
|
+
|
|
78
88
|
.. towncrier release notes start
|
|
79
89
|
|
|
90
|
+
5.0.0 (2025-06-12)
|
|
91
|
+
==================
|
|
92
|
+
|
|
93
|
+
Deprecations and Removals
|
|
94
|
+
-------------------------
|
|
95
|
+
|
|
96
|
+
- Removed ``macros.pt``, the contained macros have all been moved to separate templates. See other news entries for details.
|
|
97
|
+
|
|
98
|
+
- Remove support for Python below 3.9. In the future end of life Python 3 versions aren't supported anymore.
|
|
99
|
+
|
|
100
|
+
- Future releases will more often require newer devpi-server than before.
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
Bug Fixes
|
|
105
|
+
---------
|
|
106
|
+
|
|
107
|
+
- Fix #930: remove remaining uses of unmaintained py library.
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
Other Changes
|
|
112
|
+
-------------
|
|
113
|
+
|
|
114
|
+
- style.css: Added styling for readme/description code block / literals.
|
|
115
|
+
|
|
116
|
+
- macros.pt (``navigation`` macro): Move ``breadcrumbs`` out of ``navigation`` macro to separate ``header_breadcrumbs.pt`` template.
|
|
117
|
+
|
|
118
|
+
- macros.pt (``head`` macro): Move ``favicon`` out of ``head`` macro to separate ``favicon.pt`` template.
|
|
119
|
+
|
|
120
|
+
- macros.pt: Move ``footer`` macro to separate ``footer.pt`` template.
|
|
121
|
+
|
|
122
|
+
- macros.pt: Move ``head`` macro to separate ``head.pt`` template.
|
|
123
|
+
|
|
124
|
+
- macros.pt: Move ``headcss`` macro to separate ``html_head_css.pt`` template.
|
|
125
|
+
|
|
126
|
+
- macros.pt: Move ``headscript`` macro to separate ``html_head_scripts.pt`` template.
|
|
127
|
+
|
|
128
|
+
- macros.pt: Move ``logo`` macro to separate ``logo.pt`` template.
|
|
129
|
+
|
|
130
|
+
- macros.pt: Move ``navigation`` macro to separate ``header.pt`` template.
|
|
131
|
+
|
|
132
|
+
- macros.pt: Move ``query_doc`` macro to separate ``query_doc.pt`` template.
|
|
133
|
+
|
|
134
|
+
- macros.pt: Move ``rootaboveuserindexlist`` macro to separate ``root_above_user_index_list.pt`` template.
|
|
135
|
+
|
|
136
|
+
- macros.pt: Move ``rootbelowuserindexlist`` macro to separate ``root_below_user_index_list.pt`` template.
|
|
137
|
+
|
|
138
|
+
- macros.pt: Move ``search`` macro to separate ``header_search.pt`` template.
|
|
139
|
+
|
|
140
|
+
- macros.pt: Move ``status`` macro to separate ``header_status.pt`` template.
|
|
141
|
+
|
|
142
|
+
- macros.pt: Move ``statusbadge`` macro to separate ``status_badge.pt`` template.
|
|
143
|
+
|
|
144
|
+
- macros.pt: Move ``versions`` macro to separate ``footer_versions.pt`` template.
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
|
|
80
148
|
4.3.0 (2024-10-16)
|
|
81
149
|
==================
|
|
82
150
|
|
|
@@ -127,30 +195,3 @@ Bug Fixes
|
|
|
127
195
|
|
|
128
196
|
- Fix #980: Remove long deprecated backward compatibility for old pluggy versions to fix error with pluggy 1.1.0.
|
|
129
197
|
|
|
130
|
-
|
|
131
|
-
4.2.0 (2022-12-05)
|
|
132
|
-
==================
|
|
133
|
-
|
|
134
|
-
Features
|
|
135
|
-
--------
|
|
136
|
-
|
|
137
|
-
- Set ETag header to the doczip hash and max-age to 60 seconds for all documentation files.
|
|
138
|
-
|
|
139
|
-
- Add ``--keep-docs-packed`` option.
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
Bug Fixes
|
|
143
|
-
---------
|
|
144
|
-
|
|
145
|
-
- common.js, macros.pt: Fix #823: Remove moment.js and update jquery to 3.6.0.
|
|
146
|
-
|
|
147
|
-
- common.js: Fix #764: Jumping to anchors with whitespace in documentation now works.
|
|
148
|
-
|
|
149
|
-
- doc.pt, docview.js, style.css: Fix #764: Rewrote setting height of documentation iframe which also fixes scrolling to anchors generated by JavaScript.
|
|
150
|
-
|
|
151
|
-
- Fix project names from mirrors with devpi-server >= 6.8.0.
|
|
152
|
-
|
|
153
|
-
- Fix exception in not found page of project URLs.
|
|
154
|
-
|
|
155
|
-
- toxresults.pt, version.pt: Fix anchor generation for toxresults URLs.
|
|
156
|
-
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "5.0.0"
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
+
from devpi_common.terminal import TerminalWriter
|
|
1
2
|
from devpi_server.config import MyArgumentParser
|
|
2
3
|
from devpi_server.config import add_configfile_option
|
|
3
4
|
from devpi_server.config import add_help_option
|
|
4
5
|
from devpi_server.config import add_storage_options
|
|
5
|
-
from devpi_server.config import
|
|
6
|
+
from devpi_server.config import get_pluginmanager
|
|
7
|
+
from devpi_server.config import parseoptions
|
|
6
8
|
from devpi_server.log import configure_cli_logging
|
|
7
9
|
from devpi_server.main import Fatal
|
|
8
10
|
from devpi_server.main import xom_from_config
|
|
9
11
|
from devpi_web.config import add_indexer_backend_option
|
|
10
12
|
from devpi_web.main import get_indexer
|
|
11
|
-
import py
|
|
12
13
|
import sys
|
|
13
14
|
|
|
14
15
|
|
|
@@ -37,6 +38,6 @@ def clear_index(argv=None):
|
|
|
37
38
|
ix.delete_index()
|
|
38
39
|
log.info("Index deleted, start devpi-server again to let the index rebuild automatically.")
|
|
39
40
|
except Fatal as e:
|
|
40
|
-
tw =
|
|
41
|
+
tw = TerminalWriter(sys.stderr)
|
|
41
42
|
tw.line("fatal: %s" % e.args[0], red=True)
|
|
42
43
|
return 1
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
from bs4 import BeautifulSoup
|
|
2
|
-
from collections.abc import MutableMapping
|
|
2
|
+
from collections.abc import MutableMapping
|
|
3
3
|
from contextlib import contextmanager
|
|
4
|
+
from contextlib import suppress
|
|
4
5
|
from devpi_common.archive import Archive
|
|
5
6
|
from devpi_common.types import cached_property
|
|
6
7
|
from devpi_common.validation import normalize_name
|
|
7
8
|
from devpi_server.log import threadlog
|
|
8
|
-
from
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
import itertools
|
|
9
11
|
import json
|
|
10
|
-
import
|
|
12
|
+
import shutil
|
|
11
13
|
|
|
12
14
|
|
|
13
15
|
try:
|
|
@@ -18,21 +20,20 @@ except ImportError:
|
|
|
18
20
|
|
|
19
21
|
def get_unpack_path(stage, name, version):
|
|
20
22
|
path = stage.xom.config.args.documentation_path
|
|
21
|
-
if path is None
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
return path.join(
|
|
26
|
-
stage.user.name, stage.index, normalize_name(name), version, "+doc")
|
|
23
|
+
path = stage.keyfs.base_path if path is None else Path(path)
|
|
24
|
+
return path.joinpath(
|
|
25
|
+
stage.user.name, stage.index, normalize_name(name), version, "+doc"
|
|
26
|
+
)
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
@contextmanager
|
|
30
|
-
def locked_unpack_path(stage, name, version, remove_lock_file=False):
|
|
30
|
+
def locked_unpack_path(stage, name, version, *, remove_lock_file=False):
|
|
31
31
|
unpack_path = get_unpack_path(stage, name, version)
|
|
32
32
|
# we are using the hash file as a lock file
|
|
33
|
-
hash_path = unpack_path.
|
|
33
|
+
hash_path = unpack_path.with_suffix(".hash")
|
|
34
34
|
try:
|
|
35
|
-
|
|
35
|
+
hash_path.parent.mkdir(parents=True, exist_ok=True)
|
|
36
|
+
with hash_path.open("a+") as hash_file:
|
|
36
37
|
if fcntl:
|
|
37
38
|
fcntl.flock(hash_file, fcntl.LOCK_EX)
|
|
38
39
|
try:
|
|
@@ -42,11 +43,9 @@ def locked_unpack_path(stage, name, version, remove_lock_file=False):
|
|
|
42
43
|
fcntl.flock(hash_file, fcntl.LOCK_UN)
|
|
43
44
|
finally:
|
|
44
45
|
if remove_lock_file and hash_path.exists():
|
|
45
|
-
|
|
46
|
-
hash_path.remove()
|
|
47
|
-
except py.error.ENOENT:
|
|
46
|
+
with suppress(FileNotFoundError):
|
|
48
47
|
# there is a rare possibility of a race condition here
|
|
49
|
-
|
|
48
|
+
hash_path.unlink()
|
|
50
49
|
|
|
51
50
|
|
|
52
51
|
def keep_docs_packed(config):
|
|
@@ -60,23 +59,21 @@ def docs_exist(stage, name, version, entry):
|
|
|
60
59
|
def docs_file_content(stage, name, version, entry, relpath):
|
|
61
60
|
if not keep_docs_packed(stage.xom.config):
|
|
62
61
|
return None
|
|
63
|
-
with entry.file_open_read() as f:
|
|
64
|
-
|
|
65
|
-
return archive.read(relpath)
|
|
62
|
+
with entry.file_open_read() as f, Archive(f) as archive:
|
|
63
|
+
return archive.read(relpath)
|
|
66
64
|
|
|
67
65
|
|
|
68
66
|
def docs_file_exists(stage, name, version, entry, relpath):
|
|
69
67
|
if keep_docs_packed(stage.xom.config):
|
|
70
|
-
with entry.file_open_read() as f:
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
return False
|
|
68
|
+
with entry.file_open_read() as f, Archive(f) as archive:
|
|
69
|
+
try:
|
|
70
|
+
if archive.getfile(relpath):
|
|
71
|
+
return True
|
|
72
|
+
except archive.FileNotExist:
|
|
73
|
+
return False
|
|
77
74
|
else:
|
|
78
75
|
doc_path = unpack_docs(stage, name, version, entry)
|
|
79
|
-
if doc_path.
|
|
76
|
+
if doc_path.joinpath(relpath).is_file():
|
|
80
77
|
return True
|
|
81
78
|
return False
|
|
82
79
|
|
|
@@ -85,7 +82,7 @@ def docs_file_path(stage, name, version, entry, relpath):
|
|
|
85
82
|
if keep_docs_packed(stage.xom.config):
|
|
86
83
|
return None
|
|
87
84
|
doc_path = unpack_docs(stage, name, version, entry)
|
|
88
|
-
return doc_path.
|
|
85
|
+
return doc_path.joinpath(relpath)
|
|
89
86
|
|
|
90
87
|
|
|
91
88
|
def unpack_docs(stage, name, version, entry):
|
|
@@ -93,21 +90,18 @@ def unpack_docs(stage, name, version, entry):
|
|
|
93
90
|
# we are not losing the original zip file anyway
|
|
94
91
|
with locked_unpack_path(stage, name, version) as (hash_file, unpack_path):
|
|
95
92
|
hash_file.seek(0)
|
|
96
|
-
if hash_file.read().strip() ==
|
|
93
|
+
if hash_file.read().strip() == entry.best_available_hash_spec:
|
|
97
94
|
return unpack_path
|
|
98
95
|
if unpack_path.exists():
|
|
99
|
-
|
|
100
|
-
unpack_path.remove()
|
|
101
|
-
except py.error.ENOENT:
|
|
96
|
+
with suppress(FileNotFoundError):
|
|
102
97
|
# there is a rare possibility of a race condition here
|
|
103
|
-
|
|
98
|
+
unpack_path.unlink()
|
|
104
99
|
if not entry.file_exists():
|
|
105
100
|
return unpack_path
|
|
106
|
-
with entry.file_open_read() as f:
|
|
107
|
-
|
|
108
|
-
archive.extract(unpack_path)
|
|
101
|
+
with entry.file_open_read() as f, Archive(f) as archive:
|
|
102
|
+
archive.extract(unpack_path)
|
|
109
103
|
hash_file.seek(0)
|
|
110
|
-
hash_file.write(
|
|
104
|
+
hash_file.write(entry.best_available_hash_spec)
|
|
111
105
|
hash_file.truncate()
|
|
112
106
|
threadlog.debug("%s: unpacked %s-%s docs to %s",
|
|
113
107
|
stage.name, name, version, unpack_path)
|
|
@@ -115,17 +109,18 @@ def unpack_docs(stage, name, version, entry):
|
|
|
115
109
|
|
|
116
110
|
|
|
117
111
|
class PackedEntry:
|
|
118
|
-
def __init__(self,
|
|
119
|
-
self.
|
|
112
|
+
def __init__(self, name, body):
|
|
113
|
+
self.name = name
|
|
120
114
|
self.body = body
|
|
121
115
|
|
|
122
|
-
def
|
|
123
|
-
if mode != 'rb':
|
|
124
|
-
raise RuntimeError("Unsupported mode %r" % mode)
|
|
116
|
+
def read_bytes(self):
|
|
125
117
|
return self.body
|
|
126
118
|
|
|
119
|
+
def read_text(self):
|
|
120
|
+
return self.body.decode()
|
|
121
|
+
|
|
127
122
|
|
|
128
|
-
class Docs(
|
|
123
|
+
class Docs(MutableMapping):
|
|
129
124
|
def __init__(self, stage, name, version):
|
|
130
125
|
self.stage = stage
|
|
131
126
|
self.keep_docs_packed = keep_docs_packed(self.stage.xom.config)
|
|
@@ -148,40 +143,43 @@ class Docs(DictMixin):
|
|
|
148
143
|
# aren't uploaded yet
|
|
149
144
|
threadlog.warn("Tried to access %s, but it doesn't exist.", self.unpack_path)
|
|
150
145
|
return {}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
146
|
+
return (
|
|
147
|
+
self._packed_entries()
|
|
148
|
+
if self.keep_docs_packed
|
|
149
|
+
else self._unpacked_entries()
|
|
150
|
+
)
|
|
155
151
|
|
|
156
152
|
def _packed_entries(self):
|
|
157
153
|
html = set()
|
|
158
154
|
fjson = set()
|
|
159
|
-
with self.entry.file_open_read() as f:
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
if fjson
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
k[:-5]: PackedEntry(k, archive.read(k))
|
|
175
|
-
for k in html}
|
|
155
|
+
with self.entry.file_open_read() as f, Archive(f) as archive:
|
|
156
|
+
for item in archive.namelist():
|
|
157
|
+
if item.endswith(".fjson"):
|
|
158
|
+
fjson.add(item)
|
|
159
|
+
elif item.endswith(".html"):
|
|
160
|
+
html.add(item)
|
|
161
|
+
if fjson:
|
|
162
|
+
# if there is fjson, then we get structured data
|
|
163
|
+
# see http://www.sphinx-doc.org/en/master/usage/builders/index.html#serialization-builder-details
|
|
164
|
+
src = fjson
|
|
165
|
+
s = slice(None, -6)
|
|
166
|
+
else:
|
|
167
|
+
src = html
|
|
168
|
+
s = slice(None, -5)
|
|
169
|
+
return {k[s]: PackedEntry(k, archive.read(k)) for k in src}
|
|
176
170
|
|
|
177
171
|
def _unpacked_entries(self):
|
|
178
172
|
unpack_path = unpack_docs(self.stage, self.name, self.version, self.entry)
|
|
179
|
-
if not unpack_path.
|
|
173
|
+
if not unpack_path.is_dir():
|
|
180
174
|
return {}
|
|
181
175
|
html = []
|
|
182
176
|
fjson = []
|
|
183
|
-
|
|
184
|
-
|
|
177
|
+
entries = itertools.chain(
|
|
178
|
+
unpack_path.glob("**/*.fjson"),
|
|
179
|
+
unpack_path.glob("**/*.html"),
|
|
180
|
+
)
|
|
181
|
+
for entry in entries:
|
|
182
|
+
basename = entry.name
|
|
185
183
|
if basename.endswith('.fjson'):
|
|
186
184
|
fjson.append(entry)
|
|
187
185
|
elif basename.endswith('.html'):
|
|
@@ -189,9 +187,12 @@ class Docs(DictMixin):
|
|
|
189
187
|
if fjson:
|
|
190
188
|
# if there is fjson, then we get structured data
|
|
191
189
|
# see http://www.sphinx-doc.org/en/master/usage/builders/index.html#serialization-builder-details
|
|
192
|
-
|
|
190
|
+
src = fjson
|
|
191
|
+
s = slice(None, -6)
|
|
193
192
|
else:
|
|
194
|
-
|
|
193
|
+
src = html
|
|
194
|
+
s = slice(None, -5)
|
|
195
|
+
return {str(x.relative_to(unpack_path))[s]: x for x in src}
|
|
195
196
|
|
|
196
197
|
def keys(self):
|
|
197
198
|
return self._entries.keys()
|
|
@@ -210,26 +211,19 @@ class Docs(DictMixin):
|
|
|
210
211
|
|
|
211
212
|
def __getitem__(self, name):
|
|
212
213
|
entry = self._entries[name]
|
|
213
|
-
if entry.
|
|
214
|
-
info = json.loads(entry.
|
|
214
|
+
if entry.name.endswith(".fjson"):
|
|
215
|
+
info = json.loads(entry.read_text())
|
|
215
216
|
return dict(
|
|
216
217
|
title=BeautifulSoup(info.get('title', ''), "html.parser").text,
|
|
217
218
|
text=BeautifulSoup(info.get('body', ''), "html.parser").text,
|
|
218
219
|
path=info.get('current_page_name', name))
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
title = ''
|
|
227
|
-
else:
|
|
228
|
-
title = title.text
|
|
229
|
-
return dict(
|
|
230
|
-
title=title,
|
|
231
|
-
text=body.text,
|
|
232
|
-
path=name)
|
|
220
|
+
soup = BeautifulSoup(entry.read_bytes(), "html.parser")
|
|
221
|
+
body = soup.find("body")
|
|
222
|
+
if body is None:
|
|
223
|
+
return None
|
|
224
|
+
title = soup.find("title")
|
|
225
|
+
title = "" if title is None else title.text
|
|
226
|
+
return dict(title=title, text=body.text, path=name)
|
|
233
227
|
|
|
234
228
|
|
|
235
229
|
def remove_docs(stage, project, version):
|
|
@@ -237,8 +231,8 @@ def remove_docs(stage, project, version):
|
|
|
237
231
|
# the stage was removed
|
|
238
232
|
return
|
|
239
233
|
with locked_unpack_path(stage, project, version, remove_lock_file=True) as (hash_file, directory):
|
|
240
|
-
if not directory.
|
|
234
|
+
if not directory.is_dir():
|
|
241
235
|
threadlog.debug("ignoring lost unpacked docs: %s" % directory)
|
|
242
236
|
else:
|
|
243
237
|
threadlog.debug("removing unpacked docs: %s" % directory)
|
|
244
|
-
|
|
238
|
+
shutil.rmtree(directory)
|
|
@@ -34,6 +34,7 @@ def preprocess_project(project):
|
|
|
34
34
|
if not stage.has_project_perstage(name):
|
|
35
35
|
# project doesn't exist anymore
|
|
36
36
|
return
|
|
37
|
+
# metadata_keys is only available on private indexes
|
|
37
38
|
setuptools_metadata = frozenset(getattr(stage, 'metadata_keys', ()))
|
|
38
39
|
versions = get_sorted_versions(stage.list_versions_perstage(name))
|
|
39
40
|
result = dict(name=project.name)
|