diff --git a/sphinxcontrib/confluencebuilder/builder.py b/sphinxcontrib/confluencebuilder/builder.py index 50e5f10c..157782d3 100644 --- a/sphinxcontrib/confluencebuilder/builder.py +++ b/sphinxcontrib/confluencebuilder/builder.py @@ -134,8 +134,7 @@ def init(self): old_url = self.config.confluence_server_url new_url = ConfluenceUtil.normalize_base_url(old_url) if old_url != new_url: - self.warn('normalizing confluence url from ' - '{} to {} '.format(old_url, new_url)) + self.warn(f'normalizing confluence url from {old_url} to {new_url}') self.config.confluence_server_url = new_url # detect if Confluence Cloud if using the Atlassian domain @@ -611,7 +610,7 @@ def publish_asset(self, key, docname, output, type_, hash_): self.state.register_upload_id(docname, page_id) else: self.warn('cannot publish asset since publishing ' - 'point cannot be found ({}): {}'.format(key, docname)) + f'point cannot be found ({key}): {docname}') return attachment_id = None @@ -1166,9 +1165,9 @@ def _parse_doctree_title(self, docname, doctree): doctitle = f'autogen-{docname}' if self.publish: self.warn('document will be published using an ' - 'generated title value: {}'.format(docname)) + f'generated title value: {docname}') elif self.publish: self.warn('document will not be published since it ' - 'has no title: {}'.format(docname)) + f'has no title: {docname}') return doctitle diff --git a/sphinxcontrib/confluencebuilder/cmd/report.py b/sphinxcontrib/confluencebuilder/cmd/report.py index a19a32d7..952c52ec 100644 --- a/sphinxcontrib/confluencebuilder/cmd/report.py +++ b/sphinxcontrib/confluencebuilder/cmd/report.py @@ -182,9 +182,9 @@ def report_main(args_parser): for o in root.findall('buildNumber'): info += ' build: ' + o.text + '\n' else: - logger.error('bad response from server ({})'.format( - rsp.status_code)) - info += f' fetched: error ({rsp.status_code})\n' + code = rsp.status_code + logger.error(f'bad response from server ({code})') + info += f' fetched: error ({code})\n' rv = 1 except Exception: # noqa: BLE001 sys.stdout.flush() diff --git a/sphinxcontrib/confluencebuilder/intersphinx.py b/sphinxcontrib/confluencebuilder/intersphinx.py index fc85a915..e5300b29 100644 --- a/sphinxcontrib/confluencebuilder/intersphinx.py +++ b/sphinxcontrib/confluencebuilder/intersphinx.py @@ -34,13 +34,14 @@ def escape(string): inventory_db = builder.out_dir / INVENTORY_FILENAME with inventory_db.open('wb') as f: # header - f.write(( - '# Sphinx inventory version 2\n' - '# Project: {}\n' - '# Version: {}\n' - '# The remainder of this file is compressed using zlib.\n'.format( - escape(builder.env.config.project), - escape(builder.env.config.version))).encode()) + f.write( + ( + '# Sphinx inventory version 2\n' + f'# Project: {escape(builder.env.config.project)}\n' + f'# Version: {escape(builder.env.config.version)}\n' + '# The remainder of this file is compressed using zlib.\n' + ).encode() + ) # contents compressor = zlib.compressobj(9) @@ -74,8 +75,7 @@ def escape(string): uri += '#' + anchor if dispname == name: dispname = '-' - entry = ('%s %s:%s %s %s %s\n' % - (name, domainname, typ, prio, uri, dispname)) + entry = f'{name} {domainname}:{typ} {prio} {uri} {dispname}\n' logger.verbose('(intersphinx) ' + entry.strip()) f.write(compressor.compress(entry.encode('utf-8'))) diff --git a/sphinxcontrib/confluencebuilder/rest.py b/sphinxcontrib/confluencebuilder/rest.py index 1b529299..9751c454 100644 --- a/sphinxcontrib/confluencebuilder/rest.py +++ b/sphinxcontrib/confluencebuilder/rest.py @@ -86,7 +86,7 @@ def _wrapper(self, *args, **kwargs): if self.config.confluence_publish_delay: delay = self.config.confluence_publish_delay logger.verbose('user-set api delay set; ' - 'waiting {} seconds...'.format(math.ceil(delay))) + f'waiting {math.ceil(delay)} seconds...') time.sleep(delay) # if confluence asked us to wait so many seconds before a next @@ -94,7 +94,7 @@ def _wrapper(self, *args, **kwargs): if self.next_delay: delay = self.next_delay logger.verbose('rate-limit header detected; ' - 'waiting {} seconds...'.format(math.ceil(delay))) + f'waiting {math.ceil(delay)} seconds...') time.sleep(delay) self.next_delay = None @@ -128,7 +128,7 @@ def _wrapper(self, *args, **kwargs): # wait the calculated delay before retrying again logger.warn('rate-limit response detected; ' - 'waiting {} seconds...'.format(math.ceil(delay))) + f'waiting {math.ceil(delay)} seconds...') time.sleep(delay) self.last_retry = delay attempt += 1 @@ -373,8 +373,8 @@ def _process_request(self, method, path, *args, **kwargs): # user once if delay >= 60 and not self._reported_large_delay: logger.warn('(warning) site has reported a long ' - 'rate-limit delay ({} seconds)'.format( - math.ceil(delay))) + 'rate-limit delay ' + f'({math.ceil(delay)} seconds)') self._reported_large_delay = True # check if Confluence reports a `Deprecation` header in the response; diff --git a/sphinxcontrib/confluencebuilder/singlebuilder.py b/sphinxcontrib/confluencebuilder/singlebuilder.py index b5b886d2..fa051537 100644 --- a/sphinxcontrib/confluencebuilder/singlebuilder.py +++ b/sphinxcontrib/confluencebuilder/singlebuilder.py @@ -59,8 +59,7 @@ def get_relative_uri(self, from_, to, typ=None): def get_target_uri(self, docname, typ=None): if docname in self.env.all_docs: - return '{}{}#{}'.format( - self.config.root_doc, self.link_suffix, docname) + return f'{self.config.root_doc}{self.link_suffix}#{docname}' else: return self.link_transform(docname) diff --git a/sphinxcontrib/confluencebuilder/state.py b/sphinxcontrib/confluencebuilder/state.py index 5532d1af..979180bb 100644 --- a/sphinxcontrib/confluencebuilder/state.py +++ b/sphinxcontrib/confluencebuilder/state.py @@ -105,9 +105,9 @@ def register_title(docname, title, config): offset = 2 while title.lower() in ConfluenceState.title2doc: if offset == 2: + docname2 = ConfluenceState.title2doc[title.lower()] logger.warn('title conflict detected with ' - "'{}' and '{}'".format( - ConfluenceState.title2doc[title.lower()], docname)) + f"'{docname2}' and '{docname}'") tail = f' ({offset}){base_tail}' if len(base_title) + len(tail) > try_max: @@ -227,8 +227,8 @@ def _format_postfix(postfix, docname, config): ) except KeyError: raise ConfluenceConfigError( - "Configured confluence_publish_prefix '{postfix}' has an " - "unknown template replacement.".format(postfix=postfix)) + f"Configured confluence_publish_prefix '{postfix}' has an " + "unknown template replacement.") return postfix @staticmethod diff --git a/sphinxcontrib/confluencebuilder/storage/translator.py b/sphinxcontrib/confluencebuilder/storage/translator.py index 7a42380f..50f2ddf0 100644 --- a/sphinxcontrib/confluencebuilder/storage/translator.py +++ b/sphinxcontrib/confluencebuilder/storage/translator.py @@ -101,9 +101,9 @@ def get_secnumber(self, node): if self.builder.name == 'singleconfluence': docname = self._docnames[-1] raw_anchor = node.parent['ids'][0] - anchorname = '{}/#{}'.format(docname, node.parent['ids'][0]) + anchorname = f'{docname}/#{raw_anchor}' if anchorname not in self.builder.secnumbers: - anchorname = '%s/' % raw_anchor + anchorname = f'{raw_anchor}/' else: anchorname = '#' + node.parent['ids'][0] if anchorname not in self.builder.secnumbers: @@ -171,7 +171,7 @@ def visit_start_of_file(self, node): # an anchor point with the name matching the title (which allows the # fallback link to jump to the desired point in a document). if self.builder.name == 'singleconfluence': - doc_anchorname = '%s/' % node['docname'] + doc_anchorname = node['docname'] + '/' doc_target = self.state.target(doc_anchorname) if not doc_target: doc_id = node['docname'] @@ -276,7 +276,8 @@ def visit_paragraph(self, node): # on the paragraph since the v2 editor does not permit nesting # block elements for indentation if self.v2 and self._indent_level > 0: - style += 'margin-left: {}px;'.format(INDENT * self._indent_level) + offset = INDENT * self._indent_level + style += f'margin-left: {offset}px;' # MyST-Parser will inject text-align hints in the node's classes # attribute; if set, attempt to apply the style @@ -430,14 +431,12 @@ def visit_enumerated_list(self, node): elif node['enumtype'] == 'arabic': list_style_type = 'decimal' else: - self.warn( - 'unknown enumerated list type: {}'.format(node['enumtype'])) + self.warn('unknown enumerated list type: ' + node['enumtype']) if list_style_type: if 'style' not in attribs: attribs['style'] = '' - attribs['style'] = '{}list-style-type: {};'.format( - attribs['style'], list_style_type) + attribs['style'] += f'list-style-type: {list_style_type};' self.body.append(self._start_tag(node, 'ol', suffix=self.nl, **attribs)) self.context.append(self._end_tag(node)) @@ -513,9 +512,9 @@ def visit_term(self, node): self.body.append(self.context.pop()) # dt/p if self.v2: + offset = INDENT * self._indent_level self.body.append(self._start_tag(node, 'p', - **{'style': 'margin-left: {}px;'.format( - INDENT * self._indent_level)})) + **{'style': f'margin-left: {offset}px;'})) self.context.append(self._end_tag(node)) if 'ids' in node: @@ -1133,8 +1132,9 @@ def visit_tgroup(self, node): # configuring it explicitly may break the editor's page # width configuration attribs = {} - if colspec['colwidth'] != 100 or not self.v2: - attribs['style'] = 'width: {}%'.format(colspec['colwidth']) + colwidth = colspec['colwidth'] + if colwidth != 100 or not self.v2: + attribs['style'] = f'width: {colwidth}%' self.body.append(self._start_tag( node, 'col', empty=True, **attribs)) @@ -1296,7 +1296,7 @@ def _visit_reference_intern_id(self, node): docname = self._docnames[-1] anchorname = f'{docname}/#{raw_anchor}' if anchorname not in self.builder.secnumbers: - anchorname = '%s/' % raw_anchor + anchorname = f'{raw_anchor}/' else: anchorname = f'{self.docname}#{raw_anchor}' @@ -1346,7 +1346,7 @@ def _visit_reference_intern_uri(self, node): doctitle = self.state.title(docname) if not doctitle: self.warn('unable to build link to document due to ' - 'missing title (in {}): {}'.format(self.docname, docname)) + f'missing title (in {self.docname}): {docname}') # build a broken link self.body.append(self._start_tag(node, 'a', **{'href': '#'})) @@ -1695,8 +1695,7 @@ def visit_caption(self, node): alignment = self._fetch_alignment(node) if alignment and alignment != 'left': - attribs['style'] = '{}text-align: {};'.format( - attribs['style'], alignment) + attribs['style'] += f'text-align: {alignment};' self.body.append(self._start_tag(node, 'p', **attribs)) self.add_fignumber(node.parent) @@ -1730,8 +1729,9 @@ def _visit_image(self, node, opts): # offset vertical image to align with paragraph if not self.v2 and node.get('from_math') and node.get('math_depth'): math_depth = node['math_depth'] + offset = -1 * math_depth self.body.append(self._start_tag(node, 'span', - **{'style': 'vertical-align: {}px'.format(-1 * math_depth)})) + **{'style': f'vertical-align: {offset}px'})) self.context.append(self._end_tag(node)) node.math_number = None @@ -1888,8 +1888,8 @@ def depart_legend(self, node): # ------------------ def visit_download_reference(self, node): - uri = node['reftarget'] - uri = self.encode(uri) + reftarget = node['reftarget'] + uri = self.encode(reftarget) if uri.find('://') != -1: self.body.append(self._start_tag(node, 'strong')) @@ -1915,8 +1915,7 @@ def visit_download_reference(self, node): node, asset_docname, standalone=True) if not file_key: - self.warn('unable to find download: ' '{}'.format( - node['reftarget'])) + self.warn(f'unable to find download: {reftarget}') raise nodes.SkipNode hosting_doctitle = self.state.title(hosting_docname) @@ -2065,7 +2064,8 @@ def visit_productionlist(self, node): self.body.append(f'{formatted_token} ::=') lastname = production['tokenname'] else: - self.body.append('{} '.format(' ' * len(lastname))) + prefix = ' ' * len(lastname) + self.body.append(f'{prefix} ') text = production.astext() text = self.encode(text) self.body.append(text + self.nl) @@ -2263,8 +2263,7 @@ def visit_versionmodified(self, node): elif node['type'] == 'versionadded': self._visit_info(node) else: - self.warn('unsupported version modification type: ' - '{}'.format(node['type'])) + self.warn('unsupported version modification type: ' + node['type']) self._visit_info(node) depart_versionmodified = _depart_admonition @@ -2297,7 +2296,7 @@ def visit_confluence_excerpt_include(self, node): if not doctitle: self.warn('unable to build excerpt include to document since ' 'document is missing or is missing title ' - '(in {}): {}'.format(self.docname, docname)) + f'(in {self.docname}): {docname}') raise nodes.SkipNode elif ':' in doclink: space_key, doctitle = doclink.split(':', 1) @@ -2542,7 +2541,7 @@ def visit_confluence_doc_card(self, node): self.body.append(self._end_tag(node, suffix='')) else: self.warn('unable to build link to document card due to ' - 'missing title (in {}): {}'.format(self.docname, docname)) + f'missing title (in {self.docname}): {docname}') self.body.append(node.astext()) if not self.v2: @@ -2567,7 +2566,7 @@ def visit_confluence_doc_card_inline(self, node): self.body.append(self._end_ac_link(node)) else: self.warn('unable to build link to document card due to ' - 'missing title (in {}): {}'.format(self.docname, docname)) + f'missing title (in {self.docname}): {docname}') self.body.append(node.astext()) raise nodes.SkipNode @@ -3038,7 +3037,8 @@ def visit_line_block(self, node): style += f'margin-left: {indent}px;' elif self.v2: # (see "visit_paragraph") - style += 'margin-left: {}px;'.format(INDENT * self._indent_level) + offset = INDENT * self._indent_level + style += f'margin-left: {offset}px;' if style: attribs['style'] = style @@ -3163,7 +3163,8 @@ def _start_tag(self, node, tag, suffix=None, empty=False, **kwargs): except AttributeError: node.__confluence_tag = [tag] - return '<{}{}'.format(' '.join(data), suffix) + prefix = ' '.join(data) + return f'<{prefix}{suffix}' def _end_tag(self, node, suffix=None): """ diff --git a/sphinxcontrib/confluencebuilder/transmute/__init__.py b/sphinxcontrib/confluencebuilder/transmute/__init__.py index 018d6c1c..eed60183 100644 --- a/sphinxcontrib/confluencebuilder/transmute/__init__.py +++ b/sphinxcontrib/confluencebuilder/transmute/__init__.py @@ -147,9 +147,8 @@ def __init__(self, builder): if 'ids' in new_node: math_image_ids.extend(new_node['ids']) - except imgmath.MathExtError as exc: - ConfluenceLogger.warn('inline latex {}: {}'.format( - node.astext(), exc)) + except imgmath.MathExtError as ex: + ConfluenceLogger.warn(f'inline latex {node.astext()}: {ex}') # v2 editor will manually inject anchors in an image-managed # section to avoid a newline spacing between the anchor and @@ -215,8 +214,9 @@ def __init__(self, builder): mock_translator = MockTranslator(builder) for node in findall(doctree, graphviz): + node_code = node['code'] try: - _, out_filename = render_dot(mock_translator, node['code'], + _, out_filename = render_dot(mock_translator, node_code, node['options'], builder.graphviz_output_format, 'graphviz') if not out_filename: node.parent.remove(node) @@ -226,8 +226,8 @@ def __init__(self, builder): if 'align' in node: new_node['align'] = node['align'] node.replace_self(new_node) - except GraphvizError as exc: - ConfluenceLogger.warn('dot code {}: {}'.format(node['code'], exc)) + except GraphvizError as ex: + ConfluenceLogger.warn(f'dot code {node_code}: {ex}') node.parent.remove(node) diff --git a/tests/__main__.py b/tests/__main__.py index f75136a4..591ffeab 100644 --- a/tests/__main__.py +++ b/tests/__main__.py @@ -71,14 +71,14 @@ def main(): target_unit_test_name_pattern) if not target_unit_tests: print('\nERROR: unable to find test with pattern: ' - '{}\n'.format(target_unit_test_name_pattern)) + f'{target_unit_test_name_pattern}\n') if issued: issued[0].debug() sys.exit(1) + total_tests = len(target_unit_tests) print('') - print('running specific test(s) (total: {})'.format( - len(target_unit_tests))) + print(f'running specific test(s) (total: {total_tests})') for target_unit_test in target_unit_tests: print(f' {target_unit_test.id()}') print('') diff --git a/tests/lib/__init__.py b/tests/lib/__init__.py index f6d75605..0d064e89 100644 --- a/tests/lib/__init__.py +++ b/tests/lib/__init__.py @@ -74,16 +74,16 @@ def check_unhandled_requests(self): with self.mtx: if self.del_req or self.get_req or self.put_req: - raise Exception('''unhandled requests detected + raise Exception(f'''unhandled requests detected (get requests) -{} +{self.get_req} (put requests) -{} +{self.put_req} (del requests) -{}'''.format(self.get_req, self.put_req, self.del_req)) +{self.del_req}''') def pop_delete_request(self): """ diff --git a/tests/test_validation.py b/tests/test_validation.py index bb562e3f..8655be60 100644 --- a/tests/test_validation.py +++ b/tests/test_validation.py @@ -88,10 +88,10 @@ def setUpClass(cls): cls.config['confluence_publish_postfix'] = '' cls.config['confluence_cleanup_archive'] = False cls.config['confluence_sourcelink']['version'] = cls.test_version - cls.config['rst_epilog'] = """ -.. |test_key| replace:: {} -.. |test_desc| replace:: {} -""".format(cls.test_key, cls.test_desc) + cls.config['rst_epilog'] = f''' +.. |test_key| replace:: {cls.test_key} +.. |test_desc| replace:: {cls.test_desc} +''' # find validate-sets base folder test_dir = Path(__file__).parent.resolve() diff --git a/tests/unit-tests/test_config_postfix_formatting.py b/tests/unit-tests/test_config_postfix_formatting.py index 997a489b..a83dbee7 100644 --- a/tests/unit-tests/test_config_postfix_formatting.py +++ b/tests/unit-tests/test_config_postfix_formatting.py @@ -88,8 +88,7 @@ def test_placeholder_with_format_type(self): postfix = ConfluenceState._format_postfix( postfix=confluence_publish_prefix, docname=test_docname, config=config) - self.assertEqual(postfix, '- ({hash})'.format( - hash=self.test_hash[0:10])) + self.assertEqual(postfix, f'- ({self.test_hash[0:10]})') class TestRegisterTitle(ConfluenceTestCase): diff --git a/tests/unit-tests/test_sphinx_image_candidate.py b/tests/unit-tests/test_sphinx_image_candidate.py index 356d19f4..d1986620 100644 --- a/tests/unit-tests/test_sphinx_image_candidate.py +++ b/tests/unit-tests/test_sphinx_image_candidate.py @@ -26,8 +26,7 @@ def test_storage_sphinx_image_candidate(self): self.assertIsNotNone(ext) - pyver = 'py{}{}'.format(sys.version_info.major, - sys.version_info.minor) + pyver = f'py{sys.version_info.major}{sys.version_info.minor}' doc_dir = prepare_dirs(postfix=f'-{pyver}-docs-{ext[1:]}') out_dir = prepare_dirs(postfix=f'-{pyver}-out-{ext[1:]}')