From b6306b2bcf256ad75afed8f31a8d29f1df033135 Mon Sep 17 00:00:00 2001 From: Nate Prewitt Date: Wed, 16 Sep 2020 09:07:31 -0700 Subject: [PATCH] Remove docutils dependency --- .../feature-dependency-56071.json | 5 + botocore/docs/bcdoc/docevents.py | 103 --- botocore/docs/bcdoc/textwriter.py | 799 ------------------ requirements.txt | 1 - setup.cfg | 1 - setup.py | 1 - 6 files changed, 5 insertions(+), 905 deletions(-) create mode 100644 .changes/next-release/feature-dependency-56071.json delete mode 100644 botocore/docs/bcdoc/docevents.py delete mode 100644 botocore/docs/bcdoc/textwriter.py diff --git a/.changes/next-release/feature-dependency-56071.json b/.changes/next-release/feature-dependency-56071.json new file mode 100644 index 0000000000..1eb0124a82 --- /dev/null +++ b/.changes/next-release/feature-dependency-56071.json @@ -0,0 +1,5 @@ +{ + "type": "feature", + "category": "dependency", + "description": "botocore has removed docutils as a required dependency" +} diff --git a/botocore/docs/bcdoc/docevents.py b/botocore/docs/bcdoc/docevents.py deleted file mode 100644 index f5c6c84938..0000000000 --- a/botocore/docs/bcdoc/docevents.py +++ /dev/null @@ -1,103 +0,0 @@ -# Copyright 2012-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You -# may not use this file except in compliance with the License. A copy of -# the License is located at -# -# http://aws.amazon.com/apache2.0/ -# -# or in the "license" file accompanying this file. This file is -# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -# ANY KIND, either express or implied. See the License for the specific -# language governing permissions and limitations under the License. - - -DOC_EVENTS = { - 'doc-breadcrumbs': '.%s', - 'doc-title': '.%s', - 'doc-description': '.%s', - 'doc-synopsis-start': '.%s', - 'doc-synopsis-option': '.%s.%s', - 'doc-synopsis-end': '.%s', - 'doc-options-start': '.%s', - 'doc-option': '.%s.%s', - 'doc-option-example': '.%s.%s', - 'doc-options-end': '.%s', - 'doc-examples': '.%s', - 'doc-output': '.%s', - 'doc-subitems-start': '.%s', - 'doc-subitem': '.%s.%s', - 'doc-subitems-end': '.%s', - 'doc-relateditems-start': '.%s', - 'doc-relateditem': '.%s.%s', - 'doc-relateditems-end': '.%s' - } - - -def generate_events(session, help_command): - # Now generate the documentation events - session.emit('doc-breadcrumbs.%s' % help_command.event_class, - help_command=help_command) - session.emit('doc-title.%s' % help_command.event_class, - help_command=help_command) - session.emit('doc-description.%s' % help_command.event_class, - help_command=help_command) - session.emit('doc-synopsis-start.%s' % help_command.event_class, - help_command=help_command) - if help_command.arg_table: - for arg_name in help_command.arg_table: - # An argument can set an '_UNDOCUMENTED' attribute - # to True to indicate a parameter that exists - # but shouldn't be documented. This can be used - # for backwards compatibility of deprecated arguments. - if getattr(help_command.arg_table[arg_name], - '_UNDOCUMENTED', False): - continue - session.emit( - 'doc-synopsis-option.%s.%s' % (help_command.event_class, - arg_name), - arg_name=arg_name, help_command=help_command) - session.emit('doc-synopsis-end.%s' % help_command.event_class, - help_command=help_command) - session.emit('doc-options-start.%s' % help_command.event_class, - help_command=help_command) - if help_command.arg_table: - for arg_name in help_command.arg_table: - if getattr(help_command.arg_table[arg_name], - '_UNDOCUMENTED', False): - continue - session.emit('doc-option.%s.%s' % (help_command.event_class, - arg_name), - arg_name=arg_name, help_command=help_command) - session.emit('doc-option-example.%s.%s' % - (help_command.event_class, arg_name), - arg_name=arg_name, help_command=help_command) - session.emit('doc-options-end.%s' % help_command.event_class, - help_command=help_command) - session.emit('doc-subitems-start.%s' % help_command.event_class, - help_command=help_command) - if help_command.command_table: - for command_name in sorted(help_command.command_table.keys()): - if hasattr(help_command.command_table[command_name], - '_UNDOCUMENTED'): - continue - session.emit('doc-subitem.%s.%s' - % (help_command.event_class, command_name), - command_name=command_name, - help_command=help_command) - session.emit('doc-subitems-end.%s' % help_command.event_class, - help_command=help_command) - session.emit('doc-examples.%s' % help_command.event_class, - help_command=help_command) - session.emit('doc-output.%s' % help_command.event_class, - help_command=help_command) - session.emit('doc-relateditems-start.%s' % help_command.event_class, - help_command=help_command) - if help_command.related_items: - for related_item in sorted(help_command.related_items): - session.emit('doc-relateditem.%s.%s' - % (help_command.event_class, related_item), - help_command=help_command, - related_item=related_item) - session.emit('doc-relateditems-end.%s' % help_command.event_class, - help_command=help_command) diff --git a/botocore/docs/bcdoc/textwriter.py b/botocore/docs/bcdoc/textwriter.py deleted file mode 100644 index 6fc171b9b4..0000000000 --- a/botocore/docs/bcdoc/textwriter.py +++ /dev/null @@ -1,799 +0,0 @@ -# -*- coding: utf-8 -*- -""" - - Custom docutils writer for plain text. - Based heavily on the Sphinx text writer. See copyright below. - - :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. - :license: BSD, see LICENSE for details. - -""" -import os -import re -import textwrap - -from docutils import nodes, writers - - -class TextWrapper(textwrap.TextWrapper): - """Custom subclass that uses a different word separator regex.""" - - wordsep_re = re.compile( - r'(\s+|' # any whitespace - r'(?<=\s)(?::[a-z-]+:)?`\S+|' # interpreted text start - r'[^\s\w]*\w+[a-zA-Z]-(?=\w+[a-zA-Z])|' # hyphenated words - r'(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w))') # em-dash - - -MAXWIDTH = 70 -STDINDENT = 3 - - -def my_wrap(text, width=MAXWIDTH, **kwargs): - w = TextWrapper(width=width, **kwargs) - return w.wrap(text) - - -class TextWriter(writers.Writer): - supported = ('text',) - settings_spec = ('No options here.', '', ()) - settings_defaults = {} - - output = None - - def __init__(self): - writers.Writer.__init__(self) - - def translate(self): - visitor = TextTranslator(self.document) - self.document.walkabout(visitor) - self.output = visitor.body - - -class TextTranslator(nodes.NodeVisitor): - sectionchars = '*=-~"+`' - - def __init__(self, document): - nodes.NodeVisitor.__init__(self, document) - - self.nl = os.linesep - self.states = [[]] - self.stateindent = [0] - self.list_counter = [] - self.sectionlevel = 0 - self.table = None - - def add_text(self, text): - self.states[-1].append((-1, text)) - - def new_state(self, indent=STDINDENT): - self.states.append([]) - self.stateindent.append(indent) - - def end_state(self, wrap=True, end=[''], first=None): - content = self.states.pop() - maxindent = sum(self.stateindent) - indent = self.stateindent.pop() - result = [] - toformat = [] - - def do_format(): - if not toformat: - return - if wrap: - res = my_wrap(''.join(toformat), width=MAXWIDTH-maxindent) - else: - res = ''.join(toformat).splitlines() - if end: - res += end - result.append((indent, res)) - for itemindent, item in content: - if itemindent == -1: - toformat.append(item) - else: - do_format() - result.append((indent + itemindent, item)) - toformat = [] - do_format() - if first is not None and result: - itemindent, item = result[0] - if item: - result.insert(0, (itemindent - indent, [first + item[0]])) - result[1] = (itemindent, item[1:]) - self.states[-1].extend(result) - - def visit_document(self, node): - self.new_state(0) - - def depart_document(self, node): - self.end_state() - self.body = self.nl.join(line and (' '*indent + line) - for indent, lines in self.states[0] - for line in lines) - # XXX header/footer? - - def visit_highlightlang(self, node): - raise nodes.SkipNode - - def visit_section(self, node): - self._title_char = self.sectionchars[self.sectionlevel] - self.sectionlevel += 1 - - def depart_section(self, node): - self.sectionlevel -= 1 - - def visit_topic(self, node): - self.new_state(0) - - def depart_topic(self, node): - self.end_state() - - visit_sidebar = visit_topic - depart_sidebar = depart_topic - - def visit_rubric(self, node): - self.new_state(0) - self.add_text('-[ ') - - def depart_rubric(self, node): - self.add_text(' ]-') - self.end_state() - - def visit_compound(self, node): - pass - - def depart_compound(self, node): - pass - - def visit_glossary(self, node): - pass - - def depart_glossary(self, node): - pass - - def visit_title(self, node): - if isinstance(node.parent, nodes.Admonition): - self.add_text(node.astext()+': ') - raise nodes.SkipNode - self.new_state(0) - - def depart_title(self, node): - if isinstance(node.parent, nodes.section): - char = self._title_char - else: - char = '^' - text = ''.join(x[1] for x in self.states.pop() if x[0] == -1) - self.stateindent.pop() - self.states[-1].append((0, ['', text, '%s' % (char * len(text)), ''])) - - def visit_subtitle(self, node): - pass - - def depart_subtitle(self, node): - pass - - def visit_attribution(self, node): - self.add_text('-- ') - - def depart_attribution(self, node): - pass - - def visit_desc(self, node): - pass - - def depart_desc(self, node): - pass - - def visit_desc_signature(self, node): - self.new_state(0) - if node.parent['objtype'] in ('class', 'exception'): - self.add_text('%s ' % node.parent['objtype']) - - def depart_desc_signature(self, node): - # XXX: wrap signatures in a way that makes sense - self.end_state(wrap=False, end=None) - - def visit_desc_name(self, node): - pass - - def depart_desc_name(self, node): - pass - - def visit_desc_addname(self, node): - pass - - def depart_desc_addname(self, node): - pass - - def visit_desc_type(self, node): - pass - - def depart_desc_type(self, node): - pass - - def visit_desc_returns(self, node): - self.add_text(' -> ') - - def depart_desc_returns(self, node): - pass - - def visit_desc_parameterlist(self, node): - self.add_text('(') - self.first_param = 1 - - def depart_desc_parameterlist(self, node): - self.add_text(')') - - def visit_desc_parameter(self, node): - if not self.first_param: - self.add_text(', ') - else: - self.first_param = 0 - self.add_text(node.astext()) - raise nodes.SkipNode - - def visit_desc_optional(self, node): - self.add_text('[') - - def depart_desc_optional(self, node): - self.add_text(']') - - def visit_desc_annotation(self, node): - pass - - def depart_desc_annotation(self, node): - pass - - def visit_refcount(self, node): - pass - - def depart_refcount(self, node): - pass - - def visit_desc_content(self, node): - self.new_state() - self.add_text(self.nl) - - def depart_desc_content(self, node): - self.end_state() - - def visit_figure(self, node): - self.new_state() - - def depart_figure(self, node): - self.end_state() - - def visit_caption(self, node): - pass - - def depart_caption(self, node): - pass - - def visit_productionlist(self, node): - self.new_state() - names = [] - for production in node: - names.append(production['tokenname']) - maxlen = max(len(name) for name in names) - for production in node: - if production['tokenname']: - self.add_text(production['tokenname'].ljust(maxlen) + ' ::=') - lastname = production['tokenname'] - else: - self.add_text('%s ' % (' '*len(lastname))) - self.add_text(production.astext() + self.nl) - self.end_state(wrap=False) - raise nodes.SkipNode - - def visit_seealso(self, node): - self.new_state() - - def depart_seealso(self, node): - self.end_state(first='') - - def visit_footnote(self, node): - self._footnote = node.children[0].astext().strip() - self.new_state(len(self._footnote) + 3) - - def depart_footnote(self, node): - self.end_state(first='[%s] ' % self._footnote) - - def visit_citation(self, node): - if len(node) and isinstance(node[0], nodes.label): - self._citlabel = node[0].astext() - else: - self._citlabel = '' - self.new_state(len(self._citlabel) + 3) - - def depart_citation(self, node): - self.end_state(first='[%s] ' % self._citlabel) - - def visit_label(self, node): - raise nodes.SkipNode - - # XXX: option list could use some better styling - - def visit_option_list(self, node): - pass - - def depart_option_list(self, node): - pass - - def visit_option_list_item(self, node): - self.new_state(0) - - def depart_option_list_item(self, node): - self.end_state() - - def visit_option_group(self, node): - self._firstoption = True - - def depart_option_group(self, node): - self.add_text(' ') - - def visit_option(self, node): - if self._firstoption: - self._firstoption = False - else: - self.add_text(', ') - - def depart_option(self, node): - pass - - def visit_option_string(self, node): - pass - - def depart_option_string(self, node): - pass - - def visit_option_argument(self, node): - self.add_text(node['delimiter']) - - def depart_option_argument(self, node): - pass - - def visit_description(self, node): - pass - - def depart_description(self, node): - pass - - def visit_tabular_col_spec(self, node): - raise nodes.SkipNode - - def visit_colspec(self, node): - self.table[0].append(node['colwidth']) - raise nodes.SkipNode - - def visit_tgroup(self, node): - pass - - def depart_tgroup(self, node): - pass - - def visit_thead(self, node): - pass - - def depart_thead(self, node): - pass - - def visit_tbody(self, node): - self.table.append('sep') - - def depart_tbody(self, node): - pass - - def visit_row(self, node): - self.table.append([]) - - def depart_row(self, node): - pass - - def visit_entry(self, node): - if 'morerows' in node or 'morecols' in node: - raise NotImplementedError('Column or row spanning cells are ' - 'not implemented.') - self.new_state(0) - - def depart_entry(self, node): - text = self.nl.join(self.nl.join(x[1]) for x in self.states.pop()) - self.stateindent.pop() - self.table[-1].append(text) - - def visit_table(self, node): - if self.table: - raise NotImplementedError('Nested tables are not supported.') - self.new_state(0) - self.table = [[]] - - def depart_table(self, node): - lines = self.table[1:] - fmted_rows = [] - colwidths = self.table[0] - realwidths = colwidths[:] - separator = 0 - # don't allow paragraphs in table cells for now - for line in lines: - if line == 'sep': - separator = len(fmted_rows) - else: - cells = [] - for i, cell in enumerate(line): - par = my_wrap(cell, width=colwidths[i]) - if par: - maxwidth = max(map(len, par)) - else: - maxwidth = 0 - realwidths[i] = max(realwidths[i], maxwidth) - cells.append(par) - fmted_rows.append(cells) - - def writesep(char='-'): - out = ['+'] - for width in realwidths: - out.append(char * (width+2)) - out.append('+') - self.add_text(''.join(out) + self.nl) - - def writerow(row): - lines = zip(*row) - for line in lines: - out = ['|'] - for i, cell in enumerate(line): - if cell: - out.append(' ' + cell.ljust(realwidths[i]+1)) - else: - out.append(' ' * (realwidths[i] + 2)) - out.append('|') - self.add_text(''.join(out) + self.nl) - - for i, row in enumerate(fmted_rows): - if separator and i == separator: - writesep('=') - else: - writesep('-') - writerow(row) - writesep('-') - self.table = None - self.end_state(wrap=False) - - def visit_acks(self, node): - self.new_state(0) - self.add_text( - ', '.join(n.astext() for n in node.children[0].children) + '.') - self.end_state() - raise nodes.SkipNode - - def visit_image(self, node): - if 'alt' in node.attributes: - self.add_text(_('[image: %s]') % node['alt']) - self.add_text(_('[image]')) - raise nodes.SkipNode - - def visit_transition(self, node): - indent = sum(self.stateindent) - self.new_state(0) - self.add_text('=' * (MAXWIDTH - indent)) - self.end_state() - raise nodes.SkipNode - - def visit_bullet_list(self, node): - self.list_counter.append(-1) - - def depart_bullet_list(self, node): - self.list_counter.pop() - - def visit_enumerated_list(self, node): - self.list_counter.append(0) - - def depart_enumerated_list(self, node): - self.list_counter.pop() - - def visit_definition_list(self, node): - self.list_counter.append(-2) - - def depart_definition_list(self, node): - self.list_counter.pop() - - def visit_list_item(self, node): - if self.list_counter[-1] == -1: - # bullet list - self.new_state(2) - elif self.list_counter[-1] == -2: - # definition list - pass - else: - # enumerated list - self.list_counter[-1] += 1 - self.new_state(len(str(self.list_counter[-1])) + 2) - - def depart_list_item(self, node): - if self.list_counter[-1] == -1: - self.end_state(first='* ', end=None) - elif self.list_counter[-1] == -2: - pass - else: - self.end_state(first='%s. ' % self.list_counter[-1], end=None) - - def visit_definition_list_item(self, node): - self._li_has_classifier = len(node) >= 2 and \ - isinstance(node[1], nodes.classifier) - - def depart_definition_list_item(self, node): - pass - - def visit_term(self, node): - self.new_state(0) - - def depart_term(self, node): - if not self._li_has_classifier: - self.end_state(end=None) - - def visit_termsep(self, node): - self.add_text(', ') - raise nodes.SkipNode - - def visit_classifier(self, node): - self.add_text(' : ') - - def depart_classifier(self, node): - self.end_state(end=None) - - def visit_definition(self, node): - self.new_state() - - def depart_definition(self, node): - self.end_state() - - def visit_field_list(self, node): - pass - - def depart_field_list(self, node): - pass - - def visit_field(self, node): - pass - - def depart_field(self, node): - pass - - def visit_field_name(self, node): - self.new_state(0) - - def depart_field_name(self, node): - self.add_text(':') - self.end_state(end=None) - - def visit_field_body(self, node): - self.new_state() - - def depart_field_body(self, node): - self.end_state() - - def visit_centered(self, node): - pass - - def depart_centered(self, node): - pass - - def visit_hlist(self, node): - pass - - def depart_hlist(self, node): - pass - - def visit_hlistcol(self, node): - pass - - def depart_hlistcol(self, node): - pass - - def visit_admonition(self, node): - self.new_state(0) - - def depart_admonition(self, node): - self.end_state() - - def visit_versionmodified(self, node): - self.new_state(0) - - def depart_versionmodified(self, node): - self.end_state() - - def visit_literal_block(self, node): - self.new_state() - - def depart_literal_block(self, node): - self.end_state(wrap=False) - - def visit_doctest_block(self, node): - self.new_state(0) - - def depart_doctest_block(self, node): - self.end_state(wrap=False) - - def visit_line_block(self, node): - self.new_state(0) - - def depart_line_block(self, node): - self.end_state(wrap=False) - - def visit_line(self, node): - pass - - def depart_line(self, node): - pass - - def visit_block_quote(self, node): - self.new_state() - - def depart_block_quote(self, node): - self.end_state() - - def visit_compact_paragraph(self, node): - pass - - def depart_compact_paragraph(self, node): - pass - - def visit_paragraph(self, node): - self.new_state(0) - - def depart_paragraph(self, node): - self.end_state() - - def visit_target(self, node): - raise nodes.SkipNode - - def visit_index(self, node): - raise nodes.SkipNode - - def visit_substitution_definition(self, node): - raise nodes.SkipNode - - def visit_pending_xref(self, node): - pass - - def depart_pending_xref(self, node): - pass - - def visit_reference(self, node): - pass - - def depart_reference(self, node): - pass - - def visit_download_reference(self, node): - pass - - def depart_download_reference(self, node): - pass - - def visit_emphasis(self, node): - self.add_text('*') - - def depart_emphasis(self, node): - self.add_text('*') - - def visit_literal_emphasis(self, node): - self.add_text('*') - - def depart_literal_emphasis(self, node): - self.add_text('*') - - def visit_strong(self, node): - self.add_text('**') - - def depart_strong(self, node): - self.add_text('**') - - def visit_abbreviation(self, node): - self.add_text('') - - def depart_abbreviation(self, node): - if node.hasattr('explanation'): - self.add_text(' (%s)' % node['explanation']) - - def visit_title_reference(self, node): - self.add_text('*') - - def depart_title_reference(self, node): - self.add_text('*') - - def visit_literal(self, node): - self.add_text('"') - - def depart_literal(self, node): - self.add_text('"') - - def visit_subscript(self, node): - self.add_text('_') - - def depart_subscript(self, node): - pass - - def visit_superscript(self, node): - self.add_text('^') - - def depart_superscript(self, node): - pass - - def visit_footnote_reference(self, node): - self.add_text('[%s]' % node.astext()) - raise nodes.SkipNode - - def visit_citation_reference(self, node): - self.add_text('[%s]' % node.astext()) - raise nodes.SkipNode - - def visit_Text(self, node): - self.add_text(node.astext()) - - def depart_Text(self, node): - pass - - def visit_generated(self, node): - pass - - def depart_generated(self, node): - pass - - def visit_inline(self, node): - pass - - def depart_inline(self, node): - pass - - def visit_problematic(self, node): - self.add_text('>>') - - def depart_problematic(self, node): - self.add_text('<<') - - def visit_system_message(self, node): - self.new_state(0) - self.add_text('' % node.astext()) - self.end_state() - raise nodes.SkipNode - - def visit_comment(self, node): - raise nodes.SkipNode - - def visit_meta(self, node): - # only valid for HTML - raise nodes.SkipNode - - def visit_raw(self, node): - if 'text' in node.get('format', '').split(): - self.body.append(node.astext()) - raise nodes.SkipNode - - def _visit_admonition(self, node): - self.new_state(2) - - def _make_depart_admonition(name): - def depart_admonition(self, node): - self.end_state(first=name.capitalize() + ': ') - return depart_admonition - - visit_attention = _visit_admonition - depart_attention = _make_depart_admonition('attention') - visit_caution = _visit_admonition - depart_caution = _make_depart_admonition('caution') - visit_danger = _visit_admonition - depart_danger = _make_depart_admonition('danger') - visit_error = _visit_admonition - depart_error = _make_depart_admonition('error') - visit_hint = _visit_admonition - depart_hint = _make_depart_admonition('hint') - visit_important = _visit_admonition - depart_important = _make_depart_admonition('important') - visit_note = _visit_admonition - depart_note = _make_depart_admonition('note') - visit_tip = _visit_admonition - depart_tip = _make_depart_admonition('tip') - visit_warning = _visit_admonition - depart_warning = _make_depart_admonition('warning') - - def unknown_visit(self, node): - raise NotImplementedError('Unknown node: ' + node.__class__.__name__) diff --git a/requirements.txt b/requirements.txt index 0ad64b08aa..d5296a83aa 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,6 +2,5 @@ tox>=2.5.0,<3.0.0 nose==1.3.7 mock==1.3.0 wheel==0.24.0 -docutils>=0.10,<0.16 behave==1.2.5 jsonschema==2.5.1 diff --git a/setup.cfg b/setup.cfg index d4c8f2a786..93bacfab36 100644 --- a/setup.cfg +++ b/setup.cfg @@ -5,6 +5,5 @@ universal = 1 requires-dist = python-dateutil>=2.1,<3.0.0 jmespath>=0.7.1,<1.0.0 - docutils>=0.10,<0.16 urllib3>=1.20,<1.25.8; python_version=='3.4' urllib3>=1.20,<1.26; python_version!='3.4' diff --git a/setup.py b/setup.py index edc3578970..685e8e80d5 100644 --- a/setup.py +++ b/setup.py @@ -25,7 +25,6 @@ def find_version(*file_paths): requires = [ 'jmespath>=0.7.1,<1.0.0', - 'docutils>=0.10,<0.16', 'python-dateutil>=2.1,<3.0.0', ]