Files
zulip/zerver/lib/bugdown/api_code_examples.py
Eeshan Garg c158869096 Rename tools/lib/api_tests.py to zerver/lib/api_test_helpers.py.
Now that the Markdown extension defined in
zerver/lib/bugdown/api_generate_examples depended on code in the
tools/lib/* directory, it caused the production tests to fail since
the tools/ directory wouldn't exist in a production environment.
2018-01-31 07:30:54 -05:00

113 lines
3.6 KiB
Python

import re
import os
import sys
import ujson
import inspect
from markdown.extensions import Extension
from markdown.preprocessors import Preprocessor
from typing import Any, Dict, Optional, List
import markdown
import zerver.lib.api_test_helpers
REGEXP = re.compile(r'\{generate_code_example\|\s*(.+?)\s*\|\s*(.+?)\s*\}')
PYTHON_CLIENT_CONFIG_LINES = """
#!/usr/bin/env python3
import zulip
# Download ~/zuliprc-dev from your dev server
client = zulip.Client(config_file="~/zuliprc-dev")
"""
class APICodeExamplesGenerator(Extension):
def extendMarkdown(self, md: markdown.Markdown, md_globals: Dict[str, Any]) -> None:
md.preprocessors.add(
'generate_code_example', APICodeExamplesPreprocessor(md, self.getConfigs()), '_begin'
)
class APICodeExamplesPreprocessor(Preprocessor):
def __init__(self, md: markdown.Markdown, config: Dict[str, Any]) -> None:
super(APICodeExamplesPreprocessor, self).__init__(md)
def run(self, lines: List[str]) -> List[str]:
done = False
while not done:
for line in lines:
loc = lines.index(line)
match = REGEXP.search(line)
if match:
function = match.group(1)
key = match.group(2)
if key == 'fixture':
text = self.render_fixture(function)
elif key == 'method':
text = self.render_code_example(function)
# The line that contains the directive to include the macro
# may be preceded or followed by text or tags, in that case
# we need to make sure that any preceding or following text
# stays the same.
line_split = REGEXP.split(line, maxsplit=0)
preceding = line_split[0]
following = line_split[-1]
text = [preceding] + text + [following]
lines = lines[:loc] + text + lines[loc+1:]
break
else:
done = True
return lines
def render_fixture(self, function: str) -> List[str]:
fixture = []
fixture_dict = zerver.lib.api_test_helpers.FIXTURES[function]
fixture_json = ujson.dumps(fixture_dict, indent=4, sort_keys=True)
fixture.append('```')
fixture.extend(fixture_json.splitlines())
fixture.append('```')
return fixture
def render_code_example(self, function: str) -> List[str]:
method = zerver.lib.api_test_helpers.TEST_FUNCTIONS[function]
function_source_lines = inspect.getsourcelines(method)[0]
ce_regex = re.compile(r'\# \{code_example\|\s*(.+?)\s*\}')
start = 0
end = 0
for line in function_source_lines:
match = ce_regex.search(line)
if match:
if match.group(1) == 'start':
start = function_source_lines.index(line)
elif match.group(1) == 'end':
end = function_source_lines.index(line)
config = PYTHON_CLIENT_CONFIG_LINES.splitlines()
snippet = function_source_lines[start + 1: end]
code_example = []
code_example.append('```')
code_example.extend(config)
for line in snippet:
# Remove one level of indentation and strip newlines
code_example.append(line[4:].rstrip())
code_example.append('print(result)')
code_example.append('```')
return code_example
def makeExtension(*args: Any, **kwargs: str) -> APICodeExamplesGenerator:
return APICodeExamplesGenerator(kwargs)