From 292e0266f08d624a91f9cf541c1b665e91295677 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Wed, 19 Mar 2025 19:23:39 +0000 Subject: [PATCH 001/435] Bump Ruff to 0.9.10 --- pyproject.toml | 2 +- sphinx/directives/other.py | 2 +- sphinx/domains/c/_parser.py | 2 +- sphinx/domains/citation.py | 2 +- sphinx/domains/cpp/__init__.py | 2 +- sphinx/domains/cpp/_parser.py | 2 +- sphinx/domains/python/__init__.py | 12 ++--- sphinx/domains/rst.py | 2 +- sphinx/environment/adapters/indexentries.py | 2 +- sphinx/environment/collectors/asset.py | 2 +- sphinx/ext/autodoc/__init__.py | 10 ++--- sphinx/ext/autosummary/__init__.py | 2 +- sphinx/ext/autosummary/generate.py | 2 +- sphinx/ext/graphviz.py | 4 +- sphinx/ext/imgmath.py | 6 +-- sphinx/ext/inheritance_diagram.py | 2 +- sphinx/ext/napoleon/docstring.py | 2 +- sphinx/ext/viewcode.py | 6 +-- sphinx/roles.py | 2 +- sphinx/util/docfields.py | 2 +- sphinx/util/docutils.py | 2 +- sphinx/writers/texinfo.py | 2 +- tests/test_builders/test_build_linkcheck.py | 4 +- tests/test_config/test_config.py | 2 +- tests/test_directives/test_directive_code.py | 44 +++++++++---------- tests/test_domains/test_domain_py.py | 2 +- tests/test_extensions/test_ext_coverage.py | 2 +- .../test_ext_intersphinx_cache.py | 6 +-- 28 files changed, 66 insertions(+), 66 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 9645f148dd3..59312974f8b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -92,7 +92,7 @@ docs = [ "sphinxcontrib-websupport", ] lint = [ - "ruff==0.9.9", + "ruff==0.9.10", "mypy==1.15.0", "sphinx-lint>=0.9", "types-colorama==0.4.15.20240311", diff --git a/sphinx/directives/other.py b/sphinx/directives/other.py index d9c2b98fd84..8c66ed383b5 100644 --- a/sphinx/directives/other.py +++ b/sphinx/directives/other.py @@ -411,7 +411,7 @@ def _insert_input(include_lines: list[str], source: str) -> None: if self.arguments[0].startswith('<') and self.arguments[0].endswith('>'): # docutils "standard" includes, do not do path processing return super().run() - rel_filename, filename = self.env.relfn2path(self.arguments[0]) + _rel_filename, filename = self.env.relfn2path(self.arguments[0]) self.arguments[0] = str(filename) self.env.note_included(filename) return super().run() diff --git a/sphinx/domains/c/_parser.py b/sphinx/domains/c/_parser.py index 7eb09f6f7b8..bd7ddbe2326 100644 --- a/sphinx/domains/c/_parser.py +++ b/sphinx/domains/c/_parser.py @@ -230,7 +230,7 @@ def _parse_paren_expression_list(self) -> ASTParenExprList | None: # # expression-list # -> initializer-list - exprs, trailing_comma = self._parse_initializer_list( + exprs, _trailing_comma = self._parse_initializer_list( 'parenthesized expression-list', '(', ')' ) if exprs is None: diff --git a/sphinx/domains/citation.py b/sphinx/domains/citation.py index 49b74cca269..348888c2d50 100644 --- a/sphinx/domains/citation.py +++ b/sphinx/domains/citation.py @@ -106,7 +106,7 @@ def resolve_xref( node: pending_xref, contnode: Element, ) -> nodes.reference | None: - docname, labelid, lineno = self.citations.get(target, ('', '', 0)) + docname, labelid, _lineno = self.citations.get(target, ('', '', 0)) if not docname: return None diff --git a/sphinx/domains/cpp/__init__.py b/sphinx/domains/cpp/__init__.py index 75d7732a405..fc72e208791 100644 --- a/sphinx/domains/cpp/__init__.py +++ b/sphinx/domains/cpp/__init__.py @@ -744,7 +744,7 @@ def apply(self, **kwargs: Any) -> None: template_decls = ns.templatePrefix.templates else: template_decls = [] - symbols, fail_reason = parent_symbol.find_name( + symbols, _fail_reason = parent_symbol.find_name( nestedName=name, templateDecls=template_decls, typ='any', diff --git a/sphinx/domains/cpp/_parser.py b/sphinx/domains/cpp/_parser.py index d28c474795d..aa941260da9 100644 --- a/sphinx/domains/cpp/_parser.py +++ b/sphinx/domains/cpp/_parser.py @@ -365,7 +365,7 @@ def _parse_paren_expression_list(self) -> ASTParenExprList: # # expression-list # -> initializer-list - exprs, trailing_comma = self._parse_initializer_list( + exprs, _trailing_comma = self._parse_initializer_list( 'parenthesized expression-list', '(', ')' ) if exprs is None: diff --git a/sphinx/domains/python/__init__.py b/sphinx/domains/python/__init__.py index 97519ee028e..af923cae70e 100644 --- a/sphinx/domains/python/__init__.py +++ b/sphinx/domains/python/__init__.py @@ -108,7 +108,7 @@ def add_target_and_index( modname = self.options.get('module', self.env.ref_context.get('py:module')) node_id = signode['ids'][0] - name, cls = name_cls + name, _cls = name_cls if modname: text = _('%s() (in module %s)') % (name, modname) self.indexnode['entries'].append(('single', text, node_id, '', None)) @@ -175,7 +175,7 @@ def handle_signature(self, sig: str, signode: desc_signature) -> tuple[str, str] return fullname, prefix def get_index_text(self, modname: str, name_cls: tuple[str, str]) -> str: - name, cls = name_cls + name, _cls = name_cls if modname: return _('%s (in module %s)') % (name, modname) else: @@ -268,7 +268,7 @@ def get_signature_prefix(self, sig: str) -> Sequence[nodes.Node]: return prefix def get_index_text(self, modname: str, name_cls: tuple[str, str]) -> str: - name, cls = name_cls + name, _cls = name_cls try: clsname, methname = name.rsplit('.', 1) if modname and self.config.add_module_names: @@ -364,7 +364,7 @@ def handle_signature(self, sig: str, signode: desc_signature) -> tuple[str, str] return fullname, prefix def get_index_text(self, modname: str, name_cls: tuple[str, str]) -> str: - name, cls = name_cls + name, _cls = name_cls try: clsname, attrname = name.rsplit('.', 1) if modname and self.config.add_module_names: @@ -424,7 +424,7 @@ def get_signature_prefix(self, sig: str) -> Sequence[nodes.Node]: return prefix def get_index_text(self, modname: str, name_cls: tuple[str, str]) -> str: - name, cls = name_cls + name, _cls = name_cls try: clsname, attrname = name.rsplit('.', 1) if modname and self.config.add_module_names: @@ -464,7 +464,7 @@ def handle_signature(self, sig: str, signode: desc_signature) -> tuple[str, str] return fullname, prefix def get_index_text(self, modname: str, name_cls: tuple[str, str]) -> str: - name, cls = name_cls + name, _cls = name_cls try: clsname, attrname = name.rsplit('.', 1) if modname and self.config.add_module_names: diff --git a/sphinx/domains/rst.py b/sphinx/domains/rst.py index cd5d8312d4a..55aa3103d8a 100644 --- a/sphinx/domains/rst.py +++ b/sphinx/domains/rst.py @@ -83,7 +83,7 @@ def _toc_entry_name(self, sig_node: desc_signature) -> str: return '' objtype = sig_node.parent.get('objtype') - *parents, name = sig_node['_toc_parts'] + *_parents, name = sig_node['_toc_parts'] if objtype == 'directive:option': return f':{name}:' if self.config.toc_object_entries_show_parents in {'domain', 'all'}: diff --git a/sphinx/environment/adapters/indexentries.py b/sphinx/environment/adapters/indexentries.py index c19628515b6..e9e6e408b6c 100644 --- a/sphinx/environment/adapters/indexentries.py +++ b/sphinx/environment/adapters/indexentries.py @@ -253,7 +253,7 @@ def _key_func_2(entry: tuple[str, _IndexEntryTargets]) -> str: def _group_by_func(entry: tuple[str, _IndexEntry]) -> str: """Group the entries by letter or category key.""" - key, (targets, sub_items, category_key) = entry + key, (_targets, _sub_items, category_key) = entry if category_key is not None: return category_key diff --git a/sphinx/environment/collectors/asset.py b/sphinx/environment/collectors/asset.py index 13105587673..e199fc90124 100644 --- a/sphinx/environment/collectors/asset.py +++ b/sphinx/environment/collectors/asset.py @@ -117,7 +117,7 @@ def collect_candidates( try: mimetype = guess_mimetype(filename) if mimetype is None: - basename, suffix = os.path.splitext(filename) + _basename, suffix = os.path.splitext(filename) mimetype = 'image/x-' + suffix[1:] if mimetype not in candidates: globbed.setdefault(mimetype, []).append(new_imgpath.as_posix()) diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index 8cdb039df3e..560b6905208 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -463,7 +463,7 @@ def parse_name(self) -> bool: type='autodoc', ) return False - explicit_modname, path, base, tp_list, args, retann = matched.groups() + explicit_modname, path, base, _tp_list, args, retann = matched.groups() # support explicit module and class name separation via :: if explicit_modname is not None: @@ -1359,7 +1359,7 @@ def resolve_name( # ... if still falsy, there's no way to know if not mod_cls: return None, [] - modname, sep, cls = mod_cls.rpartition('.') + modname, _sep, cls = mod_cls.rpartition('.') parents = [cls] # if the module name is still missing, get it like above if not modname: @@ -1405,7 +1405,7 @@ def _find_signature(self) -> tuple[str | None, str | None] | None: match = py_ext_sig_re.match(line) if not match: break - exmod, path, base, tp_list, args, retann = match.groups() + _exmod, _path, base, _tp_list, args, retann = match.groups() # the base name must match ours if base not in valid_names: @@ -2295,7 +2295,7 @@ def should_suppress_value_header(self) -> bool: return True else: doc = self.get_doc() or [] - docstring, metadata = separate_metadata( + _docstring, metadata = separate_metadata( '\n'.join(functools.reduce(operator.iadd, doc, [])) ) if 'hide-value' in metadata: @@ -2947,7 +2947,7 @@ def should_suppress_value_header(self) -> bool: else: doc = self.get_doc() if doc: - docstring, metadata = separate_metadata( + _docstring, metadata = separate_metadata( '\n'.join(functools.reduce(operator.iadd, doc, [])) ) if 'hide-value' in metadata: diff --git a/sphinx/ext/autosummary/__init__.py b/sphinx/ext/autosummary/__init__.py index 97c64a37cd1..733c936d8f0 100644 --- a/sphinx/ext/autosummary/__init__.py +++ b/sphinx/ext/autosummary/__init__.py @@ -814,7 +814,7 @@ def import_ivar_by_name( """ try: name, attr = name.rsplit('.', 1) - real_name, obj, parent, modname = import_by_name(name, prefixes) + real_name, obj, _parent, modname = import_by_name(name, prefixes) # Get ancestors of the object (class.__mro__ includes the class itself as # the first entry) diff --git a/sphinx/ext/autosummary/generate.py b/sphinx/ext/autosummary/generate.py index d865c0de2af..62a106479ea 100644 --- a/sphinx/ext/autosummary/generate.py +++ b/sphinx/ext/autosummary/generate.py @@ -719,7 +719,7 @@ def find_autosummary_in_docstring( See `find_autosummary_in_lines`. """ try: - real_name, obj, parent, modname = import_by_name(name) + _real_name, obj, _parent, _modname = import_by_name(name) lines = pydoc.getdoc(obj).splitlines() return find_autosummary_in_lines(lines, module=name, filename=filename) except AttributeError: diff --git a/sphinx/ext/graphviz.py b/sphinx/ext/graphviz.py index 9cd4d163e36..b973c1f5870 100644 --- a/sphinx/ext/graphviz.py +++ b/sphinx/ext/graphviz.py @@ -431,7 +431,7 @@ def render_dot_latex( filename: str | None = None, ) -> None: try: - fname, outfn = render_dot(self, code, options, 'pdf', prefix, filename) + fname, _outfn = render_dot(self, code, options, 'pdf', prefix, filename) except GraphvizError as exc: logger.warning(__('dot code %r: %s'), code, exc) raise nodes.SkipNode from exc @@ -475,7 +475,7 @@ def render_dot_texinfo( prefix: str = 'graphviz', ) -> None: try: - fname, outfn = render_dot(self, code, options, 'png', prefix) + fname, _outfn = render_dot(self, code, options, 'png', prefix) except GraphvizError as exc: logger.warning(__('dot code %r: %s'), code, exc) raise nodes.SkipNode from exc diff --git a/sphinx/ext/imgmath.py b/sphinx/ext/imgmath.py index b7bcf4a7a67..5b58db7b084 100644 --- a/sphinx/ext/imgmath.py +++ b/sphinx/ext/imgmath.py @@ -200,7 +200,7 @@ def convert_dvi_to_png(dvipath: Path, builder: Builder, out_path: Path) -> int | command.append('--depth') command.append(dvipath) - stdout, stderr = convert_dvi_to_image(command, name) + stdout, _stderr = convert_dvi_to_image(command, name) depth = None if builder.config.imgmath_use_preview: @@ -221,7 +221,7 @@ def convert_dvi_to_svg(dvipath: Path, builder: Builder, out_path: Path) -> int | command.extend(builder.config.imgmath_dvisvgm_args) command.append(dvipath) - stdout, stderr = convert_dvi_to_image(command, name) + _stdout, stderr = convert_dvi_to_image(command, name) depth = None if builder.config.imgmath_use_preview: @@ -370,7 +370,7 @@ def html_visit_displaymath(self: HTML5Translator, node: nodes.math_block) -> Non else: latex = wrap_displaymath(node.astext(), None, False) try: - rendered_path, depth = render_math(self, latex) + rendered_path, _depth = render_math(self, latex) except MathExtError as exc: msg = str(exc) sm = nodes.system_message( diff --git a/sphinx/ext/inheritance_diagram.py b/sphinx/ext/inheritance_diagram.py index ce05626abe5..83a6d4b7b01 100644 --- a/sphinx/ext/inheritance_diagram.py +++ b/sphinx/ext/inheritance_diagram.py @@ -436,7 +436,7 @@ def run(self) -> list[Node]: # references to real URLs later. These nodes will eventually be # removed from the doctree after we're done with them. for name in graph.get_all_class_names(): - refnodes, x = class_role( # type: ignore[misc] + refnodes, _x = class_role( # type: ignore[misc] 'class', f':class:`{name}`', name, 0, self.state.inliner ) node.extend(refnodes) diff --git a/sphinx/ext/napoleon/docstring.py b/sphinx/ext/napoleon/docstring.py index d1317e9d841..38325df1d94 100644 --- a/sphinx/ext/napoleon/docstring.py +++ b/sphinx/ext/napoleon/docstring.py @@ -476,7 +476,7 @@ def _consume_field( ) -> tuple[str, str, list[str]]: line = self._lines.next() - before, colon, after = self._partition_field_on_colon(line) + before, _colon, after = self._partition_field_on_colon(line) _name, _type, _desc = before, '', after if parse_type: diff --git a/sphinx/ext/viewcode.py b/sphinx/ext/viewcode.py index 4b1c62ad0d1..39e4cf420b7 100644 --- a/sphinx/ext/viewcode.py +++ b/sphinx/ext/viewcode.py @@ -205,7 +205,7 @@ def env_purge_doc(app: Sphinx, env: BuildEnvironment, docname: str) -> None: if entry is False: continue - code, tags, used, refname = entry + _code, _tags, used, _refname = entry for fullname in list(used): if used[fullname] == docname: used.pop(fullname) @@ -250,7 +250,7 @@ def get_module_filename(app: Sphinx, modname: str) -> _StrPath | None: return None else: try: - filename, source = ModuleAnalyzer.get_module_source(modname) + filename, _source = ModuleAnalyzer.get_module_source(modname) return filename except Exception: return None @@ -323,7 +323,7 @@ def collect_pages(app: Sphinx) -> Iterator[tuple[str, dict[str, Any], str]]: max_index = len(lines) - 1 link_text = _('[docs]') for name, docname in used.items(): - type, start, end = tags[name] + _type, start, end = tags[name] backlink = urito(pagename, docname) + '#' + refname + '.' + name lines[start] = ( f'
{var r;if(!(c.cursor
{var r;if(!(c.cursor {if(!(c.cursor =r.limit){break r}r.cursor++}continue}r.cursor=e;break}return true}function v(){m=r.limit;k=r.limit;b=r.limit;var i=r.cursor;r:{e:{var s=r.cursor;i:{if(!r.in_grouping(o,97,251)){break i}if(!r.in_grouping(o,97,251)){break i}if(r.cursor>=r.limit){break i}r.cursor++;break e}r.cursor=s;i:{if(r.find_among(e)==0){break i}break e}r.cursor=s;if(r.cursor>=r.limit){break r}r.cursor++;i:while(true){s:{if(!r.in_grouping(o,97,251)){break s}break i}if(r.cursor>=r.limit){break r}r.cursor++}}m=r.cursor}r.cursor=i;var a=r.cursor;r:{e:while(true){i:{if(!r.in_grouping(o,97,251)){break i}break e}if(r.cursor>=r.limit){break r}r.cursor++}e:while(true){i:{if(!r.out_grouping(o,97,251)){break i}break e}if(r.cursor>=r.limit){break r}r.cursor++}k=r.cursor;e:while(true){i:{if(!r.in_grouping(o,97,251)){break i}break e}if(r.cursor>=r.limit){break r}r.cursor++}e:while(true){i:{if(!r.out_grouping(o,97,251)){break i}break e}if(r.cursor>=r.limit){break r}r.cursor++}b=r.cursor}r.cursor=a;return true}function d(){var e;while(true){var s=r.cursor;r:{r.bra=r.cursor;e=r.find_among(i);if(e==0){break r}r.ket=r.cursor;switch(e){case 1:if(!r.slice_from("i")){return false}break;case 2:if(!r.slice_from("u")){return false}break;case 3:if(!r.slice_from("y")){return false}break;case 4:if(!r.slice_from("ë")){return false}break;case 5:if(!r.slice_from("ï")){return false}break;case 6:if(!r.slice_del()){return false}break;case 7:if(r.cursor>=r.limit){break r}r.cursor++;break}continue}r.cursor=s;break}return true}function g(){if(!(m<=r.cursor)){return false}return true}function w(){if(!(k<=r.cursor)){return false}return true}function q(){if(!(b<=r.cursor)){return false}return true}function h(){var e;r.ket=r.cursor;e=r.find_among_b(u);if(e==0){return false}r.bra=r.cursor;switch(e){case 1:if(!q()){return false}if(!r.slice_del()){return false}break;case 2:if(!q()){return false}if(!r.slice_del()){return false}var i=r.limit-r.cursor;r:{r.ket=r.cursor;if(!r.eq_s_b("ic")){r.cursor=r.limit-i;break r}r.bra=r.cursor;e:{var t=r.limit-r.cursor;i:{if(!q()){break i}if(!r.slice_del()){return false}break e}r.cursor=r.limit-t;if(!r.slice_from("iqU")){return false}}}break;case 3:if(!q()){return false}if(!r.slice_from("log")){return false}break;case 4:if(!q()){return false}if(!r.slice_from("u")){return false}break;case 5:if(!q()){return false}if(!r.slice_from("ent")){return false}break;case 6:if(!g()){return false}if(!r.slice_del()){return false}var c=r.limit-r.cursor;r:{r.ket=r.cursor;e=r.find_among_b(s);if(e==0){r.cursor=r.limit-c;break r}r.bra=r.cursor;switch(e){case 1:if(!q()){r.cursor=r.limit-c;break r}if(!r.slice_del()){return false}r.ket=r.cursor;if(!r.eq_s_b("at")){r.cursor=r.limit-c;break r}r.bra=r.cursor;if(!q()){r.cursor=r.limit-c;break r}if(!r.slice_del()){return false}break;case 2:e:{var f=r.limit-r.cursor;i:{if(!q()){break i}if(!r.slice_del()){return false}break e}r.cursor=r.limit-f;if(!w()){r.cursor=r.limit-c;break r}if(!r.slice_from("eux")){return false}}break;case 3:if(!q()){r.cursor=r.limit-c;break r}if(!r.slice_del()){return false}break;case 4:if(!g()){r.cursor=r.limit-c;break r}if(!r.slice_from("i")){return false}break}}break;case 7:if(!q()){return false}if(!r.slice_del()){return false}var l=r.limit-r.cursor;r:{r.ket=r.cursor;e=r.find_among_b(a);if(e==0){r.cursor=r.limit-l;break r}r.bra=r.cursor;switch(e){case 1:e:{var n=r.limit-r.cursor;i:{if(!q()){break i}if(!r.slice_del()){return false}break e}r.cursor=r.limit-n;if(!r.slice_from("abl")){return false}}break;case 2:e:{var b=r.limit-r.cursor;i:{if(!q()){break i}if(!r.slice_del()){return false}break e}r.cursor=r.limit-b;if(!r.slice_from("iqU")){return false}}break;case 3:if(!q()){r.cursor=r.limit-l;break r}if(!r.slice_del()){return false}break}}break;case 8:if(!q()){return false}if(!r.slice_del()){return false}var k=r.limit-r.cursor;r:{r.ket=r.cursor;if(!r.eq_s_b("at")){r.cursor=r.limit-k;break r}r.bra=r.cursor;if(!q()){r.cursor=r.limit-k;break r}if(!r.slice_del()){return false}r.ket=r.cursor;if(!r.eq_s_b("ic")){r.cursor=r.limit-k;break r}r.bra=r.cursor;e:{var m=r.limit-r.cursor;i:{if(!q()){break i}if(!r.slice_del()){return false}break e}r.cursor=r.limit-m;if(!r.slice_from("iqU")){return false}}}break;case 9:if(!r.slice_from("eau")){return false}break;case 10:if(!w()){return false}if(!r.slice_from("al")){return false}break;case 11:r:{var _=r.limit-r.cursor;e:{if(!q()){break e}if(!r.slice_del()){return false}break r}r.cursor=r.limit-_;if(!w()){return false}if(!r.slice_from("eux")){return false}}break;case 12:if(!w()){return false}if(!r.out_grouping_b(o,97,251)){return false}if(!r.slice_del()){return false}break;case 13:if(!g()){return false}if(!r.slice_from("ant")){return false}return false;case 14:if(!g()){return false}if(!r.slice_from("ent")){return false}return false;case 15:var v=r.limit-r.cursor;if(!r.in_grouping_b(o,97,251)){return false}if(!g()){return false}r.cursor=r.limit-v;if(!r.slice_del()){return false}return false}return true}function p(){if(r.cursor ' +
- '' +
- _("Hide Search Matches") +
- " '
+ + ''
+ + _("Hide Search Matches")
+ + ">>3]&1<<(7&s)))return!0;this.cursor--}return!1},this.out_grouping=function(t,r,i){return!(this.cursor>=this.limit)&&(i<(i=this.current.charCodeAt(this.cursor))||i>>3]&1<<(7&s)))return!0;this.cursor--}return!1},this.out_grouping=function(t,r,i){return!(this.cursor>=this.limit)&&(i<(i=this.current.charCodeAt(this.cursor))||i'
- )
+ tooltip = get_tooltip(self, node, config=config)
+ self.body.append(f'
')
raise nodes.SkipNode
def html_visit_displaymath(self: HTML5Translator, node: nodes.math_block) -> None:
+ config = self.builder.config
if node.get('no-wrap', node.get('nowrap', False)):
latex = node.astext()
else:
latex = wrap_displaymath(node.astext(), None, False)
try:
- rendered_path, _depth = render_math(self, latex)
+ rendered_path, _depth = render_math(self, latex, config=config)
except MathExtError as exc:
msg = str(exc)
sm = nodes.system_message(
@@ -393,14 +375,15 @@ def html_visit_displaymath(self: HTML5Translator, node: nodes.math_block) -> Non
f'{self.encode(node.astext()).strip()}
and
and
~&d)Fw*e_RX1bFPwN>D c4$CE>KxyBKE zo4H9&rV6UHk%6zeIYuRSIb4R`IG1ubGp(zEqiJ&JY8gc*&jhPrMCEp%ldBZ9*+cJ& zGY6Ixz4zMv3{bc>>;Racapx9g m=JNG)@uuk6Tvudty-IS5Qt$;?H2}`KN2a&h-8OxELtFIY}J;n>%A@u zHauqWmy@QBMCvR{OkiBD!J(&yA~iSxM;oEv(;0Hquk9VmHQ@<`BAJOc=nv3~RP#pq zto)V~>`#TO?baptIS0Zr#`?* 8+3g-PNiYgoVV3`4JaGXv!IQV>)I!*dkOs#siHz)sbF5&EQFD{}mj(YQT!&Zj zqLSJi21%dvfzA?|!C2yhX+l&;uKSYO#iR A&nB?vrbk>rSE5p+Ujs(rFLX& O4=7v*EuRi3~oLA*Rya{Ak$D-~^H)uMl z8=7NJ>-ucEi98=0EvMFbBz_59(I rE7PE3w<_K6jfHfY#kX#i|^}cs4 zj993+LK`Ax2*9>^nKn~7HR73iuH_uR+K%SjcsUJQp1N$iRnzj}x6S1k&f$@adFsde zPV`fKqaZ19L$)f2qTDKV<$`J=t4hM4SIpIYSjMY7tk%&VF@6%;905!wJrRDQbuh(| z7qh&)UrX*v7hS&%Xp+FGu4FtFvuBZ49gopOpv$u3A!2gMH&k_ktUsduym3-Jh`Qtu zl%Ev2uYT*_696$vIAR$Hy?an3OxljFVnOa79{78uqVg475;6HgUWR(l&33c91IgIh z-XR1FotLr6;{M?)NwE_{GrPTeWXC9WDhrNJJJ2&Y&;6#DlwCOd5lw}6aajuRsfqz= z%o0;&;l4FNdML`2#l_LAG L?8umDVfBiZv2mb%?kYqU zqRPyemu7eYhl{pf0OpsQ%MUmbDMiZkWO*vC1QBjk4$U!_1vC{*6<%pUWX{K))h48* z;@K&|gxHZcO_p^xSd+hXi{Can@Bw0tcbWx;jW<94bjJkE3ne2PNaZTJ6J=ZEq^oE~ z7?&DY*sXW6EL9?AjLp3*&+Q{8ay3Hs88o<+qS!FbDaRk4ew EHgpJclj54(IVKX2h+-{`fQzyf!->@r7d#2H?3bWR&>``X_aSMm3H^Ttm zVkX%j#CzZ0-Z)QBSbsq5h0-57M){Y5ka_9PJp{Sfv|i9!t|#Edpj$GY8t?rQ{75F< zz@bW2QDMDDro!D^`cylK@3G8EcAh5iKf82q5=!3ZP5=Al|1SHlo=@xV%lr*j^Y8|U zwYR4MmULo}%0KUwq_Qwf(IGA}D0U<_M5FphPN~U>8LCbAOT(!Cv^9|t$6_etde%dx zJdvX?P+W4Lk5U#@QZy6I>rzYLMW7UX&tfa%WmJ|T?9}yKgEt@-Z-(YEa5{QMmPe#S zL}^ah>|*j}?1FE5=9H|i9Rus4O4P=I`G2nd0!)r0OB;oQle4fvEhgJzdzfjN8Ginl z>F3ML%*@QZ%rN7fg<&$ISj~k=kpXv3oTp0Oo1;flU8*j%Tqh$=yypey_~`mi;FJS4 zWoL1r#<3!$G)WRTmP-lG8(&v#wQj8O!Ep^FIXI)}I!!$r42Dsh1d}cXY`!>6@_f8I z&GMW}Q8l$n)83dQ%NzwjNyL$g;=CyGqO{JAClffS)iwTb00Ko3fj95kwr!dQo(!Lg z?t89OmS@mQ!ON6NVk%g`cO_S#dV~HxjzBB|28B_Y4dN)40(4-e*G;toFD=(;HSAQ` zbXu-fxtOKVtdQqd-J9>(d6=C1_HFU{bnz!U>o>DroS)~7(XmXJr%5V}kEye1mUWaX z4rRm{$L52f#uqNSMaXavw3TrFAJ!^dKRBVdlVW4OUFzt&_%Q*#)u!)}@e9o*)`4}d zx8WxUCrkr4V*nror95Cb(gyu3fu>;N4+n5kZ~}#~s^VN);%y)b;Nfe#2KQRCuzaG* zsM8&A!-L FiNSe>q2i~i?WbXwrvag(l}1DY}M3hQ4R)!s;cJmxpO9pqAbheIA(%JQq9h1 z&O+Z~twEW8S2t2h;yuzO5yj53tg73=Z~z|+v~MOaOZbzf>a5B0QYq;-FUF=vMNyK( z9$>jhCUGQV2b%4LUbn_*_^$&1->}stXNwEb{BkmzM6;9oucZB&2yx}&?!$YJ+iWt8 z`PunnO3Y|DyrX{p(R_7I5?k(BHjIT6P7|j+SCj~}>L8W^q7$}i%6!;`%~q0t`?hx* zma`{P@h4Nu-umqoT7q{Qu_2Y&At@Aludu=)){h^YR0_y#0PC1Q%MA2!>rkBdM5Y!H zHFUVb5i_`;rv!ui2 zHtJZV6d?}Zj#0XMa4E~uM~@zlMms gpX|ysVGP*B^)cbVUjan649H^!@nH7E9R=b z_w?RspWVMy>PW`)^6u{LvoC-3i;HB;lO@;9 sHlXwkKG z@8~y!%O0A=P*PY_#sHjvTJ~Um>ch9vu+lMt^G8%n1xx`K#qf7vkA)2$%II;8jN` ~GgI6U^HX^K!Kp6L7D@ZG0=X6s{af~rO-An|(2+pZ?W4+rCN zP>#lvVmQo)Wt7Efp25B&SrVmr0%+4{JlWaVUDZ`SDC)kM&t}8X5WxOcyI#XCCgor- z5P~h1ODF>BOxLS8+CSKja}du*3ar)OZ=|3rrb2oD8Yro$u?q za?}+?&H+I0O>ZJV?P#le{A{um-mulJQs5&A=gXK7+wt{sQ7^fVh#*VLRCRJAKf21^ zj#hU&JE>O0^+)$!y;sd^qUowOJL8e?CXK~-oIZN++QYkY{?_U8?&}v)|ID>Z=hg9S z4R{cf838C-I;PQJ!+8t8!i7x*@i_R~uwigC7l=?Iz(4T0T1U1gK`GGl4%Z2+NOXMI zYH3h1+v^^2EhQzxmpO|71;P(_zCle9+N{H_?MROXIDr6<$gaghw6i!TV!*cpd>|Nq z8{$I;*IQx&Y0*0vssb!01A3!i?%0{2YPNiE{l^Fei9IZQL6R0)L&+GiV38F~rqd|N zeX!tWAa_n+n*%6F;_xCg?^&E?03{@F=}xCvS`5B(4SD#d4u+#Bju>P3y-^hBWeH1N zIQQ-DUEbZ>mojeJK8|IQBt=mqNpgN(DJl1M_oav?`_m-N@}h{-w8*l+Gj<@;(JkG; z)kRq #{SjAs zFe#EUd+O<%oU)^bhfUwANI1ZS^txKDs@8%qMccPuaD=Yupk+fX2GZ%cuRVzg+bUt6 zXz;^q8=t563k?NOse!;OtS;F2gqz%k;$VWItbV(Sus_w7835vfUyG1o+Jj>s!SJu% zGJ5cPgUJ%b1vUK6@hFGlA8hgkf5IJAD#AdAfO&cqAT$&9b{8D q~5``~sG%nsn#D2sfD&^XCQMOg?XVf)}L1t*ypb)=5?)nc()F9+jMZ~LaL zlO*lhZa5ke#`C;zp6I4tu7EieCyDniG)x5oeTWw?SL^BiL?(`KlNb4LGKP6&mTKEC z*Js0N5v3w2<8)Bs%9^JcVZc_8!Q0Z8VRl~E72|Nvfqq(dX_^*A#uo2E0Rw3~DZksZ$~lA?DY6bxa1}J9 zE>KW56gTJ4nG01B+xa6bNZT3Trcc`1nZ$9d0<4YWJQK`djdR$%V_9HbG6k;*y&ejr zy|=)PLw9ymc2P>OB7w!^(Igu_DPV3Q>z F_sn}rsdlC}X8Kl3hPnuPT% zaRGo3lGe2qDyo`VHY!U2QZ%Mpt=2_R;EJ7O@xkST#cHlH1vu}@JbL`VJ97Ej_0ee5 zcD=PgH-HR_IQD@>S5 U)F8 zS=CmFkFz|nsLI937fii*k|hAlDIUj?@gmGqqoT~Ib?fEaw|quA^ymao->B 1jcZ)^ZC)?`E+l5@#^iq?Uu87wX(nTi@*A_Kk DaOj HCmfn4$8m%JV-?Ch?z|{#5H?`{tPs3yTdR90GrTb71W9U$=?|{|1TKS0MMx+E zreT~&5f#M%NHUH#dI^}YpcYE9Pm`2|6&1ar2E*}aG-jaY%T1`ItSmU}_`;Z~X>}aK z#u%$uM$vdY=E3|pSju@W_;5TDz<`f*XLQ%aaS{c~p)AYOEDJyjwgH~PrvkG--L{l) z*s3*_X%eMrQsnqSmV-fF6i{)TTBCthC3xRS)3sG$o-OX&SpA`U_+_aEU;XBrgTa8q zx;wvm_3G*A$+eqT*44VJmzS QL5+g? zLf9@hv+OWCLmntB3OHCqhAI?P@L1H)`VidGP!x#-6pa5c#=?@LK`f1yX1#8K=pTp# z-iKjSNT49t&J%|x57Q%a+jtv_GxQ>iLqCH*ch|H{Q+2>H?|FRiBk&^J+=D--2v#*s zTZJ3|8>h;9()Tt4->Fn8iT58a8Br`plOcgJad8qe!N%j^U^Gn9creKGGGnaYyD&|2 zMY+q1G>&DQz+WOG)dQLe8q_39>!txRMO7K+!XPms8xE5c;0lSuM8;VQD{bdJfzJjM ztt?5P7DE_~4nTu~_S5&CrpC8~9;W>jE0TQ2eR}#%eE0MD`J1NKWHNp2E3aO !vogjt !R<_YuGbTWgpYbUiZIg;b2;K-Y_KVPh_(#DgJv*#K&5!wk-Pw3%Rl z^+qDhGcfuCdCq i%JjU9pn(O;QkuiAG9-J0N-_ey{bHd6y71k)vZ==QmZT18vzUxLRPC4z_1bN zmdiMar_)_eGHv@+wa!PyU^F^EKSyl^3*4cu?U0rf@rVg N(Md=e?{D8PIm?u{2PIuuj z&)3T(CpIj@ga=fn_s~_;bwvnT4tmF3OG%gXmz5r}S1zA^?&00nMZ&TuCVDNU9*yMv z$A_1%-ManU2g^axHuYpWJvco(J~}zr-}~&3eD7EO@Q>DWHyVsAwdcq4$#`e~;^jOm zAG~#+P)V4q9(_$V_djvv6E?bbXR&{z<@qvCV>yY8pG*-S=@8^?I|+^ffpUp6xOb^Z z0aGxZhKaokLqMe8F=M4v8&7T|pn~k8>tORF=-?8r@V&k_efV~`dICJVNQe#YZzz-( zEFBOEVWPfoo4Te-`W`x`u${G DF$5tgpm7DG&EUMi(NEWT7lPnmX^FvtDhr0C zpv_A1xESUtQl1*rpi3o?QpyA|K*H&I(-LAA=gX>U#-kCCd_hdFn{~~QwFSh{wE=2{ zX#$}NKAzsTZR5gOJr45#XYFJ>a?Z6~M*^rFDflO_uxD5%5^v$QDfX#u_wAck?AJbU zxj3G!mNLEm*&m4~d-v}@dhdrmbn)8N>2%78tD9D3L&u}*Pd{6fQz4YG{m$NARaI2- zXW#$c_kHlA2bV6_ZD)zUd+*M@w@;>nE6bz98 uTM!4V0Abkm~`Anh*Wo{wJKt1LC0aV1i&(IPs-%r2DP~7^#euLbb4x zG3@quDV7GNO%#J9D=RX}y^yfjLhBdyV m~9R zP`pYB{1^@d6!0zyxW>e7vsRp1ZFvM}aylr=$!N8lH_bZF^Wk6|MN9&S54U*T^sHO5 zcmUgb`|#4quS{p(*uSy2s_L4Ee1HGp+2Q)-V_-fJBZEJ8t2;0Rl=8;48=Q-iv$KOs zm)57JQ5rwEchC0vnfE{6RMpAxx!{R4zM0QofAJ+)7!$>n+TSf@&mV|q*zF%*n`zZK zCya;o2$hYNdQjmw?^esD$BB(GNMFX2pwoKWo?BzKDRY!?#LZDqi9-9X>pT>nivSex zNR&mZG^mcQLt;pfzzB(AQ3pPT#+asVbl(OguH=NR>qV$13+-23p|sGzX1PZB6}EJQ zf}RSE0_vtUx?{ql7atDcZC4>363kI9z5makc~PJvM~qP9t^_bWh7UA}0Vs(hWJd`p z5J>_4w+FsJRjr{GLGQ3heiDj?7a84ixB^LoGMH8}uO!^Tlkxs|yyJk7V+04O*7?~P zG_VZtXgpOh85!L-bsgjw04!_Wp%YM`vknFN9t&mxqZh%nR^i}05m7WOWGW7_^#$`< z|HiLf9FdlIr{aq@ucw0nVf+t& eEl(dj5Uy+ N^Br8M9*!5^97GO_!j1*%K4uxy${SprLu%yGH zhUjD9k)trldx8%F?UUjA5Kn?I*cn*pG_Zo&ZZTgj7mI4OT+Zjt_KU?#Ysi~vnl<$D zJ#OGFtPrMeo2JtpnwN@jHgevek1&c*6lZ819fr_1f0jZ2n+5e1I4pKe%L9z-0-Tj* z3A&Cj&Qv5fRYl?8V*qHz0aFx38?H19hoIol-@<|oMIRPsuHb%6vIM&^l?YFJ9zkDh zy$8>Qq8Pv-Q6*XCDXkkFMT%3l4i}KQIg}4qGB1j@YdQ1_KxaikTB0Ozq^@h|mlbOn z&mwcd9l2M3sXKgS|H{=><;UY foxOYK?RW0oy?*OvHXJ?wu}|H3=k?j6 z$LqspoY=MKR%B>>PF( &h4tMatS9 zKVJ-9kQ}~1^5)jACWNwT4WFw #n>x~8q0x~^(C#x-qlMzG;F LXRf0Qo cy-?4947zw!H5uUt$oUsIOK95CRc!{f*IkKVa+ugJ5D7j`F; za AMyHON4T?@tc9Tqh5ynM1|97 zP}fPQ^e}BiI366-an^@?LKv>oZEz08)Aqp#qc 3%qNg+CLJ5PYUjCzdyAT%6t2@HAKR)?Pnwkjy1dTn~(ICQO9FPBYKEf$OAeA$~i zQVMZoLAgcgIgmY+gVT5fh#Yl!Sx~~3tCekl3>{20!C!uN_X6d-7-oZVq%lFy_SJgb zYxtX>t6-!9;CGegIZd-Ye;B|0zqUs&?WBzwPe;Q&)B0Cm`pWrycKbc=d;9H2_uqPF z|HA(6c#w`uNn8{cQYCF&CwZ)UUt|S!`u^Q_x~55^Y%m zS**IIo|ff$aU83IWE_d+G(CM?J@dm-5fK-@;94e}DDJflTij|jC!XlmXw!%O-L}w` zZrt%a30359 Xubv~|X8TyeY* zfmH&A3)X1(k7bbJx2`*YjXZOWA*lqeRv9(h1a3~y9l||zQ>Zn$5 zyFiEA_95-Ug_gb1jT;O{S)Th$0AWzKx&fA9oFswp&$y50r{{!_ERI{^^AS+EWXcEQ zVo*+;qt$wScXl_<@+^sobrF}kY8H#-a5y|`iox=Ya#Xg116n^ia4)L 0x*gIbQU1=k`? 7_9FTM0q8pqS!gNVtOzWJ5o`;X@H z<#;qbJDuNr?&igVi(#p#sO*^}w$-~AM%g&3y16EOI-V}uw