code-annotations 1.7.0__tar.gz → 2.2.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.
- {code-annotations-1.7.0 → code_annotations-2.2.0}/CHANGELOG.rst +28 -0
- {code-annotations-1.7.0 → code_annotations-2.2.0}/PKG-INFO +49 -8
- {code-annotations-1.7.0 → code_annotations-2.2.0}/code_annotations/__init__.py +1 -1
- {code-annotations-1.7.0 → code_annotations-2.2.0}/code_annotations/base.py +2 -2
- {code-annotations-1.7.0 → code_annotations-2.2.0}/code_annotations/cli.py +117 -68
- code_annotations-2.2.0/code_annotations/contrib/config/__init__.py +14 -0
- {code-annotations-1.7.0 → code_annotations-2.2.0}/code_annotations/contrib/config/openedx_events_annotations.yaml +3 -1
- {code-annotations-1.7.0 → code_annotations-2.2.0}/code_annotations/contrib/sphinx/extensions/featuretoggles.py +1 -1
- {code-annotations-1.7.0 → code_annotations-2.2.0}/code_annotations/contrib/sphinx/extensions/openedx_events.py +40 -2
- {code-annotations-1.7.0 → code_annotations-2.2.0}/code_annotations/find_django.py +169 -102
- {code-annotations-1.7.0 → code_annotations-2.2.0}/code_annotations/generate_docs.py +1 -1
- {code-annotations-1.7.0 → code_annotations-2.2.0}/code_annotations.egg-info/PKG-INFO +49 -8
- {code-annotations-1.7.0 → code_annotations-2.2.0}/code_annotations.egg-info/requires.txt +4 -4
- {code-annotations-1.7.0 → code_annotations-2.2.0}/setup.py +4 -3
- {code-annotations-1.7.0 → code_annotations-2.2.0}/tests/test_django_generate_safelist.py +2 -2
- {code-annotations-1.7.0 → code_annotations-2.2.0}/tests/test_find_django.py +17 -0
- code-annotations-1.7.0/code_annotations/contrib/config/__init__.py +0 -19
- {code-annotations-1.7.0 → code_annotations-2.2.0}/LICENSE.txt +0 -0
- {code-annotations-1.7.0 → code_annotations-2.2.0}/MANIFEST.in +0 -0
- {code-annotations-1.7.0 → code_annotations-2.2.0}/NOTICE.txt +0 -0
- {code-annotations-1.7.0 → code_annotations-2.2.0}/README.rst +0 -0
- {code-annotations-1.7.0 → code_annotations-2.2.0}/code_annotations/annotation_errors.py +0 -0
- {code-annotations-1.7.0 → code_annotations-2.2.0}/code_annotations/contrib/config/feature_toggle_annotations.yaml +0 -0
- {code-annotations-1.7.0 → code_annotations-2.2.0}/code_annotations/contrib/config/setting_annotations.yaml +0 -0
- {code-annotations-1.7.0 → code_annotations-2.2.0}/code_annotations/contrib/sphinx/extensions/__init__.py +0 -0
- {code-annotations-1.7.0 → code_annotations-2.2.0}/code_annotations/contrib/sphinx/extensions/base.py +0 -0
- {code-annotations-1.7.0 → code_annotations-2.2.0}/code_annotations/contrib/sphinx/extensions/settings.py +0 -0
- {code-annotations-1.7.0 → code_annotations-2.2.0}/code_annotations/exceptions.py +0 -0
- {code-annotations-1.7.0 → code_annotations-2.2.0}/code_annotations/extensions/__init__.py +0 -0
- {code-annotations-1.7.0 → code_annotations-2.2.0}/code_annotations/extensions/base.py +0 -0
- {code-annotations-1.7.0 → code_annotations-2.2.0}/code_annotations/extensions/javascript.py +0 -0
- {code-annotations-1.7.0 → code_annotations-2.2.0}/code_annotations/extensions/python.py +0 -0
- {code-annotations-1.7.0 → code_annotations-2.2.0}/code_annotations/find_static.py +0 -0
- {code-annotations-1.7.0 → code_annotations-2.2.0}/code_annotations/helpers.py +0 -0
- {code-annotations-1.7.0 → code_annotations-2.2.0}/code_annotations.egg-info/SOURCES.txt +0 -0
- {code-annotations-1.7.0 → code_annotations-2.2.0}/code_annotations.egg-info/dependency_links.txt +0 -0
- {code-annotations-1.7.0 → code_annotations-2.2.0}/code_annotations.egg-info/entry_points.txt +0 -0
- {code-annotations-1.7.0 → code_annotations-2.2.0}/code_annotations.egg-info/not-zip-safe +0 -0
- {code-annotations-1.7.0 → code_annotations-2.2.0}/code_annotations.egg-info/top_level.txt +0 -0
- {code-annotations-1.7.0 → code_annotations-2.2.0}/requirements/base.in +0 -0
- {code-annotations-1.7.0 → code_annotations-2.2.0}/setup.cfg +0 -0
- {code-annotations-1.7.0 → code_annotations-2.2.0}/tests/test_base.py +0 -0
- {code-annotations-1.7.0 → code_annotations-2.2.0}/tests/test_django_coverage.py +0 -0
- {code-annotations-1.7.0 → code_annotations-2.2.0}/tests/test_django_list_local_models.py +0 -0
- {code-annotations-1.7.0 → code_annotations-2.2.0}/tests/test_find_static.py +0 -0
- {code-annotations-1.7.0 → code_annotations-2.2.0}/tests/test_generate_docs.py +0 -0
- {code-annotations-1.7.0 → code_annotations-2.2.0}/tests/test_search.py +0 -0
- {code-annotations-1.7.0 → code_annotations-2.2.0}/tests/test_sphinx.py +0 -0
|
@@ -14,6 +14,34 @@ Change Log
|
|
|
14
14
|
Unreleased
|
|
15
15
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
16
16
|
|
|
17
|
+
[2.2.0] - 2025-01-15
|
|
18
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
19
|
+
|
|
20
|
+
* Add support for optional Open edX Event trigger in-line annotation.
|
|
21
|
+
|
|
22
|
+
[2.1.0] - 2024-12-12
|
|
23
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
24
|
+
|
|
25
|
+
* Add support for optional Open edX Event warning for in-line annotation.
|
|
26
|
+
|
|
27
|
+
[2.0.0] - 2024-10-18
|
|
28
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
29
|
+
|
|
30
|
+
* Drop support for python 3.8
|
|
31
|
+
* Adds support for python 3.11 & 3.12
|
|
32
|
+
|
|
33
|
+
[1.8.1] - 2024-07-11
|
|
34
|
+
~~~~~~~~~~~~~~~~~~~~
|
|
35
|
+
|
|
36
|
+
* Fix elapsed-time calculations to always use UTC. Other clocks can be altered partway through by Django config settings being loaded while the timer is running, resulting in reporting elapsed time of "-17999.895582 seconds" or similar.
|
|
37
|
+
* Fix report filename to use year-month-day order, not year-day-month. (Also more compact, now.)
|
|
38
|
+
|
|
39
|
+
[1.8.0] - 2024-03-31
|
|
40
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
41
|
+
|
|
42
|
+
* Added python3.11 and 3.12 support. Dropped django32 support.
|
|
43
|
+
|
|
44
|
+
|
|
17
45
|
[1.6.0] - 2024-01-31
|
|
18
46
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
19
47
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: code-annotations
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.2.0
|
|
4
4
|
Summary: Extensible tools for parsing annotations in codebases
|
|
5
5
|
Home-page: https://github.com/openedx/code-annotations
|
|
6
6
|
Author: edX
|
|
@@ -9,24 +9,37 @@ License: Apache Software License 2.0
|
|
|
9
9
|
Keywords: edx pii code annotations
|
|
10
10
|
Classifier: Development Status :: 3 - Alpha
|
|
11
11
|
Classifier: Framework :: Django
|
|
12
|
-
Classifier: Framework :: Django :: 3.2
|
|
13
12
|
Classifier: Framework :: Django :: 4.2
|
|
14
13
|
Classifier: Intended Audience :: Developers
|
|
15
14
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
16
15
|
Classifier: Natural Language :: English
|
|
17
16
|
Classifier: Programming Language :: Python
|
|
18
17
|
Classifier: Programming Language :: Python :: 3
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Requires-Python: >=3.11
|
|
20
21
|
Description-Content-Type: text/x-rst
|
|
21
22
|
License-File: LICENSE.txt
|
|
22
23
|
License-File: NOTICE.txt
|
|
23
|
-
Requires-Dist: python-slugify
|
|
24
|
-
Requires-Dist: click
|
|
25
24
|
Requires-Dist: pyyaml
|
|
26
|
-
Requires-Dist:
|
|
25
|
+
Requires-Dist: click
|
|
27
26
|
Requires-Dist: Jinja2
|
|
27
|
+
Requires-Dist: stevedore
|
|
28
|
+
Requires-Dist: python-slugify
|
|
28
29
|
Provides-Extra: django
|
|
29
|
-
Requires-Dist: Django
|
|
30
|
+
Requires-Dist: Django>=4.2; extra == "django"
|
|
31
|
+
Dynamic: author
|
|
32
|
+
Dynamic: author-email
|
|
33
|
+
Dynamic: classifier
|
|
34
|
+
Dynamic: description
|
|
35
|
+
Dynamic: description-content-type
|
|
36
|
+
Dynamic: home-page
|
|
37
|
+
Dynamic: keywords
|
|
38
|
+
Dynamic: license
|
|
39
|
+
Dynamic: provides-extra
|
|
40
|
+
Dynamic: requires-dist
|
|
41
|
+
Dynamic: requires-python
|
|
42
|
+
Dynamic: summary
|
|
30
43
|
|
|
31
44
|
code-annotations
|
|
32
45
|
=============================
|
|
@@ -128,6 +141,34 @@ Change Log
|
|
|
128
141
|
Unreleased
|
|
129
142
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
130
143
|
|
|
144
|
+
[2.2.0] - 2025-01-15
|
|
145
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
146
|
+
|
|
147
|
+
* Add support for optional Open edX Event trigger in-line annotation.
|
|
148
|
+
|
|
149
|
+
[2.1.0] - 2024-12-12
|
|
150
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
151
|
+
|
|
152
|
+
* Add support for optional Open edX Event warning for in-line annotation.
|
|
153
|
+
|
|
154
|
+
[2.0.0] - 2024-10-18
|
|
155
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
156
|
+
|
|
157
|
+
* Drop support for python 3.8
|
|
158
|
+
* Adds support for python 3.11 & 3.12
|
|
159
|
+
|
|
160
|
+
[1.8.1] - 2024-07-11
|
|
161
|
+
~~~~~~~~~~~~~~~~~~~~
|
|
162
|
+
|
|
163
|
+
* Fix elapsed-time calculations to always use UTC. Other clocks can be altered partway through by Django config settings being loaded while the timer is running, resulting in reporting elapsed time of "-17999.895582 seconds" or similar.
|
|
164
|
+
* Fix report filename to use year-month-day order, not year-day-month. (Also more compact, now.)
|
|
165
|
+
|
|
166
|
+
[1.8.0] - 2024-03-31
|
|
167
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
168
|
+
|
|
169
|
+
* Added python3.11 and 3.12 support. Dropped django32 support.
|
|
170
|
+
|
|
171
|
+
|
|
131
172
|
[1.6.0] - 2024-01-31
|
|
132
173
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
133
174
|
|
|
@@ -616,9 +616,9 @@ class BaseSearch(metaclass=ABCMeta):
|
|
|
616
616
|
"""
|
|
617
617
|
self.echo.echo_vv(yaml.dump(all_results, default_flow_style=False))
|
|
618
618
|
|
|
619
|
-
now = datetime.datetime.
|
|
619
|
+
now = datetime.datetime.utcnow()
|
|
620
620
|
report_filename = os.path.join(self.config.report_path, '{}{}.yaml'.format(
|
|
621
|
-
report_prefix, now.strftime('%Y
|
|
621
|
+
report_prefix, now.strftime('%Y%m%d-%H%M%S')
|
|
622
622
|
))
|
|
623
623
|
|
|
624
624
|
formatted_results = self._format_results_for_report(all_results)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Command line interface for code annotation tools.
|
|
3
3
|
"""
|
|
4
|
+
|
|
4
5
|
import datetime
|
|
5
6
|
import sys
|
|
6
7
|
import traceback
|
|
@@ -21,53 +22,88 @@ def entry_point():
|
|
|
21
22
|
"""
|
|
22
23
|
|
|
23
24
|
|
|
24
|
-
@entry_point.command(
|
|
25
|
+
@entry_point.command("django_find_annotations")
|
|
26
|
+
@click.option(
|
|
27
|
+
"--config_file",
|
|
28
|
+
default=".annotations",
|
|
29
|
+
help="Path to the configuration file",
|
|
30
|
+
type=click.Path(exists=True, dir_okay=False, resolve_path=True),
|
|
31
|
+
)
|
|
32
|
+
@click.option(
|
|
33
|
+
"--seed_safelist/--no_safelist",
|
|
34
|
+
default=False,
|
|
35
|
+
show_default=True,
|
|
36
|
+
help="Generate an initial safelist file based on the current Django environment.",
|
|
37
|
+
)
|
|
38
|
+
@click.option(
|
|
39
|
+
"--list_local_models/--no_list_models",
|
|
40
|
+
default=False,
|
|
41
|
+
show_default=True,
|
|
42
|
+
help="List all locally defined models (in the current repo) that require annotations.",
|
|
43
|
+
)
|
|
44
|
+
@click.option(
|
|
45
|
+
"--app_name",
|
|
46
|
+
default=None,
|
|
47
|
+
help="(Optional) App name for which coverage is generated.",
|
|
48
|
+
)
|
|
49
|
+
@click.option("--report_path", default=None, help="Location to write the report")
|
|
50
|
+
@click.option("-v", "--verbosity", count=True, help="Verbosity level (-v through -vvv)")
|
|
25
51
|
@click.option(
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
52
|
+
"--lint/--no_lint",
|
|
53
|
+
help="Enable or disable linting checks",
|
|
54
|
+
default=False,
|
|
55
|
+
show_default=True,
|
|
30
56
|
)
|
|
31
57
|
@click.option(
|
|
32
|
-
|
|
58
|
+
"--report/--no_report",
|
|
59
|
+
help="Enable or disable writing the report",
|
|
33
60
|
default=False,
|
|
34
61
|
show_default=True,
|
|
35
|
-
help='Generate an initial safelist file based on the current Django environment.',
|
|
36
62
|
)
|
|
37
63
|
@click.option(
|
|
38
|
-
|
|
64
|
+
"--coverage/--no_coverage",
|
|
65
|
+
help="Enable or disable coverage checks",
|
|
39
66
|
default=False,
|
|
40
67
|
show_default=True,
|
|
41
|
-
help='List all locally defined models (in the current repo) that require annotations.',
|
|
42
68
|
)
|
|
43
|
-
@click.option('--app_name', default='', help='(Optional) App name for which coverage is generated.')
|
|
44
|
-
@click.option('--report_path', default=None, help='Location to write the report')
|
|
45
|
-
@click.option('-v', '--verbosity', count=True, help='Verbosity level (-v through -vvv)')
|
|
46
|
-
@click.option('--lint/--no_lint', help='Enable or disable linting checks', default=False, show_default=True)
|
|
47
|
-
@click.option('--report/--no_report', help='Enable or disable writing the report', default=False, show_default=True)
|
|
48
|
-
@click.option('--coverage/--no_coverage', help='Enable or disable coverage checks', default=False, show_default=True)
|
|
49
69
|
def django_find_annotations(
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
70
|
+
config_file,
|
|
71
|
+
seed_safelist,
|
|
72
|
+
list_local_models,
|
|
73
|
+
app_name,
|
|
74
|
+
report_path,
|
|
75
|
+
verbosity,
|
|
76
|
+
lint,
|
|
77
|
+
report,
|
|
78
|
+
coverage,
|
|
59
79
|
):
|
|
60
80
|
"""
|
|
61
81
|
Subcommand for dealing with annotations in Django models.
|
|
62
82
|
"""
|
|
63
83
|
try:
|
|
64
|
-
start_time = datetime.datetime.
|
|
84
|
+
start_time = datetime.datetime.utcnow()
|
|
85
|
+
|
|
86
|
+
if (
|
|
87
|
+
not coverage
|
|
88
|
+
and not seed_safelist
|
|
89
|
+
and not list_local_models
|
|
90
|
+
and not lint
|
|
91
|
+
and not report
|
|
92
|
+
):
|
|
93
|
+
click.echo(
|
|
94
|
+
"No actions specified. Please specify one or more of --seed_safelist, --list_local_models, "
|
|
95
|
+
"--lint, --report, or --coverage"
|
|
96
|
+
)
|
|
97
|
+
sys.exit(1)
|
|
98
|
+
|
|
65
99
|
config = AnnotationConfig(config_file, report_path, verbosity)
|
|
66
|
-
searcher = DjangoSearch(config)
|
|
100
|
+
searcher = DjangoSearch(config, app_name)
|
|
67
101
|
|
|
68
102
|
# Early out if we're trying to do coverage, but a coverage target is not configured
|
|
69
103
|
if coverage and not config.coverage_target:
|
|
70
|
-
raise ConfigurationException(
|
|
104
|
+
raise ConfigurationException(
|
|
105
|
+
"Please add 'coverage_target' to your configuration before running --coverage"
|
|
106
|
+
)
|
|
71
107
|
|
|
72
108
|
if seed_safelist:
|
|
73
109
|
searcher.seed_safelist()
|
|
@@ -106,38 +142,51 @@ def django_find_annotations(
|
|
|
106
142
|
for filename in annotated_models:
|
|
107
143
|
annotation_count += len(annotated_models[filename])
|
|
108
144
|
|
|
109
|
-
elapsed = datetime.datetime.
|
|
110
|
-
click.echo(
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
145
|
+
elapsed = datetime.datetime.utcnow() - start_time
|
|
146
|
+
click.echo(
|
|
147
|
+
"Search found {} annotations in {} seconds.".format(
|
|
148
|
+
annotation_count, elapsed.total_seconds()
|
|
149
|
+
)
|
|
150
|
+
)
|
|
151
|
+
except Exception as exc:
|
|
115
152
|
click.echo(traceback.print_exc())
|
|
116
153
|
fail(str(exc))
|
|
117
154
|
|
|
118
155
|
|
|
119
|
-
@entry_point.command(
|
|
156
|
+
@entry_point.command("static_find_annotations")
|
|
120
157
|
@click.option(
|
|
121
|
-
|
|
122
|
-
default=
|
|
123
|
-
help=
|
|
124
|
-
type=click.Path(exists=True, dir_okay=False, resolve_path=True)
|
|
158
|
+
"--config_file",
|
|
159
|
+
default=".annotations",
|
|
160
|
+
help="Path to the configuration file",
|
|
161
|
+
type=click.Path(exists=True, dir_okay=False, resolve_path=True),
|
|
125
162
|
)
|
|
126
163
|
@click.option(
|
|
127
|
-
|
|
128
|
-
help=
|
|
129
|
-
type=click.Path(exists=True, dir_okay=True, resolve_path=True)
|
|
164
|
+
"--source_path",
|
|
165
|
+
help="Location of the source code to search",
|
|
166
|
+
type=click.Path(exists=True, dir_okay=True, resolve_path=True),
|
|
130
167
|
)
|
|
131
|
-
@click.option(
|
|
132
|
-
@click.option(
|
|
133
|
-
@click.option(
|
|
134
|
-
|
|
135
|
-
|
|
168
|
+
@click.option("--report_path", default=None, help="Location to write the report")
|
|
169
|
+
@click.option("-v", "--verbosity", count=True, help="Verbosity level (-v through -vvv)")
|
|
170
|
+
@click.option(
|
|
171
|
+
"--lint/--no_lint",
|
|
172
|
+
help="Enable or disable linting checks",
|
|
173
|
+
default=True,
|
|
174
|
+
show_default=True,
|
|
175
|
+
)
|
|
176
|
+
@click.option(
|
|
177
|
+
"--report/--no_report",
|
|
178
|
+
help="Enable or disable writing the report file",
|
|
179
|
+
default=True,
|
|
180
|
+
show_default=True,
|
|
181
|
+
)
|
|
182
|
+
def static_find_annotations(
|
|
183
|
+
config_file, source_path, report_path, verbosity, lint, report
|
|
184
|
+
):
|
|
136
185
|
"""
|
|
137
186
|
Subcommand to find annotations via static file analysis.
|
|
138
187
|
"""
|
|
139
188
|
try:
|
|
140
|
-
start_time = datetime.datetime.
|
|
189
|
+
start_time = datetime.datetime.utcnow()
|
|
141
190
|
config = AnnotationConfig(config_file, report_path, verbosity, source_path)
|
|
142
191
|
searcher = StaticSearch(config)
|
|
143
192
|
all_results = searcher.search()
|
|
@@ -161,7 +210,7 @@ def static_find_annotations(config_file, source_path, report_path, verbosity, li
|
|
|
161
210
|
report_filename = searcher.report(all_results)
|
|
162
211
|
click.echo(f"Report written to {report_filename}.")
|
|
163
212
|
|
|
164
|
-
elapsed = datetime.datetime.
|
|
213
|
+
elapsed = datetime.datetime.utcnow() - start_time
|
|
165
214
|
annotation_count = 0
|
|
166
215
|
|
|
167
216
|
for filename in all_results:
|
|
@@ -169,49 +218,49 @@ def static_find_annotations(config_file, source_path, report_path, verbosity, li
|
|
|
169
218
|
|
|
170
219
|
click.echo(f"Search found {annotation_count} annotations in {elapsed}.")
|
|
171
220
|
|
|
172
|
-
except Exception as exc:
|
|
221
|
+
except Exception as exc:
|
|
173
222
|
click.echo(traceback.print_exc())
|
|
174
223
|
fail(str(exc))
|
|
175
224
|
|
|
176
225
|
|
|
177
226
|
@entry_point.command("generate_docs")
|
|
178
227
|
@click.option(
|
|
179
|
-
|
|
180
|
-
default=
|
|
181
|
-
help=
|
|
182
|
-
type=click.Path(exists=True, dir_okay=False)
|
|
228
|
+
"--config_file",
|
|
229
|
+
default=".annotations",
|
|
230
|
+
help="Path to the configuration file",
|
|
231
|
+
type=click.Path(exists=True, dir_okay=False),
|
|
183
232
|
)
|
|
184
|
-
@click.option(
|
|
185
|
-
@click.argument("report_files", type=click.File(
|
|
186
|
-
def generate_docs(
|
|
187
|
-
config_file,
|
|
188
|
-
verbosity,
|
|
189
|
-
report_files
|
|
190
|
-
):
|
|
233
|
+
@click.option("-v", "--verbosity", count=True, help="Verbosity level (-v through -vvv)")
|
|
234
|
+
@click.argument("report_files", type=click.File("r"), nargs=-1)
|
|
235
|
+
def generate_docs(config_file, verbosity, report_files):
|
|
191
236
|
"""
|
|
192
237
|
Generate documentation from a code annotations report.
|
|
193
238
|
"""
|
|
194
|
-
start_time = datetime.datetime.
|
|
239
|
+
start_time = datetime.datetime.utcnow()
|
|
195
240
|
|
|
196
241
|
try:
|
|
197
242
|
config = AnnotationConfig(config_file, verbosity)
|
|
198
243
|
|
|
199
244
|
for key in (
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
245
|
+
"report_template_dir",
|
|
246
|
+
"rendered_report_dir",
|
|
247
|
+
"rendered_report_file_extension",
|
|
248
|
+
"rendered_report_source_link_prefix",
|
|
204
249
|
):
|
|
205
250
|
if not getattr(config, key):
|
|
206
251
|
raise ConfigurationException(f"No {key} key in {config_file}")
|
|
207
252
|
|
|
208
|
-
config.echo(
|
|
253
|
+
config.echo(
|
|
254
|
+
"Rendering the following reports: \n{}".format(
|
|
255
|
+
"\n".join([r.name for r in report_files])
|
|
256
|
+
)
|
|
257
|
+
)
|
|
209
258
|
|
|
210
259
|
renderer = ReportRenderer(config, report_files)
|
|
211
260
|
renderer.render()
|
|
212
261
|
|
|
213
|
-
elapsed = datetime.datetime.
|
|
262
|
+
elapsed = datetime.datetime.utcnow() - start_time
|
|
214
263
|
click.echo(f"Report rendered in {elapsed.total_seconds()} seconds.")
|
|
215
|
-
except Exception as exc:
|
|
264
|
+
except Exception as exc:
|
|
216
265
|
click.echo(traceback.print_exc())
|
|
217
266
|
fail(str(exc))
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Expose contrib configuration file paths as Python variables, for use in 3rd-party utilities.
|
|
3
|
+
"""
|
|
4
|
+
import importlib.resources
|
|
5
|
+
import os
|
|
6
|
+
|
|
7
|
+
FEATURE_TOGGLE_ANNOTATIONS_CONFIG_PATH = importlib.resources.files(
|
|
8
|
+
"code_annotations") / os.path.join("contrib", "config", "feature_toggle_annotations.yaml")
|
|
9
|
+
|
|
10
|
+
SETTING_ANNOTATIONS_CONFIG_PATH = importlib.resources.files(
|
|
11
|
+
"code_annotations") / os.path.join("contrib", "config", "setting_annotations.yaml")
|
|
12
|
+
|
|
13
|
+
OPENEDX_EVENTS_ANNOTATIONS_CONFIG_PATH = importlib.resources.files(
|
|
14
|
+
"code_annotations") / os.path.join("contrib", "config", "openedx_events_annotations.yaml")
|
|
@@ -6,12 +6,14 @@ safelist_path: .annotation_safe_list.yml
|
|
|
6
6
|
coverage_target: 100.0
|
|
7
7
|
annotations:
|
|
8
8
|
feature_toggle:
|
|
9
|
-
# See annotation format documentation: https://
|
|
9
|
+
# See annotation format documentation: https://docs.openedx.org/projects/openedx-events/en/latest/reference/in-line-code-annotations-for-an-event.html
|
|
10
10
|
- ".. event_type:":
|
|
11
11
|
- ".. event_name:":
|
|
12
12
|
- ".. event_description:":
|
|
13
13
|
- ".. event_data:":
|
|
14
14
|
- ".. event_key_field:":
|
|
15
|
+
- ".. event_trigger_repository:":
|
|
16
|
+
- ".. event_warning:":
|
|
15
17
|
extensions:
|
|
16
18
|
python:
|
|
17
19
|
- py
|
|
@@ -111,7 +111,7 @@ class FeatureToggles(SphinxDirective):
|
|
|
111
111
|
for opt in optional_attrs:
|
|
112
112
|
if toggle.get(f".. toggle_{opt}:") not in (None, "None", "n/a", "N/A"):
|
|
113
113
|
toggle_section += nodes.paragraph(
|
|
114
|
-
text=f'{opt.title().replace("_"," ")}: {toggle[f".. toggle_{opt}:"]}',
|
|
114
|
+
text=f'{opt.title().replace("_", " ")}: {toggle[f".. toggle_{opt}:"]}',
|
|
115
115
|
ids=[f"{opt}-{toggle_name}"],
|
|
116
116
|
)
|
|
117
117
|
yield toggle_section
|
|
@@ -100,6 +100,7 @@ class OpenedxEvents(SphinxDirective):
|
|
|
100
100
|
event_key_field = event.get(".. event_key_field:", "")
|
|
101
101
|
event_key_literal = nodes.literal(text=event_key_field)
|
|
102
102
|
event_description = event[".. event_description:"]
|
|
103
|
+
event_trigger_repository = event.get(".. event_trigger_repository:")
|
|
103
104
|
|
|
104
105
|
event_section = nodes.section("", ids=[f"openedxevent-{event_type}"])
|
|
105
106
|
event_section += nodes.title(text=event_type, ids=[f"title-{event_type}"])
|
|
@@ -114,10 +115,47 @@ class OpenedxEvents(SphinxDirective):
|
|
|
114
115
|
)
|
|
115
116
|
event_section += nodes.paragraph("", "Event data: ", event_data_literal)
|
|
116
117
|
event_section += nodes.paragraph(
|
|
117
|
-
|
|
118
|
-
|
|
118
|
+
"",
|
|
119
|
+
"Defined at: ",
|
|
120
|
+
nodes.reference(
|
|
121
|
+
text="{} (line {})".format(
|
|
122
|
+
event["filename"], event["line_number"]
|
|
123
|
+
),
|
|
124
|
+
refuri="{}/blob/{}/{}#L{}".format(
|
|
125
|
+
self.env.config.openedxevents_repo_url,
|
|
126
|
+
self.env.config.openedxevents_repo_version,
|
|
127
|
+
event["filename"],
|
|
128
|
+
event["line_number"],
|
|
129
|
+
),
|
|
130
|
+
),
|
|
131
|
+
ids=[f"definition-{event_name}"],
|
|
119
132
|
)
|
|
120
133
|
|
|
134
|
+
if event_trigger_repository:
|
|
135
|
+
event_trigger_repository = event_trigger_repository.split(" ")
|
|
136
|
+
event_section += nodes.paragraph(text="Triggered by:", ids=[f"triggers-{event_name}"])
|
|
137
|
+
triggers_bullet_list = nodes.bullet_list()
|
|
138
|
+
for repository in event_trigger_repository:
|
|
139
|
+
search_url = f"https://github.com/search?q=repo:{repository}+{event_name}.send_event&type=code"
|
|
140
|
+
triggers_bullet_list += nodes.list_item(
|
|
141
|
+
"",
|
|
142
|
+
nodes.paragraph(
|
|
143
|
+
"",
|
|
144
|
+
"",
|
|
145
|
+
nodes.reference(
|
|
146
|
+
text=repository,
|
|
147
|
+
refuri=search_url,
|
|
148
|
+
),
|
|
149
|
+
),
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
event_section += triggers_bullet_list
|
|
153
|
+
|
|
154
|
+
if event.get(".. event_warning:") not in (None, "None", "n/a", "N/A"):
|
|
155
|
+
event_section += nodes.warning(
|
|
156
|
+
"", nodes.paragraph("", event[".. event_warning:"]), ids=[f"warning-{event_name}"]
|
|
157
|
+
)
|
|
158
|
+
|
|
121
159
|
subject_header += event_section
|
|
122
160
|
|
|
123
161
|
if domain_header:
|