Man page clean-up (#1508)

Ensure we don’t include dynamic content in the static man pages.
This commit is contained in:
Jakub Roztocil 2023-05-22 11:56:30 -07:00 committed by GitHub
parent c2677eeccf
commit 2da955fb06
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 67 additions and 48 deletions

View File

@ -1,27 +1,22 @@
name: Update Autogenerated Files
name: Update Generated Content
on:
push:
branches:
- master
jobs:
regen-autogenerated-files:
update-content:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: 3.9
- run: make regen-all
- run: make content
- name: Create Pull Request
id: cpr
uses: peter-evans/create-pull-request@v4
with:
commit-message: "[automated] Update auto-generated files"
title: "[automated] Update auto-generated files"
commit-message: "[automated] Update generated content"
title: "[automated] Update generated content"
delete-branch: true
token: ${{ secrets.GITHUB_TOKEN }}

View File

@ -231,15 +231,15 @@ brew-test:
brew audit --strict httpie
###############################################################################
# Regeneration
# Generated content
###############################################################################
regen-all: regen-man-pages regen-install-methods
content: man installation-docs
regen-man-pages: install
man: install
@echo $(H1)Regenerate man pages$(H1END)
$(VENV_PYTHON) extras/scripts/generate_man_pages.py
regen-install-methods:
installation-docs:
@echo $(H1)Updating installation instructions in the docs$(H1END)
$(VENV_PYTHON) docs/installation/generate.py

View File

@ -399,7 +399,7 @@ The authentication mechanism to be used. Defaults to \[dq]basic\[dq].
\[dq]bearer\[dq]: Bearer HTTP Auth
For finding out all available authentication types in your system, try:
To see all available auth types on your system, including ones installed via plugins, run:
$ http \fB\,--auth-type\/\fR
@ -510,11 +510,10 @@ are shown here).
A string in the OpenSSL cipher list format. By default, the following
ciphers are used on your system:
A string in the OpenSSL cipher list format.
TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES256-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA
See `http \fB\,--help\/\fR` for the default ciphers list on you system.
.IP "\fB\,--cert\/\fR"

View File

@ -399,7 +399,7 @@ The authentication mechanism to be used. Defaults to \[dq]basic\[dq].
\[dq]bearer\[dq]: Bearer HTTP Auth
For finding out all available authentication types in your system, try:
To see all available auth types on your system, including ones installed via plugins, run:
$ http \fB\,--auth-type\/\fR
@ -509,12 +509,10 @@ are shown here).
.IP "\fB\,--ciphers\/\fR"
A string in the OpenSSL cipher list format.
A string in the OpenSSL cipher list format. By default, the following
ciphers are used on your system:
TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES256-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA
See `http \fB\,--help\/\fR` for the default ciphers list on you system.
.IP "\fB\,--cert\/\fR"

View File

@ -1,20 +1,25 @@
import os
import re
from contextlib import contextmanager
from pathlib import Path
from typing import Optional, Iterator, Iterable
# So that httpie.cli.definition can provide man-page-specific output. Must be set before importing httpie.
os.environ['HTTPIE_BUILDING_MAN_PAGES'] = '1'
import httpie
from httpie.cli.definition import options as core_options
from httpie.cli.definition import options as core_options, IS_MAN_PAGE
from httpie.cli.options import ParserSpec
from httpie.manager.cli import options as manager_options
from httpie.output.ui.rich_help import OptionsHighlighter, to_usage
from httpie.output.ui.rich_utils import render_as_string
from httpie.utils import split_iterable
# Escape certain characters so they are rendered properly on
# all terminals.
# https://man7.org/linux/man-pages/man7/groff_char.7.html
assert IS_MAN_PAGE, 'CLI definition does not understand were building man pages'
# Escape certain characters, so they are rendered properly on all terminals.
# <https://man7.org/linux/man-pages/man7/groff_char.7.html>
ESCAPE_MAP = {
'"': '\[dq]',
"'": '\[aq]',
@ -32,6 +37,7 @@ OPTION_HIGHLIGHT_RE = re.compile(
OptionsHighlighter.highlights[0]
)
class ManPageBuilder:
def __init__(self):
self.source = []
@ -125,7 +131,7 @@ def to_man_page(program_name: str, spec: ParserSpec, *, is_top_level_cmd: bool =
with builder.section('SYNOPSIS'):
# `http` and `https` are commands that can be directly used, so they can have
# have a valid usage. But `httpie` is a top-level command with multiple sub commands,
# a valid usage. But `httpie` is a top-level command with multiple sub commands,
# so for the synopsis we'll only reference the `httpie` name.
if is_top_level_cmd:
synopsis = program_name
@ -153,7 +159,7 @@ def to_man_page(program_name: str, spec: ParserSpec, *, is_top_level_cmd: bool =
if raw_arg.get('is_positional'):
# In case of positional arguments, metavar is always equal
# to the list of options (e.g `METHOD`).
metavar = None
metavar = None
builder.add_options(raw_arg['options'], metavar=metavar)
desc = builder.format_desc(raw_arg.get('description', ''))
@ -178,6 +184,5 @@ def main() -> None:
stream.write(to_man_page(program_name, spec, **config))
if __name__ == '__main__':
main()

View File

@ -1,5 +1,6 @@
from __future__ import annotations
import os
import textwrap
from argparse import FileType
@ -22,6 +23,12 @@ from httpie.plugins.builtin import BuiltinAuthPlugin
from httpie.plugins.registry import plugin_manager
from httpie.ssl_ import AVAILABLE_SSL_VERSION_ARG_MAPPING, DEFAULT_SSL_CIPHERS_STRING
# Man pages are static (built when making a release).
# We use this check to not include generated, system-specific information there (e.g., default --ciphers).
IS_MAN_PAGE = bool(os.environ.get('HTTPIE_BUILDING_MAN_PAGES'))
options = ParserSpec(
'http',
description=f'{__doc__.strip()} <https://httpie.io>',
@ -35,7 +42,6 @@ options = ParserSpec(
source_file=__file__
)
#######################################################################
# Positional arguments.
#######################################################################
@ -234,6 +240,7 @@ processing_options.add_argument(
""",
)
#######################################################################
# Output processing
#######################################################################
@ -610,6 +617,7 @@ sessions.add_argument(
""",
)
#######################################################################
# Authentication
#######################################################################
@ -630,7 +638,7 @@ def format_auth_help(auth_plugins_mapping, *, isolation_mode: bool = False):
if issubclass(auth_plugin, BuiltinAuthPlugin)
]
text += '\n'
text += 'For finding out all available authentication types in your system, try:\n\n'
text += 'To see all available auth types on your system, including ones installed via plugins, run:\n\n'
text += ' $ http --auth-type'
auth_types = '\n\n '.join(
@ -646,7 +654,7 @@ def format_auth_help(auth_plugins_mapping, *, isolation_mode: bool = False):
''
if not plugin.description
else '\n '
+ ('\n '.join(textwrap.wrap(plugin.description)))
+ ('\n '.join(textwrap.wrap(plugin.description)))
),
)
for plugin in auth_plugins
@ -826,23 +834,36 @@ ssl.add_argument(
""",
)
CIPHERS_CURRENT_DEFAULTS = (
"""
See `http --help` for the default ciphers list on you system.
"""
if IS_MAN_PAGE else
f"""
By default, the following ciphers are used on your system:
{DEFAULT_SSL_CIPHERS_STRING}
"""
)
ssl.add_argument(
'--ciphers',
short_help='A string in the OpenSSL cipher list format.',
help=f"""
A string in the OpenSSL cipher list format. By default, the following
ciphers are used on your system:
A string in the OpenSSL cipher list format.
{DEFAULT_SSL_CIPHERS_STRING}
{CIPHERS_CURRENT_DEFAULTS}
""",
"""
)
ssl.add_argument(
'--cert',
default=None,
type=readable_file_arg,
short_help='Specifys a local cert to use as client side SSL certificate.',
short_help='Specifies a local cert to use as the client-side SSL certificate.',
help="""
You can specify a local cert to use as client side SSL certificate.
This file may either contain both private key and certificate or you may

View File

@ -4,23 +4,22 @@ import subprocess
import os
from httpie.context import Environment
MAN_COMMAND = 'man'
NO_MAN_PAGES = os.getenv('HTTPIE_NO_MAN_PAGES', False)
# On some systems, HTTP(n) might exist but we are only
# interested in HTTP(1).
#
# For more information on man page sections: https://unix.stackexchange.com/a/138643
# On some systems, HTTP(n) might exist, but we are only interested in HTTP(1).
# For more information on man page sections: <https://unix.stackexchange.com/a/138643>
MAN_PAGE_SECTION = '1'
def is_available(program: str) -> bool:
"""Check whether HTTPie's man pages are available in this system."""
"""
Check whether `program`'s man pages are available on this system.
"""
if NO_MAN_PAGES or os.system == 'nt':
return False
try:
process = subprocess.run(
[MAN_COMMAND, MAN_PAGE_SECTION, program],
@ -29,7 +28,7 @@ def is_available(program: str) -> bool:
stderr=subprocess.DEVNULL
)
except Exception:
# There might be some errors outside of the process, e.g
# There might be some errors outside the process, e.g
# a permission error to execute something that is not an
# executable.
return False
@ -38,8 +37,10 @@ def is_available(program: str) -> bool:
def display_for(env: Environment, program: str) -> None:
"""Display the man page for the given command (http/https)."""
"""
Open the system man page for the given command (http/https/httpie).
"""
subprocess.run(
[MAN_COMMAND, MAN_PAGE_SECTION, program],
stdout=env.stdout,