为什么我在 Sphinxcontrib-httpexample 中使用 python 时没有获得 JSON 属性的换行符?

问题描述 投票:0回答:1

我正在尝试在 sphinxcontrib-httpexample 中添加一个新选项卡,例如

curl
httpie
python-request
。我已经进行了所需的更改,除了输出格式之外,一切都正常。

JSON 文件:

POST /plone/front-page/@aliases HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0
Content-Type: application/json

{
    "items": [
        {
            "path": "/new-alias"
        },
        {
            "path": "/old-alias"
        },
        {
            "path": "/final-alias"
        }
    ]
}

Python代码(我将其添加到这个文件中):

def build_plone_javascript_command(request):
    javascript_code = 'createAliasesMutation'
    redir_input2 = ''

    # Request body
    data = maybe_str(request.data())
    if data:
        if is_json(request.headers.get('Content-Type', '')):
            redir_input2 = json.dumps(data, indent=2, sort_keys=True,
                           separators=(',', ': '))
        else:
            redir_input2 = data
            
    # Output string
    output_string = f"{javascript_code}\n|\nconst aliasesData = {redir_input2};"

    return output_string

python 函数返回一个格式化字符串,然后将其放入 Sphinx CodeBlock 中。

修改后的Sphinx代码块:

from docutils import nodes
from docutils.parsers.rst import directives
from docutils.statemachine import StringList
from sphinx.directives.code import CodeBlock
from sphinxcontrib.httpexample import builders
from sphinxcontrib.httpexample import parsers
from sphinxcontrib.httpexample import utils

import os
import re


AVAILABLE_BUILDERS = {
    'curl': (builders.build_curl_command, 'bash'),
    'wget': (builders.build_wget_command, 'bash'),
    'httpie': (builders.build_httpie_command, 'bash'),
    'requests': (builders.build_requests_command, 'python'),
    'python-requests': (builders.build_requests_command, 'python'),
    'plone_javascript': (builders.build_plone_javascript_command, 'javascript'),
}

AVAILABLE_FIELDS = [
    'query'
]


def choose_builders(arguments):
    return [directives.choice(argument, AVAILABLE_BUILDERS)
            for argument in (arguments or [])]


class HTTPExample(CodeBlock):

    required_arguments = 0
    optional_arguments = len(AVAILABLE_BUILDERS)

    option_spec = utils.merge_dicts(CodeBlock.option_spec, {
        'request': directives.unchanged,
        'response': directives.unchanged,
    })

    def run(self):
        config = self.state.document.settings.env.config

        # Read enabled builders; Defaults to None
        chosen_builders = choose_builders(self.arguments)

        # Enable 'http' language for http part
        self.arguments = ['http']

        # process 'query' reST fields
        if self.content:
            raw = ('\r\n'.join(self.content)).encode('utf-8')
            request = parsers.parse_request(raw)
            params, _ = request.extract_fields('query')
            params = [(p[1], p[2]) for p in params]
            new_path = utils.add_url_params(request.path, params)
            self.content[0] = ' '.join(
                [request.command, new_path, request.request_version])

        # split the request and optional response in the content.
        # The separator is two empty lines followed by a line starting with
        # 'HTTP/' or 'HTTP '
        request_content = StringList()
        request_content_no_fields = StringList()
        response_content = None
        emptylines_count = 0
        in_response = False
        is_field = r':({}) (.+): (.+)'.format('|'.join(AVAILABLE_FIELDS))
        for i, line in enumerate(self.content):
            source = self.content.source(i)
            if in_response:
                response_content.append(line, source)
            else:
                if emptylines_count >= 2 and \
                        (line.startswith('HTTP/') or line.startswith('HTTP ')):
                    in_response = True
                    response_content = StringList()
                    response_content.append(line, source)
                elif line == '':
                    emptylines_count += 1
                else:
                    request_content.extend(
                        StringList([''] * emptylines_count, source))
                    request_content.append(line, source)

                    if not re.match(is_field, line):
                        request_content_no_fields.extend(
                            StringList([''] * emptylines_count, source))
                        request_content_no_fields.append(line, source)

                    emptylines_count = 0

        # Load optional external request
        cwd = os.path.dirname(self.state.document.current_source)
        if 'request' in self.options:
            request = utils.resolve_path(self.options['request'], cwd)
            with open(request) as fp:
                request_content = request_content_no_fields = StringList(
                    list(map(str.rstrip, fp.readlines())), request)

        # Load optional external response
        if 'response' in self.options:
            response = utils.resolve_path(self.options['response'], cwd)
            with open(response) as fp:
                response_content = StringList(
                    list(map(str.rstrip, fp.readlines())), response)

        # reset the content to the request, stripped of the reST fields
        self.content = request_content_no_fields

        # Wrap and render main directive as 'http-example-http'
        klass = 'http-example-http'
        container = nodes.container('', classes=[klass])
        container.append(nodes.caption('', 'http'))
        container.extend(super(HTTPExample, self).run())

        # Init result node list
        result = [container]

        # reset the content to just the request
        self.content = request_content

        # Append builder responses
        if request_content_no_fields:
            raw = ('\r\n'.join(request_content_no_fields)).encode('utf-8')
            for name in chosen_builders:
                request = parsers.parse_request(raw, config.httpexample_scheme)
                builder_, language = AVAILABLE_BUILDERS[name]

                
                name = 'JavaScript' if name == 'plone_javascript' else name
                
                command = builder_(request)

                content = StringList(
                    [command], request_content_no_fields.source(0))
                options = self.options.copy()
                options.pop('name', None)
                options.pop('caption', None)

                block = CodeBlock(
                    'code-block',
                    [language],
                    options,
                    content,
                    self.lineno,
                    self.content_offset,
                    self.block_text,
                    self.state,
                    self.state_machine
                )

                # Wrap and render main directive as 'http-example-{name}'
                klass = 'http-example-{}'.format(name)
                container = nodes.container('', classes=[klass])
                container.append(nodes.caption('', name))
                container.extend(block.run())

                # Append to result nodes
                result.append(container)

        # Append optional response
        if response_content:
            options = self.options.copy()
            options.pop('name', None)
            options.pop('caption', None)

            block = CodeBlock(
                'code-block',
                ['http'],
                options,
                response_content,
                self.lineno,
                self.content_offset,
                self.block_text,
                self.state,
                self.state_machine
            )

            # Wrap and render main directive as 'http-example-response'
            klass = 'http-example-response'
            container = nodes.container('', classes=[klass])
            container.append(nodes.caption('', 'response'))
            container.extend(block.run())

            # Append to result nodes
            result.append(container)

        # Final wrap
        container_node = nodes.container('', classes=['http-example'])
        container_node.extend(result)

        return [container_node]

输出:

createAliasesMutation | const aliasesData = { "items": [ { "datetime": "2022-05-05", "path": "/old-page", "redirect-to": "/front-page" }, { "datetime": "2022-05-05", "path": "/fizzbuzz", "redirect-to": "/front-page" } ] };

期望的输出(类似这样):

createAliasesMutation 
| 
const aliasesData =
{
    "items": [
        {
            "path": "/new-alias"
        },
        {
            "path": "/old-alias"
        },
        {
            "path": "/final-alias"
        }
    ]
}

HTML 文字:

<pre id="codecell19"><span></span><span class="nx">createAliasesMutation</span>
<span class="o">|</span>
<span class="kd">const</span><span class="w"> </span><span class="nx">aliasesData</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">  </span><span class="s2">"items"</span><span class="o">:</span><span class="w"> </span><span class="p">[</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">      </span><span class="s2">"datetime"</span><span class="o">:</span><span class="w"> </span><span class="s2">"2022-05-05"</span><span class="p">,</span>
<span class="w">      </span><span class="s2">"path"</span><span class="o">:</span><span class="w"> </span><span class="s2">"/old-page"</span><span class="p">,</span>
<span class="w">      </span><span class="s2">"redirect-to"</span><span class="o">:</span><span class="w"> </span><span class="s2">"/front-page"</span>
<span class="w">    </span><span class="p">},</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">      </span><span class="s2">"datetime"</span><span class="o">:</span><span class="w"> </span><span class="s2">"2022-05-05"</span><span class="p">,</span>
<span class="w">      </span><span class="s2">"path"</span><span class="o">:</span><span class="w"> </span><span class="s2">"/fizzbuzz"</span><span class="p">,</span>
<span class="w">      </span><span class="s2">"redirect-to"</span><span class="o">:</span><span class="w"> </span><span class="s2">"/front-page"</span>
<span class="w">    </span><span class="p">}</span>
<span class="w">  </span><span class="p">]</span>
<span class="p">};</span>
</pre>

我尝试使用此

stackoverflow问题
中的.replace('\\n','\n'),但仍然不起作用。

编辑:我再次发布此问题,因为我没有在之前的帖子中添加所有详细信息。

python json newline python-sphinx sphinx
1个回答
0
投票

问题可能是这里

.http-example div[class^='highlight'] pre {
    white-space: normal;
}

我不确定他们为什么添加这个,但是 white-space

 属性设置为 
normal 会将所有空白(包括换行符)折叠成一个空格。这是大多数元素的默认值,但对于
pre
,默认值是
pre
,这可能是您的用例所需要的。
    

© www.soinside.com 2019 - 2024. All rights reserved.