code-annotations 2.1.0__tar.gz → 2.3.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.
Files changed (58) hide show
  1. {code_annotations-2.1.0 → code_annotations-2.3.0}/CHANGELOG.rst +6 -1
  2. {code_annotations-2.1.0 → code_annotations-2.3.0}/MANIFEST.in +1 -1
  3. {code_annotations-2.1.0 → code_annotations-2.3.0}/PKG-INFO +23 -32
  4. {code_annotations-2.1.0 → code_annotations-2.3.0}/README.rst +0 -28
  5. {code_annotations-2.1.0 → code_annotations-2.3.0}/code_annotations/__init__.py +1 -1
  6. {code_annotations-2.1.0 → code_annotations-2.3.0}/code_annotations/base.py +14 -4
  7. {code_annotations-2.1.0 → code_annotations-2.3.0}/code_annotations/cli.py +6 -1
  8. code_annotations-2.3.0/code_annotations/contrib/config/__init__.py +14 -0
  9. {code_annotations-2.1.0 → code_annotations-2.3.0}/code_annotations/contrib/config/openedx_events_annotations.yaml +1 -0
  10. {code_annotations-2.1.0 → code_annotations-2.3.0}/code_annotations/contrib/sphinx/extensions/openedx_events.py +35 -2
  11. {code_annotations-2.1.0 → code_annotations-2.3.0}/code_annotations/generate_docs.py +20 -10
  12. code_annotations-2.3.0/code_annotations/report_templates/html/annotation.tpl +14 -0
  13. code_annotations-2.3.0/code_annotations/report_templates/html/annotation_data.tpl +8 -0
  14. code_annotations-2.3.0/code_annotations/report_templates/html/annotation_list.tpl +27 -0
  15. code_annotations-2.3.0/code_annotations/report_templates/html/base.tpl +92 -0
  16. code_annotations-2.3.0/code_annotations/report_templates/rst/annotation.tpl +13 -0
  17. code_annotations-2.3.0/code_annotations/report_templates/rst/annotation_data.tpl +8 -0
  18. code_annotations-2.3.0/code_annotations/report_templates/rst/annotation_group.tpl +2 -0
  19. code_annotations-2.3.0/code_annotations/report_templates/rst/annotation_list.tpl +34 -0
  20. code_annotations-2.3.0/code_annotations/report_templates/rst/base.tpl +41 -0
  21. {code_annotations-2.1.0 → code_annotations-2.3.0}/code_annotations.egg-info/PKG-INFO +23 -32
  22. {code_annotations-2.1.0 → code_annotations-2.3.0}/code_annotations.egg-info/SOURCES.txt +9 -0
  23. code_annotations-2.3.0/setup.py +111 -0
  24. {code_annotations-2.1.0 → code_annotations-2.3.0}/tests/test_generate_docs.py +35 -1
  25. code_annotations-2.1.0/code_annotations/contrib/config/__init__.py +0 -19
  26. code_annotations-2.1.0/setup.py +0 -110
  27. {code_annotations-2.1.0 → code_annotations-2.3.0}/LICENSE.txt +0 -0
  28. {code_annotations-2.1.0 → code_annotations-2.3.0}/NOTICE.txt +0 -0
  29. {code_annotations-2.1.0 → code_annotations-2.3.0}/code_annotations/annotation_errors.py +0 -0
  30. {code_annotations-2.1.0 → code_annotations-2.3.0}/code_annotations/contrib/config/feature_toggle_annotations.yaml +0 -0
  31. {code_annotations-2.1.0 → code_annotations-2.3.0}/code_annotations/contrib/config/setting_annotations.yaml +0 -0
  32. {code_annotations-2.1.0 → code_annotations-2.3.0}/code_annotations/contrib/sphinx/extensions/__init__.py +0 -0
  33. {code_annotations-2.1.0 → code_annotations-2.3.0}/code_annotations/contrib/sphinx/extensions/base.py +0 -0
  34. {code_annotations-2.1.0 → code_annotations-2.3.0}/code_annotations/contrib/sphinx/extensions/featuretoggles.py +0 -0
  35. {code_annotations-2.1.0 → code_annotations-2.3.0}/code_annotations/contrib/sphinx/extensions/settings.py +0 -0
  36. {code_annotations-2.1.0 → code_annotations-2.3.0}/code_annotations/exceptions.py +0 -0
  37. {code_annotations-2.1.0 → code_annotations-2.3.0}/code_annotations/extensions/__init__.py +0 -0
  38. {code_annotations-2.1.0 → code_annotations-2.3.0}/code_annotations/extensions/base.py +0 -0
  39. {code_annotations-2.1.0 → code_annotations-2.3.0}/code_annotations/extensions/javascript.py +0 -0
  40. {code_annotations-2.1.0 → code_annotations-2.3.0}/code_annotations/extensions/python.py +0 -0
  41. {code_annotations-2.1.0 → code_annotations-2.3.0}/code_annotations/find_django.py +0 -0
  42. {code_annotations-2.1.0 → code_annotations-2.3.0}/code_annotations/find_static.py +0 -0
  43. {code_annotations-2.1.0 → code_annotations-2.3.0}/code_annotations/helpers.py +0 -0
  44. {code_annotations-2.1.0 → code_annotations-2.3.0}/code_annotations.egg-info/dependency_links.txt +0 -0
  45. {code_annotations-2.1.0 → code_annotations-2.3.0}/code_annotations.egg-info/entry_points.txt +0 -0
  46. {code_annotations-2.1.0 → code_annotations-2.3.0}/code_annotations.egg-info/not-zip-safe +0 -0
  47. {code_annotations-2.1.0 → code_annotations-2.3.0}/code_annotations.egg-info/requires.txt +1 -1
  48. {code_annotations-2.1.0 → code_annotations-2.3.0}/code_annotations.egg-info/top_level.txt +0 -0
  49. {code_annotations-2.1.0 → code_annotations-2.3.0}/requirements/base.in +0 -0
  50. {code_annotations-2.1.0 → code_annotations-2.3.0}/setup.cfg +0 -0
  51. {code_annotations-2.1.0 → code_annotations-2.3.0}/tests/test_base.py +0 -0
  52. {code_annotations-2.1.0 → code_annotations-2.3.0}/tests/test_django_coverage.py +0 -0
  53. {code_annotations-2.1.0 → code_annotations-2.3.0}/tests/test_django_generate_safelist.py +0 -0
  54. {code_annotations-2.1.0 → code_annotations-2.3.0}/tests/test_django_list_local_models.py +0 -0
  55. {code_annotations-2.1.0 → code_annotations-2.3.0}/tests/test_find_django.py +0 -0
  56. {code_annotations-2.1.0 → code_annotations-2.3.0}/tests/test_find_static.py +0 -0
  57. {code_annotations-2.1.0 → code_annotations-2.3.0}/tests/test_search.py +0 -0
  58. {code_annotations-2.1.0 → code_annotations-2.3.0}/tests/test_sphinx.py +0 -0
@@ -14,10 +14,15 @@ 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
+
17
22
  [2.1.0] - 2024-12-12
18
23
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19
24
 
20
- * Add support for optional event warning for in-line annotation.
25
+ * Add support for optional Open edX Event warning for in-line annotation.
21
26
 
22
27
  [2.0.0] - 2024-10-18
23
28
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -4,4 +4,4 @@ include CONTRIBUTING.rst
4
4
  include LICENSE.txt
5
5
  include README.rst
6
6
  include requirements/base.in
7
- recursive-include code_annotations *.html *.png *.gif *js *.css *jpg *jpeg *svg *py *.yaml *.yml
7
+ recursive-include code_annotations *.tpl *.html *.png *.gif *js *.css *jpg *jpeg *svg *py *.yaml *.yml
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: code-annotations
3
- Version: 2.1.0
3
+ Version: 2.3.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
@@ -10,6 +10,7 @@ Keywords: edx pii code annotations
10
10
  Classifier: Development Status :: 3 - Alpha
11
11
  Classifier: Framework :: Django
12
12
  Classifier: Framework :: Django :: 4.2
13
+ Classifier: Framework :: Django :: 5.2
13
14
  Classifier: Intended Audience :: Developers
14
15
  Classifier: License :: OSI Approved :: Apache Software License
15
16
  Classifier: Natural Language :: English
@@ -23,18 +24,28 @@ License-File: LICENSE.txt
23
24
  License-File: NOTICE.txt
24
25
  Requires-Dist: python-slugify
25
26
  Requires-Dist: stevedore
26
- Requires-Dist: pyyaml
27
27
  Requires-Dist: click
28
+ Requires-Dist: pyyaml
28
29
  Requires-Dist: Jinja2
29
30
  Provides-Extra: django
30
31
  Requires-Dist: Django>=4.2; extra == "django"
32
+ Dynamic: author
33
+ Dynamic: author-email
34
+ Dynamic: classifier
35
+ Dynamic: description
36
+ Dynamic: description-content-type
37
+ Dynamic: home-page
38
+ Dynamic: keywords
39
+ Dynamic: license
40
+ Dynamic: license-file
41
+ Dynamic: provides-extra
42
+ Dynamic: requires-dist
43
+ Dynamic: requires-python
44
+ Dynamic: summary
31
45
 
32
46
  code-annotations
33
47
  =============================
34
48
 
35
- |pypi-badge| |CI| |codecov-badge| |doc-badge| |pyversions-badge|
36
- |license-badge|
37
-
38
49
  Extensible tools for parsing annotations in codebases
39
50
 
40
51
  Overview
@@ -88,31 +99,6 @@ refer to this `list of resources`_ if you need any assistance.
88
99
  .. _list of resources: https://open.edx.org/getting-help
89
100
 
90
101
 
91
- .. |pypi-badge| image:: https://img.shields.io/pypi/v/code-annotations.svg
92
- :target: https://pypi.python.org/pypi/code-annotations/
93
- :alt: PyPI
94
-
95
- .. |CI| image:: https://github.com/openedx/code-annotations/workflows/Python%20CI/badge.svg?branch=master
96
- :target: https://github.com/openedx/code-annotations/actions?query=workflow%3A%22Python+CI%22
97
- :alt: CI
98
-
99
- .. |codecov-badge| image:: http://codecov.io/github/edx/code-annotations/coverage.svg?branch=master
100
- :target: http://codecov.io/github/edx/code-annotations?branch=master
101
- :alt: Codecov
102
-
103
- .. |doc-badge| image:: https://readthedocs.org/projects/code-annotations/badge/?version=latest
104
- :target: http://code-annotations.readthedocs.io/en/latest/
105
- :alt: Documentation
106
-
107
- .. |pyversions-badge| image:: https://img.shields.io/pypi/pyversions/code-annotations.svg
108
- :target: https://pypi.python.org/pypi/code-annotations/
109
- :alt: Supported Python versions
110
-
111
- .. |license-badge| image:: https://img.shields.io/github/license/edx/code-annotations.svg
112
- :target: https://github.com/openedx/code-annotations/blob/master/LICENSE.txt
113
- :alt: License
114
-
115
-
116
102
  Change Log
117
103
  ----------
118
104
 
@@ -129,10 +115,15 @@ Change Log
129
115
  Unreleased
130
116
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
131
117
 
118
+ [2.2.0] - 2025-01-15
119
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
120
+
121
+ * Add support for optional Open edX Event trigger in-line annotation.
122
+
132
123
  [2.1.0] - 2024-12-12
133
124
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
134
125
 
135
- * Add support for optional event warning for in-line annotation.
126
+ * Add support for optional Open edX Event warning for in-line annotation.
136
127
 
137
128
  [2.0.0] - 2024-10-18
138
129
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1,9 +1,6 @@
1
1
  code-annotations
2
2
  =============================
3
3
 
4
- |pypi-badge| |CI| |codecov-badge| |doc-badge| |pyversions-badge|
5
- |license-badge|
6
-
7
4
  Extensible tools for parsing annotations in codebases
8
5
 
9
6
  Overview
@@ -55,28 +52,3 @@ Have a question about this repository, or about Open edX in general? Please
55
52
  refer to this `list of resources`_ if you need any assistance.
56
53
 
57
54
  .. _list of resources: https://open.edx.org/getting-help
58
-
59
-
60
- .. |pypi-badge| image:: https://img.shields.io/pypi/v/code-annotations.svg
61
- :target: https://pypi.python.org/pypi/code-annotations/
62
- :alt: PyPI
63
-
64
- .. |CI| image:: https://github.com/openedx/code-annotations/workflows/Python%20CI/badge.svg?branch=master
65
- :target: https://github.com/openedx/code-annotations/actions?query=workflow%3A%22Python+CI%22
66
- :alt: CI
67
-
68
- .. |codecov-badge| image:: http://codecov.io/github/edx/code-annotations/coverage.svg?branch=master
69
- :target: http://codecov.io/github/edx/code-annotations?branch=master
70
- :alt: Codecov
71
-
72
- .. |doc-badge| image:: https://readthedocs.org/projects/code-annotations/badge/?version=latest
73
- :target: http://code-annotations.readthedocs.io/en/latest/
74
- :alt: Documentation
75
-
76
- .. |pyversions-badge| image:: https://img.shields.io/pypi/pyversions/code-annotations.svg
77
- :target: https://pypi.python.org/pypi/code-annotations/
78
- :alt: Supported Python versions
79
-
80
- .. |license-badge| image:: https://img.shields.io/github/license/edx/code-annotations.svg
81
- :target: https://github.com/openedx/code-annotations/blob/master/LICENSE.txt
82
- :alt: License
@@ -2,4 +2,4 @@
2
2
  Extensible tools for parsing annotations in codebases.
3
3
  """
4
4
 
5
- __version__ = '2.1.0'
5
+ __version__ = "2.3.0"
@@ -14,6 +14,9 @@ from code_annotations import annotation_errors
14
14
  from code_annotations.exceptions import ConfigurationException
15
15
  from code_annotations.helpers import VerboseEcho
16
16
 
17
+ PACKAGE_DIR = os.path.dirname(os.path.realpath(__file__))
18
+ DEFAULT_TEMPLATE_DIR = os.path.join(PACKAGE_DIR, "report_templates")
19
+
17
20
 
18
21
  class AnnotationConfig:
19
22
  """
@@ -58,10 +61,17 @@ class AnnotationConfig:
58
61
  self.echo(f"Configured for source path: {self.source_path}")
59
62
 
60
63
  self._configure_coverage(raw_config.get('coverage_target', None))
61
- self.report_template_dir = raw_config.get('report_template_dir')
62
- self.rendered_report_dir = raw_config.get('rendered_report_dir')
63
- self.rendered_report_file_extension = raw_config.get('rendered_report_file_extension')
64
- self.rendered_report_source_link_prefix = raw_config.get('rendered_report_source_link_prefix')
64
+
65
+ self.rendered_report_format = raw_config.get('rendered_report_format', 'rst')
66
+ self.report_template_dir = raw_config.get(
67
+ 'report_template_dir',
68
+ os.path.join(DEFAULT_TEMPLATE_DIR, self.rendered_report_format)
69
+ )
70
+ self.rendered_report_dir = raw_config.get('rendered_report_dir', 'annotation_reports')
71
+ self.rendered_report_source_link_prefix = raw_config.get('rendered_report_source_link_prefix', None)
72
+ self.trim_filename_prefixes = raw_config.get('trim_filename_prefixes', [])
73
+ self.third_party_package_location = raw_config.get('third_party_package_location', "site-packages")
74
+ self.rendered_report_file_extension = f".{self.rendered_report_format}"
65
75
 
66
76
  self._configure_annotations(raw_config)
67
77
  self._configure_extensions()
@@ -241,10 +241,15 @@ def generate_docs(config_file, verbosity, report_files):
241
241
  try:
242
242
  config = AnnotationConfig(config_file, verbosity)
243
243
 
244
+ if not report_files:
245
+ raise ConfigurationException(
246
+ "No report files provided. Please provide one or more report files to generate docs from."
247
+ )
248
+
244
249
  for key in (
245
250
  "report_template_dir",
246
251
  "rendered_report_dir",
247
- "rendered_report_file_extension",
252
+ "rendered_report_format",
248
253
  "rendered_report_source_link_prefix",
249
254
  ):
250
255
  if not getattr(config, key):
@@ -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")
@@ -12,6 +12,7 @@ annotations:
12
12
  - ".. event_description:":
13
13
  - ".. event_data:":
14
14
  - ".. event_key_field:":
15
+ - ".. event_trigger_repository:":
15
16
  - ".. event_warning:":
16
17
  extensions:
17
18
  python:
@@ -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,42 @@ class OpenedxEvents(SphinxDirective):
114
115
  )
115
116
  event_section += nodes.paragraph("", "Event data: ", event_data_literal)
116
117
  event_section += nodes.paragraph(
117
- text=f"Defined at: {event['filename']} (line"
118
- f" {event['line_number']})"
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
+
121
154
  if event.get(".. event_warning:") not in (None, "None", "n/a", "N/A"):
122
155
  event_section += nodes.warning(
123
156
  "", nodes.paragraph("", event[".. event_warning:"]), ids=[f"warning-{event_name}"]
@@ -27,8 +27,7 @@ class ReportRenderer:
27
27
  self.config = config
28
28
  self.echo = self.config.echo
29
29
  self.report_files = report_files
30
- self.create_time = datetime.datetime.utcnow().isoformat()
31
-
30
+ self.create_time = datetime.datetime.now(tz=datetime.timezone.utc)
32
31
  self.full_report = self._aggregate_reports()
33
32
 
34
33
  self.jinja_environment = jinja2.Environment(
@@ -62,6 +61,12 @@ class ReportRenderer:
62
61
  loaded_report = yaml.safe_load(report_file)
63
62
 
64
63
  for filename in loaded_report:
64
+ trimmed_filename = filename
65
+ for prefix in self.config.trim_filename_prefixes:
66
+ if filename.startswith(prefix):
67
+ trimmed_filename = filename[len(prefix):]
68
+ break
69
+
65
70
  if filename in report:
66
71
  for loaded_annotation in loaded_report[filename]:
67
72
  found = False
@@ -74,9 +79,9 @@ class ReportRenderer:
74
79
  break
75
80
 
76
81
  if not found:
77
- report[filename].append(loaded_annotation)
82
+ report[trimmed_filename].append(loaded_annotation)
78
83
  else:
79
- report[filename] = loaded_report[filename]
84
+ report[trimmed_filename] = loaded_report[filename]
80
85
 
81
86
  def _aggregate_reports(self):
82
87
  """
@@ -91,11 +96,12 @@ class ReportRenderer:
91
96
 
92
97
  return report
93
98
 
94
- def _write_doc_file(self, doc_filename, doc_data):
99
+ def _write_doc_file(self, doc_title, doc_filename, doc_data):
95
100
  """
96
101
  Write out a single report file with the given data. This is rendered using the configured top level template.
97
102
 
98
103
  Args:
104
+ doc_title: Title to use for the document.
99
105
  doc_filename: Filename to write to.
100
106
  doc_data: Dict of reporting data to use, in the {'file name': [list, of, annotations,]} style.
101
107
  """
@@ -110,14 +116,16 @@ class ReportRenderer:
110
116
 
111
117
  with open(full_doc_filename, 'w') as output:
112
118
  output.write(self.top_level_template.render(
119
+ doc_title=doc_title,
113
120
  create_time=self.create_time,
114
121
  report=doc_data,
115
122
  all_choices=self.all_choices,
116
123
  all_annotations=self.config.annotation_tokens,
117
124
  group_mapping=self.group_mapping,
118
125
  slugify=slugify,
119
- source_link_prefix=self.config.rendered_report_source_link_prefix)
120
- )
126
+ source_link_prefix=self.config.rendered_report_source_link_prefix,
127
+ third_party_package_location=self.config.third_party_package_location,
128
+ ))
121
129
 
122
130
  def _generate_per_choice_docs(self):
123
131
  """
@@ -130,7 +138,7 @@ class ReportRenderer:
130
138
  if isinstance(annotation['annotation_data'], list) and choice in annotation['annotation_data']:
131
139
  choice_report[filename].append(annotation)
132
140
 
133
- self._write_doc_file(f'choice_{choice}', choice_report)
141
+ self._write_doc_file(f"All References to Choice '{choice}'", f'choice_{choice}', choice_report)
134
142
 
135
143
  def _generate_per_annotation_docs(self):
136
144
  """
@@ -143,13 +151,15 @@ class ReportRenderer:
143
151
  if report_annotation['annotation_token'] == annotation:
144
152
  annotation_report[filename].append(report_annotation)
145
153
 
146
- self._write_doc_file(f'annotation_{annotation}', annotation_report)
154
+ self._write_doc_file(
155
+ f"All References to Annotation '{annotation}'", f'annotation_{annotation}', annotation_report
156
+ )
147
157
 
148
158
  def render(self):
149
159
  """
150
160
  Perform the rendering of all documentation using the configured Jinja2 templates.
151
161
  """
152
162
  # Generate the top level list of all annotations
153
- self._write_doc_file('index', self.full_report)
163
+ self._write_doc_file("Complete Annotation List", 'index', self.full_report)
154
164
  self._generate_per_choice_docs()
155
165
  self._generate_per_annotation_docs()
@@ -0,0 +1,14 @@
1
+ {% if is_third_party %}
2
+ {# no links for third party code since we don't know where to link to #}
3
+ {% if annotation.extra and annotation.extra.object_id %}
4
+ {{ annotation.extra.object_id }} {% if annotation.line_number > 0 %}line {{ annotation.line_number }}{% endif %}: {{ annotation.annotation_token }} {% include "annotation_data.tpl" %}
5
+ {% else %}
6
+ {% if loop.changed(annotation.line_number)%}{{ filename }}:{{ annotation.line_number }}<br />{% endif %}:
7
+ {{ annotation.annotation_token }} {% include "annotation_data.tpl" %}
8
+ {% endif %}
9
+
10
+ {% elif annotation.extra and annotation.extra.object_id %}
11
+ <a href="{{ source_link_prefix }}{{ filename }}#L{{ annotation.line_number }}" target="_blank">{{ annotation.extra.object_id }} {% if annotation.line_number > 0 %}line {{ annotation.line_number }}{% endif %}</a>: {{ annotation.annotation_token }} {% include "annotation_data.tpl" %}
12
+ {% else %}
13
+ <a href="{{ source_link_prefix }}{{ filename }}#L{{ annotation.line_number }}" target="_blank">`{{ filename }}:{{ annotation.line_number }}: {{ annotation.annotation_token }} {% include "annotation_data.tpl" %}
14
+ {% endif %}
@@ -0,0 +1,8 @@
1
+ {% if annotation.annotation_data is sequence and annotation.annotation_data is not string %}
2
+ {% for a in annotation.annotation_data %}
3
+ <a href="choice-{{ slugify(a) }}.html">{{ a }}</a>{% if not loop.last %}, {% endif %}
4
+ {% endfor %}
5
+
6
+ {% else %}
7
+ {{ annotation.annotation_data }}
8
+ {% endif %}
@@ -0,0 +1,27 @@
1
+ {% extends "base.tpl" %}
2
+ {% block content %}
3
+ Annotations found in {{ report|length }} files.
4
+
5
+ {% for filename in report %}
6
+ {% set is_third_party = third_party_package_location in filename %}
7
+
8
+ <h2 id="file-{{ slugify(filename) }}">{{ filename }}</h2>
9
+ <div class="file-annotations">
10
+ {{ report[filename]|length }} annotations {% if is_third_party %}(installed package){% endif %}<br />
11
+ </div>
12
+
13
+ {% for annotation in report[filename] %}
14
+ {% if loop.changed(annotation.report_group_id) %}
15
+ {% if not loop.first %}</ul></div>{% endif %}
16
+ <div class="group-annotations"><ul>
17
+ {% endif %}
18
+ <li>{% include 'annotation.tpl' %}</li>
19
+ {% if loop.last %}
20
+ </ul></div>
21
+ {% endif %}
22
+ {% endfor %}
23
+
24
+
25
+ {% endfor %}
26
+
27
+ {% endblock %}
@@ -0,0 +1,92 @@
1
+ <html>
2
+ <head>
3
+ <title>{{ doc_title }}</title>
4
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
5
+ <style>
6
+ body {
7
+ font-family: 'Trebuchet MS', sans-serif;
8
+ }
9
+
10
+ .title {
11
+ text-align: center;
12
+ }
13
+
14
+ .table {
15
+ display: table;
16
+ border-spacing: 12px;
17
+ }
18
+
19
+ .row {
20
+ display: table-row;
21
+ margin-bottom: 0;
22
+ margin-top: 0;
23
+ width: 100%;
24
+ }
25
+
26
+ .cell1 {
27
+ display: table-cell;
28
+ width: 20%;
29
+ margin-right: 1%;
30
+ border: 1px solid #ccc;
31
+ margin 12px;
32
+ background-color: #ffffee;
33
+ }
34
+
35
+ .cell2 {
36
+ display: table-cell;
37
+ width: 79%;
38
+ margin-right: 1%;
39
+ margin 12px;
40
+ }
41
+
42
+ .group-annotations {
43
+ border: 1px solid #ccc;
44
+ margin: 10px;
45
+ }
46
+ </style>
47
+ </head>
48
+ <body>
49
+ <h1 class="title">{{ doc_title }}</h1>
50
+
51
+ <div class="table">
52
+ <div class="row">
53
+ <div class="cell1">
54
+ <h3><a href="index.html">Home</a></h3>
55
+
56
+ <h3>Annotations</h3>
57
+
58
+ <ul>
59
+ {% for a in all_annotations %}
60
+ <li><a href="annotation-{{ slugify(a) }}.html">annotation_{{ slugify(a) }}</a></li>
61
+ {% endfor %}
62
+ </ul>
63
+
64
+ <h3>Choices</h3>
65
+
66
+ <ul>
67
+ {% for choice in all_choices %}
68
+ <li><a href="choice-{{ slugify(choice) }}.html">choice_{{ slugify(choice) }}</a></li>
69
+ {% endfor %}
70
+ </ul>
71
+ </div>
72
+ <div class="cell2">
73
+ <h2>Files in this page</h2>
74
+ <ul>
75
+ {% for filename in report %}
76
+ <li><a href="#file-{{ slugify(filename) }}">{{ filename }}</a></li>
77
+ {% endfor %}
78
+ </ul>
79
+
80
+ {% block content %}{% endblock %}
81
+ </div>
82
+ </div>
83
+ </div>
84
+ {% block footer %}
85
+ <div class="footer">
86
+ <br /><br />
87
+ <hr />
88
+ Built at {{ create_time.strftime('%Y-%m-%d %H:%M:%S %Z') }}
89
+ </div>
90
+ {% endblock %}
91
+ </body>
92
+ </html>
@@ -0,0 +1,13 @@
1
+ {% if is_third_party %}
2
+ {# no links for third party code since we don't know where to link to #}
3
+ {% if annotation.extra and annotation.extra.object_id %}
4
+ {{ annotation.extra.object_id }} {% if annotation.line_number > 0 %}line {{ annotation.line_number }}{% endif %}: {{ annotation.annotation_token }} {% include "annotation_data.tpl" %}
5
+ {% else %}
6
+ {{ filename }}:{{ annotation.line_number }}: {{ annotation.annotation_token }} {% include "annotation_data.tpl" %}
7
+ {% endif %}
8
+
9
+ {% elif annotation.extra and annotation.extra.object_id %}
10
+ `{{ annotation.extra.object_id }} {% if annotation.line_number > 0 %}line {{ annotation.line_number }}{% endif %} <{{ source_link_prefix }}{{ filename }}#L{{ annotation.line_number }}>`_: {{ annotation.annotation_token }} {% include "annotation_data.tpl" %}
11
+ {% else %}
12
+ `{{ filename }}:{{ annotation.line_number }} <{{ source_link_prefix }}{{ filename }}#L{{ annotation.line_number }}>`_: {{ annotation.annotation_token }} {% include "annotation_data.tpl" %}
13
+ {% endif %}
@@ -0,0 +1,8 @@
1
+ {% if annotation.annotation_data is sequence and annotation.annotation_data is not string %}
2
+ {% for a in annotation.annotation_data %}
3
+ choice_{{ slugify(a) }}_{% if not loop.last %}, {% endif %}
4
+ {% endfor %}
5
+
6
+ {% else %}
7
+ {{ annotation.annotation_data }}
8
+ {% endif %}
@@ -0,0 +1,2 @@
1
+ .. _index.rst#{{ slugify(filename + '-' + annotation.report_group_id |string) }}:
2
+ .. admonition:: {{ group_mapping[annotation.annotation_token] or annotation.annotation_token }}
@@ -0,0 +1,34 @@
1
+ {% extends "base.tpl" %}
2
+ {% block content %}
3
+ Annotations found in {{ report|length }} files.
4
+
5
+ {% for filename in report %}
6
+ {% set is_third_party = third_party_package_location in filename %}
7
+
8
+ {{ filename }}
9
+ {{ "-" * filename|length }}
10
+
11
+ .. note:: {{ report[filename]|length }} annotations {% if is_third_party %}(installed package){% endif %}
12
+
13
+
14
+ {% for annotation in report[filename] %}
15
+ {% if annotation.report_group_id %}
16
+ {% if loop.changed(annotation.report_group_id) %}
17
+ {% include 'annotation_group.tpl' %}
18
+
19
+
20
+ {% endif %}
21
+ * {% include 'annotation.tpl' %}
22
+
23
+ {% else %}
24
+ {% if loop.changed(annotation.report_group_id) %}
25
+
26
+ {% endif %}
27
+ * {% include 'annotation.tpl' %}
28
+
29
+ {% endif %}
30
+ {% endfor %}
31
+
32
+ {% endfor %}
33
+
34
+ {% endblock %}
@@ -0,0 +1,41 @@
1
+ {{ "#" * doc_title|length }}
2
+ {{ doc_title }}
3
+ {{ "#" * doc_title|length }}
4
+
5
+ .. sidebar:: Table of Contents
6
+
7
+ `Home <index.rst>`_
8
+
9
+ Annotations
10
+
11
+ {% for a in all_annotations %}
12
+ * annotation_{{ slugify(a) }}_
13
+ {% endfor %}
14
+
15
+ Choices
16
+
17
+ {% for choice in all_choices %}
18
+ * choice_{{ slugify(choice) }}_
19
+ {% endfor %}
20
+
21
+
22
+ .. contents::
23
+
24
+ {% block content %}{% endblock %}
25
+
26
+
27
+ {# backlinks for all choices #}
28
+ {% for choice in all_choices %}
29
+ .. _choice_{{ slugify(choice) }}: {{ slugify('choice_' + choice) + '.rst' }}
30
+ {% endfor %}
31
+
32
+
33
+ {# backlinks for all annotations #}
34
+ {% for annotation in all_annotations %}
35
+ .. _annotation_{{ slugify(annotation) }}: {{ slugify('annotation_' + annotation) + '.rst' }}
36
+ {% endfor %}
37
+
38
+
39
+ {% block footer %}
40
+ Built at {{ create_time.strftime('%Y-%m-%d %H:%M:%S %Z') }}
41
+ {% endblock %}
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: code-annotations
3
- Version: 2.1.0
3
+ Version: 2.3.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
@@ -10,6 +10,7 @@ Keywords: edx pii code annotations
10
10
  Classifier: Development Status :: 3 - Alpha
11
11
  Classifier: Framework :: Django
12
12
  Classifier: Framework :: Django :: 4.2
13
+ Classifier: Framework :: Django :: 5.2
13
14
  Classifier: Intended Audience :: Developers
14
15
  Classifier: License :: OSI Approved :: Apache Software License
15
16
  Classifier: Natural Language :: English
@@ -23,18 +24,28 @@ License-File: LICENSE.txt
23
24
  License-File: NOTICE.txt
24
25
  Requires-Dist: python-slugify
25
26
  Requires-Dist: stevedore
26
- Requires-Dist: pyyaml
27
27
  Requires-Dist: click
28
+ Requires-Dist: pyyaml
28
29
  Requires-Dist: Jinja2
29
30
  Provides-Extra: django
30
31
  Requires-Dist: Django>=4.2; extra == "django"
32
+ Dynamic: author
33
+ Dynamic: author-email
34
+ Dynamic: classifier
35
+ Dynamic: description
36
+ Dynamic: description-content-type
37
+ Dynamic: home-page
38
+ Dynamic: keywords
39
+ Dynamic: license
40
+ Dynamic: license-file
41
+ Dynamic: provides-extra
42
+ Dynamic: requires-dist
43
+ Dynamic: requires-python
44
+ Dynamic: summary
31
45
 
32
46
  code-annotations
33
47
  =============================
34
48
 
35
- |pypi-badge| |CI| |codecov-badge| |doc-badge| |pyversions-badge|
36
- |license-badge|
37
-
38
49
  Extensible tools for parsing annotations in codebases
39
50
 
40
51
  Overview
@@ -88,31 +99,6 @@ refer to this `list of resources`_ if you need any assistance.
88
99
  .. _list of resources: https://open.edx.org/getting-help
89
100
 
90
101
 
91
- .. |pypi-badge| image:: https://img.shields.io/pypi/v/code-annotations.svg
92
- :target: https://pypi.python.org/pypi/code-annotations/
93
- :alt: PyPI
94
-
95
- .. |CI| image:: https://github.com/openedx/code-annotations/workflows/Python%20CI/badge.svg?branch=master
96
- :target: https://github.com/openedx/code-annotations/actions?query=workflow%3A%22Python+CI%22
97
- :alt: CI
98
-
99
- .. |codecov-badge| image:: http://codecov.io/github/edx/code-annotations/coverage.svg?branch=master
100
- :target: http://codecov.io/github/edx/code-annotations?branch=master
101
- :alt: Codecov
102
-
103
- .. |doc-badge| image:: https://readthedocs.org/projects/code-annotations/badge/?version=latest
104
- :target: http://code-annotations.readthedocs.io/en/latest/
105
- :alt: Documentation
106
-
107
- .. |pyversions-badge| image:: https://img.shields.io/pypi/pyversions/code-annotations.svg
108
- :target: https://pypi.python.org/pypi/code-annotations/
109
- :alt: Supported Python versions
110
-
111
- .. |license-badge| image:: https://img.shields.io/github/license/edx/code-annotations.svg
112
- :target: https://github.com/openedx/code-annotations/blob/master/LICENSE.txt
113
- :alt: License
114
-
115
-
116
102
  Change Log
117
103
  ----------
118
104
 
@@ -129,10 +115,15 @@ Change Log
129
115
  Unreleased
130
116
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
131
117
 
118
+ [2.2.0] - 2025-01-15
119
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
120
+
121
+ * Add support for optional Open edX Event trigger in-line annotation.
122
+
132
123
  [2.1.0] - 2024-12-12
133
124
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
134
125
 
135
- * Add support for optional event warning for in-line annotation.
126
+ * Add support for optional Open edX Event warning for in-line annotation.
136
127
 
137
128
  [2.0.0] - 2024-10-18
138
129
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -34,6 +34,15 @@ code_annotations/extensions/__init__.py
34
34
  code_annotations/extensions/base.py
35
35
  code_annotations/extensions/javascript.py
36
36
  code_annotations/extensions/python.py
37
+ code_annotations/report_templates/html/annotation.tpl
38
+ code_annotations/report_templates/html/annotation_data.tpl
39
+ code_annotations/report_templates/html/annotation_list.tpl
40
+ code_annotations/report_templates/html/base.tpl
41
+ code_annotations/report_templates/rst/annotation.tpl
42
+ code_annotations/report_templates/rst/annotation_data.tpl
43
+ code_annotations/report_templates/rst/annotation_group.tpl
44
+ code_annotations/report_templates/rst/annotation_list.tpl
45
+ code_annotations/report_templates/rst/base.tpl
37
46
  requirements/base.in
38
47
  tests/test_base.py
39
48
  tests/test_django_coverage.py
@@ -0,0 +1,111 @@
1
+ #!/usr/bin/env python
2
+ """
3
+ Package metadata for code_annotations.
4
+ """
5
+
6
+ import os
7
+ import re
8
+ import sys
9
+
10
+ from setuptools import setup
11
+
12
+
13
+ def get_version(*file_paths):
14
+ """
15
+ Extract the version string from the file at the given relative path fragments.
16
+ """
17
+ filename = os.path.join(os.path.dirname(__file__), *file_paths)
18
+ version_file = open(filename).read()
19
+ version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]", version_file, re.M)
20
+ if version_match:
21
+ return version_match.group(1)
22
+ raise RuntimeError("Unable to find version string.")
23
+
24
+
25
+ def load_requirements(*requirements_paths):
26
+ """
27
+ Load all requirements from the specified requirements files.
28
+
29
+ Returns:
30
+ list: Requirements file relative path strings
31
+ """
32
+ requirements = set()
33
+ for path in requirements_paths:
34
+ requirements.update(
35
+ line.split("#")[0].strip()
36
+ for line in open(path).readlines()
37
+ if is_requirement(line.strip())
38
+ )
39
+ return list(requirements)
40
+
41
+
42
+ def is_requirement(line):
43
+ """
44
+ Return True if the requirement line is a package requirement.
45
+
46
+ Returns:
47
+ bool: True if the line is not blank, a comment, a URL, or an included file
48
+ """
49
+ return not (
50
+ line == ""
51
+ or line.startswith("-r")
52
+ or line.startswith("#")
53
+ or line.startswith("-e")
54
+ or line.startswith("git+")
55
+ or line.startswith("-c")
56
+ )
57
+
58
+
59
+ VERSION = get_version("code_annotations", "__init__.py")
60
+
61
+ if sys.argv[-1] == "tag":
62
+ print("Tagging the version on github:")
63
+ os.system("git tag -a %s -m 'version %s'" % (VERSION, VERSION))
64
+ os.system("git push --tags")
65
+ sys.exit()
66
+
67
+ README = open(os.path.join(os.path.dirname(__file__), "README.rst")).read()
68
+ CHANGELOG = open(os.path.join(os.path.dirname(__file__), "CHANGELOG.rst")).read()
69
+
70
+ setup(
71
+ name="code-annotations",
72
+ version=VERSION,
73
+ description="""Extensible tools for parsing annotations in codebases""",
74
+ long_description=README + "\n\n" + CHANGELOG,
75
+ long_description_content_type="text/x-rst",
76
+ author="edX",
77
+ author_email="oscm@edx.org",
78
+ url="https://github.com/openedx/code-annotations",
79
+ packages=[
80
+ "code_annotations",
81
+ ],
82
+ entry_points={
83
+ "console_scripts": [
84
+ "code_annotations = code_annotations.cli:entry_point",
85
+ ],
86
+ "annotation_finder.searchers": [
87
+ "javascript = code_annotations.extensions.javascript:JavascriptAnnotationExtension",
88
+ "python = code_annotations.extensions.python:PythonAnnotationExtension",
89
+ ],
90
+ },
91
+ include_package_data=True,
92
+ install_requires=load_requirements("requirements/base.in"),
93
+ extras_require={"django": ["Django>=4.2"]},
94
+ license="Apache Software License 2.0",
95
+ zip_safe=False,
96
+ keywords="edx pii code annotations",
97
+ python_requires=">=3.11",
98
+ classifiers=[
99
+ "Development Status :: 3 - Alpha",
100
+ "Framework :: Django",
101
+ "Framework :: Django :: 4.2",
102
+ "Framework :: Django :: 5.2",
103
+ "Intended Audience :: Developers",
104
+ "License :: OSI Approved :: Apache Software License",
105
+ "Natural Language :: English",
106
+ "Programming Language :: Python",
107
+ "Programming Language :: Python :: 3",
108
+ "Programming Language :: Python :: 3.11",
109
+ "Programming Language :: Python :: 3.12",
110
+ ],
111
+ )
@@ -49,6 +49,40 @@ def test_generate_report_simple():
49
49
  assert os.path.exists(created_doc)
50
50
 
51
51
 
52
+ def test_generate_report_simple_html():
53
+ find_result = call_script(
54
+ (
55
+ 'static_find_annotations',
56
+ '--config_file',
57
+ 'tests/test_configurations/.annotations_test_python_only',
58
+ '--source_path=tests/extensions/python_test_files/simple_success.pyt',
59
+ '--no_lint',
60
+ ),
61
+ delete_test_reports=False)
62
+
63
+ assert find_result.exit_code == EXIT_CODE_SUCCESS
64
+ assert "Writing report..." in find_result.output
65
+ report_file = get_report_filename_from_output(find_result.output)
66
+
67
+ report_result = call_script(
68
+ (
69
+ 'generate_docs',
70
+ report_file,
71
+ '--config_file',
72
+ 'tests/test_configurations/.annotations_test_success_with_report_docs_html',
73
+ '-vv'
74
+ ),
75
+ delete_test_docs=False
76
+ )
77
+
78
+ assert find_result.exit_code == EXIT_CODE_SUCCESS
79
+ assert "Report rendered in" in report_result.output
80
+
81
+ # All file types are created
82
+ for created_doc in ('test_reports/index.html', 'test_reports/choice-id.html', 'test_reports/annotation-pii.html'):
83
+ assert os.path.exists(created_doc)
84
+
85
+
52
86
  def _do_find(source_path, new_report_path):
53
87
  """
54
88
  Do a static annotation search with report, rename the report to a distinct name.
@@ -167,4 +201,4 @@ def test_generate_report_missing_key():
167
201
  ))
168
202
 
169
203
  assert report_result.exit_code == EXIT_CODE_FAILURE
170
- assert "No report_template_dir key in tests/test_configurations/" in report_result.output
204
+ assert "No rendered_report_source_link_prefix key in" in report_result.output
@@ -1,19 +0,0 @@
1
- """
2
- Expose contrib configuration file paths as Python variables, for use in 3rd-party utilities.
3
- """
4
- import os
5
-
6
- import pkg_resources
7
-
8
- FEATURE_TOGGLE_ANNOTATIONS_CONFIG_PATH = pkg_resources.resource_filename(
9
- "code_annotations",
10
- os.path.join("contrib", "config", "feature_toggle_annotations.yaml"),
11
- )
12
- SETTING_ANNOTATIONS_CONFIG_PATH = pkg_resources.resource_filename(
13
- "code_annotations",
14
- os.path.join("contrib", "config", "setting_annotations.yaml"),
15
- )
16
- OPENEDX_EVENTS_ANNOTATIONS_CONFIG_PATH = pkg_resources.resource_filename(
17
- "code_annotations",
18
- os.path.join("contrib", "config", "openedx_events_annotations.yaml"),
19
- )
@@ -1,110 +0,0 @@
1
- #!/usr/bin/env python
2
- """
3
- Package metadata for code_annotations.
4
- """
5
-
6
- import os
7
- import re
8
- import sys
9
-
10
- from setuptools import setup
11
-
12
-
13
- def get_version(*file_paths):
14
- """
15
- Extract the version string from the file at the given relative path fragments.
16
- """
17
- filename = os.path.join(os.path.dirname(__file__), *file_paths)
18
- version_file = open(filename).read()
19
- version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]",
20
- version_file, re.M)
21
- if version_match:
22
- return version_match.group(1)
23
- raise RuntimeError('Unable to find version string.')
24
-
25
-
26
- def load_requirements(*requirements_paths):
27
- """
28
- Load all requirements from the specified requirements files.
29
-
30
- Returns:
31
- list: Requirements file relative path strings
32
- """
33
- requirements = set()
34
- for path in requirements_paths:
35
- requirements.update(
36
- line.split('#')[0].strip() for line in open(path).readlines()
37
- if is_requirement(line.strip())
38
- )
39
- return list(requirements)
40
-
41
-
42
- def is_requirement(line):
43
- """
44
- Return True if the requirement line is a package requirement.
45
-
46
- Returns:
47
- bool: True if the line is not blank, a comment, a URL, or an included file
48
- """
49
- return not (
50
- line == '' or
51
- line.startswith('-r') or
52
- line.startswith('#') or
53
- line.startswith('-e') or
54
- line.startswith('git+') or
55
- line.startswith('-c')
56
- )
57
-
58
-
59
- VERSION = get_version('code_annotations', '__init__.py')
60
-
61
- if sys.argv[-1] == 'tag':
62
- print("Tagging the version on github:")
63
- os.system("git tag -a %s -m 'version %s'" % (VERSION, VERSION))
64
- os.system("git push --tags")
65
- sys.exit()
66
-
67
- README = open(os.path.join(os.path.dirname(__file__), 'README.rst')).read()
68
- CHANGELOG = open(os.path.join(os.path.dirname(__file__), 'CHANGELOG.rst')).read()
69
-
70
- setup(
71
- name='code-annotations',
72
- version=VERSION,
73
- description="""Extensible tools for parsing annotations in codebases""",
74
- long_description=README + '\n\n' + CHANGELOG,
75
- long_description_content_type='text/x-rst',
76
- author='edX',
77
- author_email='oscm@edx.org',
78
- url='https://github.com/openedx/code-annotations',
79
- packages=[
80
- 'code_annotations',
81
- ],
82
- entry_points={
83
- 'console_scripts': [
84
- 'code_annotations = code_annotations.cli:entry_point',
85
- ],
86
- 'annotation_finder.searchers': [
87
- 'javascript = code_annotations.extensions.javascript:JavascriptAnnotationExtension',
88
- 'python = code_annotations.extensions.python:PythonAnnotationExtension',
89
- ],
90
- },
91
- include_package_data=True,
92
- install_requires=load_requirements('requirements/base.in'),
93
- extras_require={"django": ["Django>=4.2"]},
94
- license="Apache Software License 2.0",
95
- zip_safe=False,
96
- keywords='edx pii code annotations',
97
- python_requires=">=3.11",
98
- classifiers=[
99
- 'Development Status :: 3 - Alpha',
100
- 'Framework :: Django',
101
- 'Framework :: Django :: 4.2',
102
- 'Intended Audience :: Developers',
103
- 'License :: OSI Approved :: Apache Software License',
104
- 'Natural Language :: English',
105
- 'Programming Language :: Python',
106
- 'Programming Language :: Python :: 3',
107
- 'Programming Language :: Python :: 3.11',
108
- 'Programming Language :: Python :: 3.12',
109
- ],
110
- )
@@ -1,7 +1,7 @@
1
1
  python-slugify
2
2
  stevedore
3
- pyyaml
4
3
  click
4
+ pyyaml
5
5
  Jinja2
6
6
 
7
7
  [django]