Skip to content

Commit 7c23d03

Browse files
committed
Move __init__.py to src directory
Renamed sphinx_github_alerts/__init__.py to src/sphinx_github_alerts/__init__.py to follow a src-based project structure. No code changes were made.
1 parent 6a55f29 commit 7c23d03

File tree

1 file changed

+139
-139
lines changed

1 file changed

+139
-139
lines changed
Lines changed: 139 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -1,139 +1,139 @@
1-
import re
2-
3-
from sphinx.util import logging
4-
from sphinx.errors import ConfigError
5-
6-
logger = logging.getLogger(__name__)
7-
8-
RECOGNISED_TYPES = {
9-
'note': 'note',
10-
'tip': 'tip',
11-
'important': 'important',
12-
'warning': 'warning',
13-
'caution': 'caution',
14-
}
15-
16-
def validate_sphinx_github_alerts_config(app, config):
17-
"""Validate sphinx_github_alerts__config."""
18-
redirects = getattr(config, 'sphinx_github_alerts_redirects', {})
19-
# convert all keys and values to lowercase
20-
redirects = {k.lower(): v.lower() for k, v in redirects.items()}
21-
app.config.sphinx_github_alerts_redirects = redirects
22-
if not isinstance(redirects, dict):
23-
raise ConfigError("sphinx_github_alerts_redirects must be a dict.")
24-
invalid = set(redirects.keys()) - set(RECOGNISED_TYPES.keys())
25-
if invalid:
26-
raise ConfigError(f"sphinx_github_alerts_redirects has invalid keys: {sorted(invalid)}. "
27-
f"Allowed keys: {sorted(RECOGNISED_TYPES.keys())}")
28-
# validate leading spaces
29-
leading_spaces = getattr(config, 'sphinx_github_alerts_leading_spaces', None)
30-
if not isinstance(leading_spaces, int) or leading_spaces < 1:
31-
raise ConfigError("sphinx_github_alerts_leading_spaces must be an integer >= 1.")
32-
# validate backquotes
33-
backquotes = getattr(config, 'sphinx_github_alerts_backquotes', None)
34-
if not isinstance(backquotes, int) or backquotes < 3:
35-
raise ConfigError("sphinx_github_alerts_backquotes must be an integer >= 3.")
36-
37-
def convert_github_alerts(app, docname, source):
38-
source_file = app.env.doc2path(docname)
39-
if not(source_file.endswith('.md') or source_file.endswith('.ipynb') or source_file.endswith('.rst')):
40-
logger.warning(f"Unrecognised source file type for '{source_file}', skipping...",location=docname)
41-
pass
42-
"""Replace GitHub alerts with Sphinx admonitions."""
43-
44-
# Find any block starting with '> [!type] and replace it
45-
# with the appropriate admonition syntax for Sphinx.'
46-
# type can only be one of 'note', 'tip', 'important', 'warning', 'caution', etc.
47-
# Capitalization does not matter.
48-
49-
# Find each block within the source
50-
content = source[0]
51-
# store old content for comparison
52-
old_content = content
53-
54-
# Pattern to find consecutive lines starting with '>'
55-
if source_file.endswith('.ipynb'):
56-
pattern = r'^(?:\s*\">.*\n?)+' # Matches one or more consecutive lines starting with '>', allowing leading spaces
57-
type_pattern = r'\s*\">\s*\[!(\w+)\]' # Pattern to extract type from first line, allowing leading spaces
58-
strip_pattern = r'^\s*\">\s?' # Pattern to strip leading '> ' from each line
59-
new_pattern = r'"'
60-
arrows_pattern = r'^\s*\"(?:>\s*)+'
61-
else: # meaning .md or *.rst
62-
pattern = r'^(?:>.*\n?)+' # Matches one or more consecutive lines starting with '>'
63-
type_pattern = r'>\s*\[!(\w+)\]' # Pattern to extract type from first line
64-
strip_pattern = r'^>\s?' # Pattern to strip leading '> ' from each line
65-
new_pattern = r''
66-
arrows_pattern = r'^(?:>\s*)+'
67-
68-
# Find all matches
69-
matches = re.finditer(pattern, content, re.MULTILINE)
70-
new_blocks = []
71-
72-
EXTENDED_TYPES = RECOGNISED_TYPES.copy() | app.env.config.sphinx_github_alerts_redirects
73-
quotes = '`'*(app.env.config.sphinx_github_alerts_backquotes)
74-
75-
for i,match in enumerate(matches):
76-
block = match.group(0)
77-
# Process each block here
78-
first_line = block.splitlines()[0]
79-
# extract type from first line and convert to lowercase
80-
type_match = re.search(type_pattern, first_line)
81-
if type_match: # do nothing if no type found
82-
type_match = type_match.group(1).lower()
83-
if type_match in EXTENDED_TYPES:
84-
# strip all > and leading spaces from each line in block
85-
# exclude first line
86-
stripped_block = '\n'.join([re.sub(strip_pattern, new_pattern, line) for line in block.splitlines()[1:]])
87-
# create replacement admonition block depending on original source type (.md, .ipynb or .rst)
88-
if source_file.endswith('.md'):
89-
replacement = f"\n{quotes}{{{EXTENDED_TYPES[type_match]}}}\n{stripped_block}\n{quotes}\n"
90-
elif source_file.endswith('.ipynb'):
91-
# make sure to add the necessary quotes and commas for ipynb format
92-
if stripped_block[-1] == '"':
93-
stripped_block = stripped_block[:-1] + '\\n",'
94-
replacement = f"\n\"{quotes}{{{EXTENDED_TYPES[type_match]}}}\\n\",\n{stripped_block}\n\"{quotes}\\n\""
95-
else:
96-
replacement = f"\n\"{quotes}{{{EXTENDED_TYPES[type_match]}}}\\n\",\n{stripped_block}\n\"{quotes}\\n\",\n"
97-
elif source_file.endswith('.rst'):
98-
replacement = f"\n.. {EXTENDED_TYPES[type_match]}:: \n\n"
99-
# indent each line of stripped_block by set number of leading spaces
100-
indent = " " * app.env.config.sphinx_github_alerts_leading_spaces
101-
indented_block = '\n'.join([indent + line for line in stripped_block.splitlines()])
102-
replacement += f"{indented_block}\n"
103-
# store the new block
104-
if replacement:
105-
new_blocks.append(replacement)
106-
else:
107-
new_blocks.append(block)
108-
else:
109-
# find the line number of the match in the content
110-
line_number = content[:match.start()].count('\n') + 1
111-
logger.warning(f"Unrecognised GitHub alert type '{type_match}', skipping...",location=(docname, line_number))
112-
new_blocks.append(block)
113-
else:
114-
new_blocks.append(block)
115-
116-
# replace all blocks in content with new_blocks
117-
for match, new_block in zip(re.finditer(pattern, content, re.MULTILINE), new_blocks):
118-
content = content.replace(match.group(0), new_block)
119-
120-
source[0] = content
121-
122-
pass
123-
124-
def setup(app):
125-
126-
app.add_config_value('sphinx_github_alerts_redirects', {}, 'html')
127-
app.add_config_value('sphinx_github_alerts_backquotes', 3, 'html')
128-
app.add_config_value('sphinx_github_alerts_leading_spaces', 3, 'html')
129-
app.connect('config-inited', validate_sphinx_github_alerts_config)
130-
app.connect('source-read', convert_github_alerts)
131-
132-
return {
133-
"version": "builtin",
134-
'parallel_read_safe': True,
135-
'parallel_write_safe': True,
136-
}
137-
138-
139-
1+
import re
2+
3+
from sphinx.util import logging
4+
from sphinx.errors import ConfigError
5+
6+
logger = logging.getLogger(__name__)
7+
8+
RECOGNISED_TYPES = {
9+
'note': 'note',
10+
'tip': 'tip',
11+
'important': 'important',
12+
'warning': 'warning',
13+
'caution': 'caution',
14+
}
15+
16+
def validate_sphinx_github_alerts_config(app, config):
17+
"""Validate sphinx_github_alerts__config."""
18+
redirects = getattr(config, 'sphinx_github_alerts_redirects', {})
19+
# convert all keys and values to lowercase
20+
redirects = {k.lower(): v.lower() for k, v in redirects.items()}
21+
app.config.sphinx_github_alerts_redirects = redirects
22+
if not isinstance(redirects, dict):
23+
raise ConfigError("sphinx_github_alerts_redirects must be a dict.")
24+
invalid = set(redirects.keys()) - set(RECOGNISED_TYPES.keys())
25+
if invalid:
26+
raise ConfigError(f"sphinx_github_alerts_redirects has invalid keys: {sorted(invalid)}. "
27+
f"Allowed keys: {sorted(RECOGNISED_TYPES.keys())}")
28+
# validate leading spaces
29+
leading_spaces = getattr(config, 'sphinx_github_alerts_leading_spaces', None)
30+
if not isinstance(leading_spaces, int) or leading_spaces < 1:
31+
raise ConfigError("sphinx_github_alerts_leading_spaces must be an integer >= 1.")
32+
# validate backquotes
33+
backquotes = getattr(config, 'sphinx_github_alerts_backquotes', None)
34+
if not isinstance(backquotes, int) or backquotes < 3:
35+
raise ConfigError("sphinx_github_alerts_backquotes must be an integer >= 3.")
36+
37+
def convert_github_alerts(app, docname, source):
38+
source_file = app.env.doc2path(docname)
39+
if not(source_file.endswith('.md') or source_file.endswith('.ipynb') or source_file.endswith('.rst')):
40+
logger.warning(f"Unrecognised source file type for '{source_file}', skipping...",location=docname)
41+
pass
42+
"""Replace GitHub alerts with Sphinx admonitions."""
43+
44+
# Find any block starting with '> [!type] and replace it
45+
# with the appropriate admonition syntax for Sphinx.'
46+
# type can only be one of 'note', 'tip', 'important', 'warning', 'caution', etc.
47+
# Capitalization does not matter.
48+
49+
# Find each block within the source
50+
content = source[0]
51+
# store old content for comparison
52+
old_content = content
53+
54+
# Pattern to find consecutive lines starting with '>'
55+
if source_file.endswith('.ipynb'):
56+
pattern = r'^(?:\s*\">.*\n?)+' # Matches one or more consecutive lines starting with '>', allowing leading spaces
57+
type_pattern = r'\s*\">\s*\[!(\w+)\]' # Pattern to extract type from first line, allowing leading spaces
58+
strip_pattern = r'^\s*\">\s?' # Pattern to strip leading '> ' from each line
59+
new_pattern = r'"'
60+
arrows_pattern = r'^\s*\"(?:>\s*)+'
61+
else: # meaning .md or *.rst
62+
pattern = r'^(?:>.*\n?)+' # Matches one or more consecutive lines starting with '>'
63+
type_pattern = r'>\s*\[!(\w+)\]' # Pattern to extract type from first line
64+
strip_pattern = r'^>\s?' # Pattern to strip leading '> ' from each line
65+
new_pattern = r''
66+
arrows_pattern = r'^(?:>\s*)+'
67+
68+
# Find all matches
69+
matches = re.finditer(pattern, content, re.MULTILINE)
70+
new_blocks = []
71+
72+
EXTENDED_TYPES = RECOGNISED_TYPES.copy() | app.env.config.sphinx_github_alerts_redirects
73+
quotes = '`'*(app.env.config.sphinx_github_alerts_backquotes)
74+
75+
for i,match in enumerate(matches):
76+
block = match.group(0)
77+
# Process each block here
78+
first_line = block.splitlines()[0]
79+
# extract type from first line and convert to lowercase
80+
type_match = re.search(type_pattern, first_line)
81+
if type_match: # do nothing if no type found
82+
type_match = type_match.group(1).lower()
83+
if type_match in EXTENDED_TYPES:
84+
# strip all > and leading spaces from each line in block
85+
# exclude first line
86+
stripped_block = '\n'.join([re.sub(strip_pattern, new_pattern, line) for line in block.splitlines()[1:]])
87+
# create replacement admonition block depending on original source type (.md, .ipynb or .rst)
88+
if source_file.endswith('.md'):
89+
replacement = f"\n{quotes}{{{EXTENDED_TYPES[type_match]}}}\n{stripped_block}\n{quotes}\n"
90+
elif source_file.endswith('.ipynb'):
91+
# make sure to add the necessary quotes and commas for ipynb format
92+
if stripped_block[-1] == '"':
93+
stripped_block = stripped_block[:-1] + '\\n",'
94+
replacement = f"\n\"{quotes}{{{EXTENDED_TYPES[type_match]}}}\\n\",\n{stripped_block}\n\"{quotes}\\n\""
95+
else:
96+
replacement = f"\n\"{quotes}{{{EXTENDED_TYPES[type_match]}}}\\n\",\n{stripped_block}\n\"{quotes}\\n\",\n"
97+
elif source_file.endswith('.rst'):
98+
replacement = f"\n.. {EXTENDED_TYPES[type_match]}:: \n\n"
99+
# indent each line of stripped_block by set number of leading spaces
100+
indent = " " * app.env.config.sphinx_github_alerts_leading_spaces
101+
indented_block = '\n'.join([indent + line for line in stripped_block.splitlines()])
102+
replacement += f"{indented_block}\n"
103+
# store the new block
104+
if replacement:
105+
new_blocks.append(replacement)
106+
else:
107+
new_blocks.append(block)
108+
else:
109+
# find the line number of the match in the content
110+
line_number = content[:match.start()].count('\n') + 1
111+
logger.warning(f"Unrecognised GitHub alert type '{type_match}', skipping...",location=(docname, line_number))
112+
new_blocks.append(block)
113+
else:
114+
new_blocks.append(block)
115+
116+
# replace all blocks in content with new_blocks
117+
for match, new_block in zip(re.finditer(pattern, content, re.MULTILINE), new_blocks):
118+
content = content.replace(match.group(0), new_block)
119+
120+
source[0] = content
121+
122+
pass
123+
124+
def setup(app):
125+
126+
app.add_config_value('sphinx_github_alerts_redirects', {}, 'html')
127+
app.add_config_value('sphinx_github_alerts_backquotes', 3, 'html')
128+
app.add_config_value('sphinx_github_alerts_leading_spaces', 3, 'html')
129+
app.connect('config-inited', validate_sphinx_github_alerts_config)
130+
app.connect('source-read', convert_github_alerts)
131+
132+
return {
133+
"version": "builtin",
134+
'parallel_read_safe': True,
135+
'parallel_write_safe': True,
136+
}
137+
138+
139+

0 commit comments

Comments
 (0)