--- genshi/builder.py | 12 ++++------ genshi/compat.py | 5 +--- genshi/core.py | 33 ++++++++++++++--------------- genshi/filters/html.py | 15 ++++++------- genshi/filters/i18n.py | 23 +++++++++----------- genshi/filters/tests/i18n.py | 5 +--- genshi/filters/tests/test_html.py | 43 ++++++++++++++++++-------------------- genshi/filters/tests/transform.py | 17 +++++++-------- genshi/filters/transform.py | 10 +++----- genshi/input.py | 26 +++++++++++----------- genshi/output.py | 7 ++---- genshi/path.py | 3 -- genshi/template/base.py | 16 ++++++-------- genshi/template/directives.py | 6 +---- genshi/template/eval.py | 20 +++++++---------- genshi/template/loader.py | 5 +--- genshi/template/plugin.py | 5 +--- genshi/template/tests/markup.py | 5 +--- genshi/template/text.py | 5 +--- genshi/util.py | 7 ++---- setup.cfg | 2 - 21 files changed, 122 insertions(+), 148 deletions(-) Index: Genshi-0.7.9/genshi/builder.py =================================================================== --- Genshi-0.7.9.orig/genshi/builder.py 2024-06-16 01:52:43.000000000 +0200 +++ Genshi-0.7.9/genshi/builder.py 2025-05-09 08:47:55.639423560 +0200 @@ -68,8 +68,6 @@ Hello, world! """ -import six - from genshi.compat import numeric_types from genshi.core import Attrs, Markup, Namespace, QName, Stream, \ START, END, TEXT @@ -110,7 +108,7 @@ return str(self.generate()) def __unicode__(self): - return six.text_type(self.generate()) + return str(self.generate()) def __html__(self): return Markup(self.generate()) @@ -121,7 +119,7 @@ :param node: the node to append; can be an `Element`, `Fragment`, or a `Stream`, or a Python string or number """ - simple_types = (Stream, Element) + six.string_types + numeric_types + simple_types = (Stream, Element, str) + numeric_types if isinstance(node, simple_types): # For objects of a known/primitive type, we avoid the check for # whether it is iterable for better performance @@ -144,8 +142,8 @@ for event in child: yield event else: - if not isinstance(child, six.string_types): - child = six.text_type(child) + if not isinstance(child, str): + child = str(child) yield TEXT, child, (None, -1, -1) def generate(self): @@ -162,7 +160,7 @@ for name, value in kwargs.items(): name = name.rstrip('_').replace('_', '-') if value is not None and name not in names: - attrs.append((QName(name), six.text_type(value))) + attrs.append((QName(name), str(value))) names.add(name) return Attrs(attrs) Index: Genshi-0.7.9/genshi/compat.py =================================================================== --- Genshi-0.7.9.orig/genshi/compat.py 2024-06-16 01:52:43.000000000 +0200 +++ Genshi-0.7.9/genshi/compat.py 2025-05-09 08:33:55.950025453 +0200 @@ -23,11 +23,10 @@ import warnings from types import CodeType -import six IS_PYTHON2 = (sys.version_info[0] == 2) -numeric_types = (float, ) + six.integer_types +numeric_types = (float, int) # This function should only be called in Python 2, and will fail in Python 3 @@ -47,7 +46,7 @@ # We need to test if an object is an instance of a string type in places def isstring(obj): - return isinstance(obj, six.string_types) + return isinstance(obj, str) # We need to differentiate between StringIO and BytesIO in places Index: Genshi-0.7.9/genshi/core.py =================================================================== --- Genshi-0.7.9.orig/genshi/core.py 2024-06-16 01:52:43.000000000 +0200 +++ Genshi-0.7.9/genshi/core.py 2025-05-09 08:30:16.089149971 +0200 @@ -18,7 +18,6 @@ from itertools import chain import operator -import six from genshi.compat import stringrepr from genshi.util import stripentities, striptags @@ -282,7 +281,7 @@ if hasattr(event, 'totuple'): event = event.totuple() else: - event = TEXT, six.text_type(event), (None, -1, -1) + event = TEXT, str(event), (None, -1, -1) yield event return @@ -411,7 +410,7 @@ :return: a new instance with the attribute removed :rtype: `Attrs` """ - if isinstance(names, six.string_types): + if isinstance(names, str): names = (names,) return Attrs([(name, val) for name, val in self if name not in names]) @@ -445,17 +444,17 @@ return TEXT, ''.join([x[1] for x in self]), (None, -1, -1) -class Markup(six.text_type): +class Markup(str): """Marks a string as being safe for inclusion in HTML/XML output without needing to be escaped. """ __slots__ = [] def __add__(self, other): - return Markup(six.text_type.__add__(self, escape(other))) + return Markup(str.__add__(self, escape(other))) def __radd__(self, other): - return Markup(six.text_type.__add__(escape(other), self)) + return Markup(str.__add__(escape(other), self)) def __mod__(self, args): if isinstance(args, dict): @@ -464,14 +463,14 @@ args = tuple(map(escape, args)) else: args = escape(args) - return Markup(six.text_type.__mod__(self, args)) + return Markup(str.__mod__(self, args)) def __mul__(self, num): - return Markup(six.text_type.__mul__(self, num)) + return Markup(str.__mul__(self, num)) __rmul__ = __mul__ def __repr__(self): - return "<%s %s>" % (type(self).__name__, six.text_type.__repr__(self)) + return "<%s %s>" % (type(self).__name__, str.__repr__(self)) def join(self, seq, escape_quotes=True): """Return a `Markup` object which is the concatenation of the strings @@ -489,7 +488,7 @@ :see: `escape` """ escaped_items = [escape(item, quotes=escape_quotes) for item in seq] - return Markup(six.text_type.join(self, escaped_items)) + return Markup(str.join(self, escaped_items)) @classmethod def escape(cls, text, quotes=True): @@ -538,7 +537,7 @@ """ if not self: return '' - return six.text_type(self).replace('"', '"') \ + return str(self).replace('"', '"') \ .replace('>', '>') \ .replace('<', '<') \ .replace('&', '&') @@ -652,7 +651,7 @@ self.uri = uri def __init__(self, uri): - self.uri = six.text_type(uri) + self.uri = str(uri) def __contains__(self, qname): return qname.namespace == self.uri @@ -691,7 +690,7 @@ XML_NAMESPACE = Namespace('http://www.w3.org/XML/1998/namespace') -class QName(six.text_type): +class QName(str): """A qualified element or attribute name. The unicode value of instances of this class contains the qualified name of @@ -729,11 +728,11 @@ qname = qname.lstrip('{') parts = qname.split('}', 1) if len(parts) > 1: - self = six.text_type.__new__(cls, '{%s' % qname) - self.namespace, self.localname = map(six.text_type, parts) + self = str.__new__(cls, '{%s' % qname) + self.namespace, self.localname = map(str, parts) else: - self = six.text_type.__new__(cls, qname) - self.namespace, self.localname = None, six.text_type(qname) + self = str.__new__(cls, qname) + self.namespace, self.localname = None, str(qname) return self def __getnewargs__(self): Index: Genshi-0.7.9/genshi/filters/html.py =================================================================== --- Genshi-0.7.9.orig/genshi/filters/html.py 2024-06-16 01:52:43.000000000 +0200 +++ Genshi-0.7.9/genshi/filters/html.py 2025-05-09 08:30:16.089433034 +0200 @@ -15,7 +15,6 @@ import re -import six from genshi.core import Attrs, QName, stripentities from genshi.core import END, START, TEXT, COMMENT @@ -99,13 +98,13 @@ checked = False if isinstance(value, (list, tuple)): if declval is not None: - u_vals = [six.text_type(v) for v in value] + u_vals = [str(v) for v in value] checked = declval in u_vals else: checked = any(value) else: if declval is not None: - checked = declval == six.text_type(value) + checked = declval == str(value) elif type == 'checkbox': checked = bool(value) if checked: @@ -121,7 +120,7 @@ value = value[0] if value is not None: attrs |= [ - (QName('value'), six.text_type(value)) + (QName('value'), str(value)) ] elif tagname == 'select': name = attrs.get('name') @@ -164,10 +163,10 @@ select_value = None elif in_select and tagname == 'option': if isinstance(select_value, (tuple, list)): - selected = option_value in [six.text_type(v) for v + selected = option_value in [str(v) for v in select_value] else: - selected = option_value == six.text_type(select_value) + selected = option_value == str(select_value) okind, (tag, attrs), opos = option_start if selected: attrs |= [(QName('selected'), 'selected')] @@ -183,7 +182,7 @@ option_text = [] elif in_textarea and tagname == 'textarea': if textarea_value: - yield TEXT, six.text_type(textarea_value), pos + yield TEXT, str(textarea_value), pos textarea_value = None in_textarea = False yield kind, data, pos @@ -526,7 +525,7 @@ def _repl(match): t = match.group(1) if t: - return six.unichr(int(t, 16)) + return chr(int(t, 16)) t = match.group(2) if t == '\\': return r'\\' Index: Genshi-0.7.9/genshi/filters/i18n.py =================================================================== --- Genshi-0.7.9.orig/genshi/filters/i18n.py 2024-06-16 01:52:43.000000000 +0200 +++ Genshi-0.7.9/genshi/filters/i18n.py 2025-05-09 08:30:16.089768807 +0200 @@ -24,7 +24,6 @@ from functools import partial from types import FunctionType -import six from genshi.core import Attrs, Namespace, QName, START, END, TEXT, \ XML_NAMESPACE, _ensure, StreamEventKind @@ -801,7 +800,7 @@ if kind is START: tag, attrs = data if tag in self.ignore_tags or \ - isinstance(attrs.get(xml_lang), six.string_types): + isinstance(attrs.get(xml_lang), str): skip += 1 yield kind, data, pos continue @@ -811,7 +810,7 @@ for name, value in attrs: newval = value - if isinstance(value, six.string_types): + if isinstance(value, str): text = value.strip() if translate_attrs and name in include_attrs and text: newval = gettext(text) @@ -831,7 +830,7 @@ elif translate_text and kind is TEXT: text = data.strip() if text: - data = data.replace(text, six.text_type(gettext(text))) + data = data.replace(text, str(gettext(text))) yield kind, data, pos elif kind is SUB: @@ -944,7 +943,7 @@ if kind is START and not skip: tag, attrs = data if tag in self.ignore_tags or \ - isinstance(attrs.get(xml_lang), six.string_types): + isinstance(attrs.get(xml_lang), str): skip += 1 continue @@ -1050,7 +1049,7 @@ def _extract_attrs(self, event, gettext_functions, search_text): for name, value in event[1][1]: - if search_text and isinstance(value, six.string_types): + if search_text and isinstance(value, str): if name in self.include_attrs: text = value.strip() if text: @@ -1321,10 +1320,10 @@ strings = [] def _add(arg): if isinstance(arg, _ast_Str) \ - and isinstance(_ast_Str_value(arg), six.text_type): + and isinstance(_ast_Str_value(arg), str): strings.append(_ast_Str_value(arg)) elif isinstance(arg, _ast_Str): - strings.append(six.text_type(_ast_Str_value(arg), 'utf-8')) + strings.append(str(_ast_Str_value(arg), 'utf-8')) elif arg: strings.append(None) [_add(arg) for arg in node.args] @@ -1365,22 +1364,22 @@ :rtype: ``iterator`` """ template_class = options.get('template_class', MarkupTemplate) - if isinstance(template_class, six.string_types): + if isinstance(template_class, str): module, clsname = template_class.split(':', 1) template_class = getattr(__import__(module, {}, {}, [clsname]), clsname) encoding = options.get('encoding', None) extract_text = options.get('extract_text', True) - if isinstance(extract_text, six.string_types): + if isinstance(extract_text, str): extract_text = extract_text.lower() in ('1', 'on', 'yes', 'true') ignore_tags = options.get('ignore_tags', Translator.IGNORE_TAGS) - if isinstance(ignore_tags, six.string_types): + if isinstance(ignore_tags, str): ignore_tags = ignore_tags.split() ignore_tags = [QName(tag) for tag in ignore_tags] include_attrs = options.get('include_attrs', Translator.INCLUDE_ATTRS) - if isinstance(include_attrs, six.string_types): + if isinstance(include_attrs, str): include_attrs = include_attrs.split() include_attrs = [QName(attr) for attr in include_attrs] Index: Genshi-0.7.9/genshi/filters/tests/i18n.py =================================================================== --- Genshi-0.7.9.orig/genshi/filters/tests/i18n.py 2024-06-16 01:52:43.000000000 +0200 +++ Genshi-0.7.9/genshi/filters/tests/i18n.py 2025-05-09 08:30:16.090147309 +0200 @@ -15,7 +15,6 @@ from gettext import NullTranslations import unittest -import six from genshi.core import Attrs from genshi.template import MarkupTemplate, Context @@ -48,7 +47,7 @@ if tmsg is missing: if self._fallback: return self._fallback.ugettext(message) - return six.text_type(message) + return str(message) return tmsg else: def gettext(self, message): @@ -57,7 +56,7 @@ if tmsg is missing: if self._fallback: return self._fallback.gettext(message) - return six.text_type(message) + return str(message) return tmsg if IS_PYTHON2: Index: Genshi-0.7.9/genshi/filters/tests/test_html.py =================================================================== --- Genshi-0.7.9.orig/genshi/filters/tests/test_html.py 2024-06-16 01:52:43.000000000 +0200 +++ Genshi-0.7.9/genshi/filters/tests/test_html.py 2025-05-09 08:30:16.090568412 +0200 @@ -13,7 +13,6 @@ import unittest -import six from genshi.input import HTML, ParseError from genshi.filters.html import HTMLFormFiller, HTMLSanitizer @@ -524,91 +523,91 @@ def test_sanitize_expression(self): html = HTML(u'
XSS
') - self.assertEqual('
XSS
', six.text_type(html | StyleSanitizer())) + self.assertEqual('
XSS
', str(html | StyleSanitizer())) def test_capital_expression(self): html = HTML(u'
XSS
') - self.assertEqual('
XSS
', six.text_type(html | StyleSanitizer())) + self.assertEqual('
XSS
', str(html | StyleSanitizer())) def test_sanitize_url_with_javascript(self): html = HTML(u'
' u'XSS
') - self.assertEqual('
XSS
', six.text_type(html | StyleSanitizer())) + self.assertEqual('
XSS
', str(html | StyleSanitizer())) def test_sanitize_capital_url_with_javascript(self): html = HTML(u'
' u'XSS
') - self.assertEqual('
XSS
', six.text_type(html | StyleSanitizer())) + self.assertEqual('
XSS
', str(html | StyleSanitizer())) def test_sanitize_unicode_escapes(self): html = HTML(u'
' u'XSS
') - self.assertEqual('
XSS
', six.text_type(html | StyleSanitizer())) + self.assertEqual('
XSS
', str(html | StyleSanitizer())) def test_sanitize_backslash_without_hex(self): html = HTML(u'
XSS
') - self.assertEqual('
XSS
', six.text_type(html | StyleSanitizer())) + self.assertEqual('
XSS
', str(html | StyleSanitizer())) input_str = u'
XSS
' html = HTML(input_str) - self.assertEqual(input_str, six.text_type(html | StyleSanitizer())) + self.assertEqual(input_str, str(html | StyleSanitizer())) def test_sanitize_unsafe_props(self): html = HTML(u'
XSS
') - self.assertEqual('
XSS
', six.text_type(html | StyleSanitizer())) + self.assertEqual('
XSS
', str(html | StyleSanitizer())) html = HTML(u'
XSS
') - self.assertEqual('
XSS
', six.text_type(html | StyleSanitizer())) + self.assertEqual('
XSS
', str(html | StyleSanitizer())) html = HTML(u'
' u'XSS
') - self.assertEqual('
XSS
', six.text_type(html | StyleSanitizer())) + self.assertEqual('
XSS
', str(html | StyleSanitizer())) html = HTML(u"""
XSS
""") - self.assertEqual('
XSS
', six.text_type(html | StyleSanitizer())) + self.assertEqual('
XSS
', str(html | StyleSanitizer())) html = HTML(u"""
XSS
""") - self.assertEqual('
XSS
', six.text_type(html | StyleSanitizer())) + self.assertEqual('
XSS
', str(html | StyleSanitizer())) def test_sanitize_negative_margin(self): html = HTML(u'
XSS
') - self.assertEqual('
XSS
', six.text_type(html | StyleSanitizer())) + self.assertEqual('
XSS
', str(html | StyleSanitizer())) html = HTML(u'
XSS
') - self.assertEqual('
XSS
', six.text_type(html | StyleSanitizer())) + self.assertEqual('
XSS
', str(html | StyleSanitizer())) def test_sanitize_css_hack(self): html = HTML(u'
XSS
') - self.assertEqual('
XSS
', six.text_type(html | StyleSanitizer())) + self.assertEqual('
XSS
', str(html | StyleSanitizer())) html = HTML(u'
XSS
') - self.assertEqual('
XSS
', six.text_type(html | StyleSanitizer())) + self.assertEqual('
XSS
', str(html | StyleSanitizer())) def test_sanitize_property_name(self): html = HTML(u'
prop
') self.assertEqual('
prop
', - six.text_type(html | StyleSanitizer())) + str(html | StyleSanitizer())) def test_sanitize_unicode_expression(self): # Fullwidth small letters html = HTML(u'
' u'XSS
') - self.assertEqual('
XSS
', six.text_type(html | StyleSanitizer())) + self.assertEqual('
XSS
', str(html | StyleSanitizer())) # Fullwidth capital letters html = HTML(u'
' u'XSS
') - self.assertEqual('
XSS
', six.text_type(html | StyleSanitizer())) + self.assertEqual('
XSS
', str(html | StyleSanitizer())) # IPA extensions html = HTML(u'
' u'XSS
') - self.assertEqual('
XSS
', six.text_type(html | StyleSanitizer())) + self.assertEqual('
XSS
', str(html | StyleSanitizer())) def test_sanitize_unicode_url(self): # IPA extensions html = HTML(u'
' u'XSS
') - self.assertEqual('
XSS
', six.text_type(html | StyleSanitizer())) + self.assertEqual('
XSS
', str(html | StyleSanitizer())) def suite(): Index: Genshi-0.7.9/genshi/filters/tests/transform.py =================================================================== --- Genshi-0.7.9.orig/genshi/filters/tests/transform.py 2024-06-16 01:52:43.000000000 +0200 +++ Genshi-0.7.9/genshi/filters/tests/transform.py 2025-05-09 08:30:16.090861554 +0200 @@ -14,7 +14,6 @@ import doctest import unittest -import six from genshi import HTML from genshi.builder import Element @@ -36,22 +35,22 @@ for mark, (kind, data, pos) in stream: if kind is START: if with_attrs: - kv_attrs = dict((six.text_type(k), v) for k, v in data[1]) - data = (six.text_type(data[0]), kv_attrs) + kv_attrs = dict((str(k), v) for k, v in data[1]) + data = (str(data[0]), kv_attrs) else: - data = six.text_type(data[0]) + data = str(data[0]) elif kind is END: - data = six.text_type(data) + data = str(data) elif kind is ATTR: kind = ATTR - data = dict((six.text_type(k), v) for k, v in data[1]) + data = dict((str(k), v) for k, v in data[1]) yield mark, kind, data return list(_generate()) def _transform(html, transformer, with_attrs=False): """Apply transformation returning simplified marked stream.""" - if isinstance(html, six.string_types): + if isinstance(html, str): html = HTML(html, encoding='utf-8') stream = transformer(html, keep_marks=True) return _simplify(stream, with_attrs) @@ -61,7 +60,7 @@ """Test .select()""" def _select(self, select): html = HTML(FOOBAR, encoding='utf-8') - if isinstance(select, six.string_types): + if isinstance(select, str): select = [select] transformer = Transformer(select[0]) for sel in select[1:]: @@ -668,7 +667,7 @@ html = HTML(html) if content is None: content = Injector() - elif isinstance(content, six.string_types): + elif isinstance(content, str): content = HTML(content) return _transform(html, getattr(Transformer(select), self.operation) (content)) Index: Genshi-0.7.9/genshi/filters/transform.py =================================================================== --- Genshi-0.7.9.orig/genshi/filters/transform.py 2024-06-16 01:52:43.000000000 +0200 +++ Genshi-0.7.9/genshi/filters/transform.py 2025-05-09 08:30:16.091146631 +0200 @@ -33,7 +33,7 @@ ... ... ''', ... encoding='utf-8') ->>> print(html | Transformer('body/em').map(six.text_type.upper, TEXT) +>>> print(html | Transformer('body/em').map(str.upper, TEXT) ... .unwrap().wrap(tag.u)) Some Title @@ -51,7 +51,6 @@ import re import sys -import six from genshi.builder import Element from genshi.core import Stream, Attrs, QName, TEXT, START, END, _ensure, Markup @@ -627,11 +626,10 @@ """Applies a function to the ``data`` element of events of ``kind`` in the selection. - >>> import six >>> html = HTML('Some Title' ... 'Some body text.', ... encoding='utf-8') - >>> print(html | Transformer('head/title').map(six.text_type.upper, TEXT)) + >>> print(html | Transformer('head/title').map(str.upper, TEXT)) SOME TITLESome body text. @@ -767,7 +765,7 @@ yield OUTSIDE, result elif result: # XXX Assume everything else is "text"? - yield None, (TEXT, six.text_type(result), (None, -1, -1)) + yield None, (TEXT, str(result), (None, -1, -1)) else: yield None, event @@ -993,7 +991,7 @@ :param replace: Replacement pattern. :param count: Number of replacements to make in each text fragment. """ - if isinstance(pattern, six.string_types): + if isinstance(pattern, str): self.pattern = re.compile(pattern) else: self.pattern = pattern Index: Genshi-0.7.9/genshi/input.py =================================================================== --- Genshi-0.7.9.orig/genshi/input.py 2024-06-16 01:52:43.000000000 +0200 +++ Genshi-0.7.9/genshi/input.py 2025-05-09 08:30:16.091399898 +0200 @@ -19,8 +19,8 @@ import codecs from xml.parsers import expat -import six -from six.moves import html_entities as entities, html_parser as html +import html.entities +import html.parser from genshi.core import Attrs, QName, Stream, stripentities from genshi.core import START, END, XML_DECL, DOCTYPE, TEXT, START_NS, \ @@ -92,7 +92,7 @@ """ _entitydefs = ['' % (name, value) for name, value in - entities.name2codepoint.items()] + html.entities.name2codepoint.items()] _external_dtd = u'\n'.join(_entitydefs).encode('utf-8') def __init__(self, source, filename=None, encoding=None): @@ -157,7 +157,7 @@ del self.expat # get rid of circular references done = True else: - if isinstance(data, six.text_type): + if isinstance(data, str): data = data.encode('utf-8') self.expat.Parse(data, False) for event in self._queue: @@ -243,7 +243,7 @@ if text.startswith('&'): # deal with undefined entities try: - text = six.unichr(entities.name2codepoint[text[1:-1]]) + text = chr(html.entities.name2codepoint[text[1:-1]]) self._enqueue(TEXT, text) except KeyError: filename, lineno, offset = self._getpos() @@ -276,7 +276,7 @@ return Stream(list(XMLParser(StringIO(text)))) -class HTMLParser(html.HTMLParser, object): +class HTMLParser(html.parser.HTMLParser, object): """Parser for HTML input based on the Python `HTMLParser` module. This class provides the same interface for generating stream events as @@ -305,7 +305,7 @@ :param filename: the name of the file, if known :param filename: encoding of the file; ignored if the input is unicode """ - html.HTMLParser.__init__(self) + html.parser.HTMLParser.__init__(self) self.source = source self.filename = filename self.encoding = encoding @@ -334,7 +334,7 @@ self.close() done = True else: - if not isinstance(data, six.text_type): + if not isinstance(data, str): raise UnicodeError("source returned bytes, but no encoding specified") self.feed(data) for kind, data, pos in self._queue: @@ -346,7 +346,7 @@ for tag in open_tags: yield END, QName(tag), pos break - except html.HTMLParseError as e: + except html.parser.HTMLParseError as e: msg = '%s: line %d, column %d' % (e.msg, e.lineno, e.offset) raise ParseError(msg, self.filename, e.lineno, e.offset) return Stream(_generate()).filter(_coalesce) @@ -389,14 +389,14 @@ def handle_charref(self, name): if name.lower().startswith('x'): - text = six.unichr(int(name[1:], 16)) + text = chr(int(name[1:], 16)) else: - text = six.unichr(int(name)) + text = chr(int(name)) self._enqueue(TEXT, text) def handle_entityref(self, name): try: - text = six.unichr(entities.name2codepoint[name]) + text = chr(html.entities.name2codepoint[name]) except KeyError: text = '&%s;' % name self._enqueue(TEXT, text) @@ -435,7 +435,7 @@ :raises ParseError: if the HTML text is not well-formed, and error recovery fails """ - if isinstance(text, six.text_type): + if isinstance(text, str): # If it's unicode text the encoding should be set to None. # The option to pass in an incorrect encoding is for ease # of writing doctests that work in both Python 2.x and 3.x. Index: Genshi-0.7.9/genshi/output.py =================================================================== --- Genshi-0.7.9.orig/genshi/output.py 2024-06-16 01:52:43.000000000 +0200 +++ Genshi-0.7.9/genshi/output.py 2025-05-09 08:30:16.091646863 +0200 @@ -18,7 +18,6 @@ from itertools import chain import re -import six from genshi.core import escape, Attrs, Markup, QName, StreamEventKind from genshi.core import START, END, TEXT, XML_DECL, DOCTYPE, START_NS, END_NS, \ @@ -73,7 +72,7 @@ :see: `XMLSerializer`, `XHTMLSerializer`, `HTMLSerializer`, `TextSerializer` :since: version 0.4.1 """ - if isinstance(method, six.string_types): + if isinstance(method, str): method = {'xml': XMLSerializer, 'xhtml': XHTMLSerializer, 'html': HTMLSerializer, @@ -583,7 +582,7 @@ data = event[1] if strip_markup and type(data) is Markup: data = data.striptags().stripentities() - yield six.text_type(data) + yield str(data) class EmptyTagFilter(object): @@ -825,7 +824,7 @@ :param doctype: DOCTYPE as a string or DocType object. """ - if isinstance(doctype, six.string_types): + if isinstance(doctype, str): doctype = DocType.get(doctype) self.doctype_event = (DOCTYPE, doctype, (None, -1, -1)) Index: Genshi-0.7.9/genshi/path.py =================================================================== --- Genshi-0.7.9.orig/genshi/path.py 2024-06-16 01:52:43.000000000 +0200 +++ Genshi-0.7.9/genshi/path.py 2025-05-09 08:30:16.092083005 +0200 @@ -45,7 +45,6 @@ import re from itertools import chain -import six from genshi.compat import IS_PYTHON2 from genshi.core import Stream, Attrs, Namespace, QName @@ -939,7 +938,7 @@ value = as_scalar(value) if value is False: return '' - return six.text_type(value) + return str(value) def as_bool(value): return bool(as_scalar(value)) Index: Genshi-0.7.9/genshi/template/base.py =================================================================== --- Genshi-0.7.9.orig/genshi/template/base.py 2024-06-16 01:52:43.000000000 +0200 +++ Genshi-0.7.9/genshi/template/base.py 2025-05-09 08:30:16.092500501 +0200 @@ -16,7 +16,6 @@ from collections import deque import os -import six from genshi.compat import numeric_types, StringIO, BytesIO from genshi.core import Attrs, Stream, StreamEventKind, START, TEXT, _ensure @@ -322,8 +321,7 @@ return type.__new__(cls, name, bases, d) -@six.add_metaclass(DirectiveFactoryMeta) -class DirectiveFactory(object): +class DirectiveFactory(metaclass=DirectiveFactoryMeta): """Base for classes that provide a set of template directives. :since: version 0.6 @@ -380,7 +378,7 @@ """ serializer = None - _number_conv = six.text_type # function used to convert numbers to event data + _number_conv = str # function used to convert numbers to event data def __init__(self, source, filepath=None, filename=None, loader=None, encoding=None, lookup='strict', allow_exec=True): @@ -412,7 +410,7 @@ self._prepared = False if not isinstance(source, Stream) and not hasattr(source, 'read'): - if isinstance(source, six.text_type): + if isinstance(source, str): source = StringIO(source) else: source = BytesIO(source) @@ -504,7 +502,7 @@ if kind is INCLUDE: href, cls, fallback = data tmpl_inlined = False - if (isinstance(href, six.string_types) and + if (isinstance(href, str) and not getattr(self.loader, 'auto_reload', True)): # If the path to the included template is static, and # auto-reloading is disabled on the template loader, @@ -603,7 +601,7 @@ # First check for a string, otherwise the iterable test # below succeeds, and the string will be chopped up into # individual characters - if isinstance(result, six.string_types): + if isinstance(result, str): yield TEXT, result, pos elif isinstance(result, numeric_types): yield TEXT, number_conv(result), pos @@ -612,7 +610,7 @@ stream = _ensure(result) break else: - yield TEXT, six.text_type(result), pos + yield TEXT, str(result), pos elif kind is SUB: # This event is a list of directives and a list of nested @@ -641,7 +639,7 @@ for event in stream: if event[0] is INCLUDE: href, cls, fallback = event[1] - if not isinstance(href, six.string_types): + if not isinstance(href, str): parts = [] for subkind, subdata, subpos in self._flatten(href, ctxt, **vars): Index: Genshi-0.7.9/genshi/template/directives.py =================================================================== --- Genshi-0.7.9.orig/genshi/template/directives.py 2024-06-16 01:52:43.000000000 +0200 +++ Genshi-0.7.9/genshi/template/directives.py 2025-05-09 08:30:16.092811998 +0200 @@ -13,7 +13,6 @@ """Implementation of the various template directives.""" -import six from genshi.core import QName, Stream from genshi.path import Path @@ -36,8 +35,7 @@ return type.__new__(cls, name, bases, d) -@six.add_metaclass(DirectiveMeta) -class Directive(object): +class Directive(metaclass=DirectiveMeta): """Abstract base class for template directives. A directive is basically a callable that takes three positional arguments: @@ -177,7 +175,7 @@ elif not isinstance(attrs, list): # assume it's a dict attrs = attrs.items() attrib |= [ - (QName(n), v is not None and six.text_type(v).strip() or None) + (QName(n), v is not None and str(v).strip() or None) for n, v in attrs ] yield kind, (tag, attrib), pos Index: Genshi-0.7.9/genshi/template/eval.py =================================================================== --- Genshi-0.7.9.orig/genshi/template/eval.py 2024-06-16 01:52:43.000000000 +0200 +++ Genshi-0.7.9/genshi/template/eval.py 2025-05-09 08:46:35.444265640 +0200 @@ -13,12 +13,10 @@ """Support for "safe" evaluation of Python expressions.""" +import builtins from textwrap import dedent from types import CodeType -import six -from six.moves import builtins - from genshi.core import Markup from genshi.template.astutil import ASTTransformer, ASTCodeGenerator, parse from genshi.template.base import TemplateRuntimeError @@ -53,7 +51,7 @@ if `None`, the appropriate transformation is chosen depending on the mode """ - if isinstance(source, six.string_types): + if isinstance(source, str): self.source = source node = _parse(source, mode=self.mode) else: @@ -72,7 +70,7 @@ filename=filename, lineno=lineno, xform=xform) if lookup is None: lookup = LenientLookup - elif isinstance(lookup, six.string_types): + elif isinstance(lookup, str): lookup = {'lenient': LenientLookup, 'strict': StrictLookup}[lookup] self._globals = lookup.globals @@ -178,7 +176,7 @@ """ __traceback_hide__ = 'before_and_this' _globals = self._globals(data) - six.exec_(self.code, _globals, data) + exec(self.code, _globals, data) UNDEFINED = object() @@ -317,7 +315,7 @@ try: return obj[key] except (AttributeError, KeyError, IndexError, TypeError) as e: - if isinstance(key, six.string_types): + if isinstance(key, str): val = getattr(obj, key, UNDEFINED) if val is UNDEFINED: val = cls.undefined(key, owner=obj) @@ -407,7 +405,7 @@ if first.rstrip().endswith(':') and not rest[0].isspace(): rest = '\n'.join([' %s' % line for line in rest.splitlines()]) source = '\n'.join([first, rest]) - if isinstance(source, six.text_type): + if isinstance(source, str): source = (u'\ufeff' + source).encode('utf-8') return parse(source, mode) @@ -418,11 +416,11 @@ filename = '' if IS_PYTHON2: # Python 2 requires non-unicode filenames - if isinstance(filename, six.text_type): + if isinstance(filename, str): filename = filename.encode('utf-8', 'replace') else: # Python 3 requires unicode filenames - if not isinstance(filename, six.text_type): + if not isinstance(filename, str): filename = filename.decode('utf-8', 'replace') if lineno <= 0: lineno = 1 @@ -510,7 +508,7 @@ return names def visit_Str(self, node): - if not isinstance(node.s, six.text_type): + if not isinstance(node.s, str): try: # If the string is ASCII, return a `str` object node.s.decode('ascii') except ValueError: # Otherwise return a `unicode` object Index: Genshi-0.7.9/genshi/template/loader.py =================================================================== --- Genshi-0.7.9.orig/genshi/template/loader.py 2024-06-16 01:52:43.000000000 +0200 +++ Genshi-0.7.9/genshi/template/loader.py 2025-05-09 08:30:16.093319313 +0200 @@ -19,7 +19,6 @@ except ImportError: import dummy_threading as threading -import six from genshi.template.base import TemplateError from genshi.util import LRUCache @@ -219,7 +218,7 @@ raise TemplateError('Search path for templates not configured') for loadfunc in search_path: - if isinstance(loadfunc, six.string_types): + if isinstance(loadfunc, str): loadfunc = directory(loadfunc) try: filepath, filename, fileobj, uptodate = loadfunc(filename) @@ -331,7 +330,7 @@ def _dispatch_by_prefix(filename): for prefix, delegate in delegates.items(): if filename.startswith(prefix): - if isinstance(delegate, six.string_types): + if isinstance(delegate, str): delegate = directory(delegate) filepath, _, fileobj, uptodate = delegate( filename[len(prefix):].lstrip('/\\') Index: Genshi-0.7.9/genshi/template/plugin.py =================================================================== --- Genshi-0.7.9.orig/genshi/template/plugin.py 2024-06-16 01:52:43.000000000 +0200 +++ Genshi-0.7.9/genshi/template/plugin.py 2025-05-09 08:30:16.093507047 +0200 @@ -16,7 +16,6 @@ CherryPy/Buffet. """ -import six from genshi.input import ET, HTML, XML from genshi.output import DocType @@ -48,7 +47,7 @@ self.default_encoding = options.get('genshi.default_encoding', None) auto_reload = options.get('genshi.auto_reload', '1') - if isinstance(auto_reload, six.string_types): + if isinstance(auto_reload, str): auto_reload = auto_reload.lower() in ('1', 'on', 'yes', 'true') search_path = [p for p in options.get('genshi.search_path', '').split(':') if p] @@ -170,7 +169,7 @@ options = {} new_syntax = options.get('genshi.new_text_syntax') - if isinstance(new_syntax, six.string_types): + if isinstance(new_syntax, str): new_syntax = new_syntax.lower() in ('1', 'on', 'yes', 'true') if new_syntax: self.template_class = NewTextTemplate Index: Genshi-0.7.9/genshi/template/tests/markup.py =================================================================== --- Genshi-0.7.9.orig/genshi/template/tests/markup.py 2024-06-16 01:52:43.000000000 +0200 +++ Genshi-0.7.9/genshi/template/tests/markup.py 2025-05-09 08:30:16.093698697 +0200 @@ -19,7 +19,6 @@ import tempfile import unittest -import six from genshi.compat import BytesIO, StringIO from genshi.core import Markup @@ -199,7 +198,7 @@ """.encode('iso-8859-1'), encoding='iso-8859-1') self.assertEqual(u"""\n
\xf6 -
""", six.text_type(tmpl.generate())) + """, str(tmpl.generate())) def test_latin1_encoded_explicit_encoding(self): tmpl = MarkupTemplate(u"""
@@ -207,7 +206,7 @@
""".encode('iso-8859-1'), encoding='iso-8859-1') self.assertEqual(u"""
\xf6 -
""", six.text_type(tmpl.generate())) + """, str(tmpl.generate())) def test_exec_with_trailing_space(self): """ Index: Genshi-0.7.9/genshi/template/text.py =================================================================== --- Genshi-0.7.9.orig/genshi/template/text.py 2024-06-16 01:52:43.000000000 +0200 +++ Genshi-0.7.9/genshi/template/text.py 2025-05-09 08:30:16.093948257 +0200 @@ -28,7 +28,6 @@ import re -import six from genshi.core import TEXT from genshi.template.base import BadDirectiveError, Template, \ @@ -163,7 +162,7 @@ depth = 0 source = source.read() - if not isinstance(source, six.text_type): + if not isinstance(source, str): source = source.decode(encoding or 'utf-8', 'replace') offset = 0 lineno = 1 @@ -280,7 +279,7 @@ depth = 0 source = source.read() - if not isinstance(source, six.text_type): + if not isinstance(source, str): source = source.decode(encoding or 'utf-8', 'replace') offset = 0 lineno = 1 Index: Genshi-0.7.9/genshi/util.py =================================================================== --- Genshi-0.7.9.orig/genshi/util.py 2024-06-16 01:52:43.000000000 +0200 +++ Genshi-0.7.9/genshi/util.py 2025-05-09 08:30:16.094135209 +0200 @@ -15,9 +15,8 @@ import re -from six.moves import html_entities as entities +import html.entities -import six __docformat__ = 'restructuredtext en' @@ -212,13 +211,13 @@ ref = int(ref[1:], 16) else: ref = int(ref, 10) - return six.unichr(ref) + return chr(ref) else: # character entity ref = match.group(2) if keepxmlentities and ref in ('amp', 'apos', 'gt', 'lt', 'quot'): return '&%s;' % ref try: - return six.unichr(entities.name2codepoint[ref]) + return chr(html.entities.name2codepoint[ref]) except KeyError: if keepxmlentities: return '&%s;' % ref Index: Genshi-0.7.9/setup.cfg =================================================================== --- Genshi-0.7.9.orig/setup.cfg 2024-06-16 01:52:56.000000000 +0200 +++ Genshi-0.7.9/setup.cfg 2025-05-09 08:30:26.396346827 +0200 @@ -39,8 +39,6 @@ genshi.filters.tests genshi.template.tests genshi.template.tests.templates -install_requires = - six setup_requires = setuptools