diff options
49 files changed, 292 insertions, 215 deletions
diff --git a/docutils/frontend.py b/docutils/frontend.py index 40ba90103..c21bd2c2d 100644 --- a/docutils/frontend.py +++ b/docutils/frontend.py @@ -193,7 +193,7 @@ def make_paths_absolute(pathdict, keys, base_path=None): if base_path is None: base_path = os.getcwd() for key in keys: - if pathdict.has_key(key): + if key in pathdict: value = pathdict[key] if isinstance(value, types.ListType): value = [make_one_path_absolute(base_path, path) @@ -225,7 +225,7 @@ class Values(optparse.Values): other_dict = other_dict.__dict__ other_dict = other_dict.copy() for setting in option_parser.lists.keys(): - if (hasattr(self, setting) and other_dict.has_key(setting)): + if (hasattr(self, setting) and setting in other_dict): value = getattr(self, setting) if value: value += other_dict[setting] @@ -585,7 +585,7 @@ class OptionParser(optparse.OptionParser, docutils.SettingsSpec): continue for section in (tuple(component.config_section_dependencies or ()) + (component.config_section,)): - if applied.has_key(section): + if section in applied: continue applied[section] = 1 settings.update(parser.get_section(section), self) @@ -699,7 +699,7 @@ Skipping "%s" configuration file. if not self.has_section('general'): self.add_section('general') for key, value in options.items(): - if self.old_settings.has_key(key): + if key in self.old_settings: section, setting = self.old_settings[key] if not self.has_section(section): self.add_section(section) diff --git a/docutils/languages/__init__.py b/docutils/languages/__init__.py index c721c0210..7d6521fc1 100644 --- a/docutils/languages/__init__.py +++ b/docutils/languages/__init__.py @@ -14,7 +14,7 @@ __docformat__ = 'reStructuredText' _languages = {} def get_language(language_code): - if _languages.has_key(language_code): + if language_code in _languages: return _languages[language_code] module = __import__(language_code, globals(), locals()) _languages[language_code] = module diff --git a/docutils/nodes.py b/docutils/nodes.py index 30050a121..816befd4d 100644 --- a/docutils/nodes.py +++ b/docutils/nodes.py @@ -27,7 +27,6 @@ import re import warnings from types import IntType, SliceType, StringType, UnicodeType, \ TupleType, ListType, ClassType, TypeType -from UserString import UserString # ============================== @@ -62,11 +61,7 @@ class Node: return 1 def __str__(self): - return self.__unicode__().encode('raw_unicode_escape') - - def __unicode__(self): - # Override in subclass. - raise NotImplementedError + return unicode(self).encode('raw_unicode_escape') def asdom(self, dom=None): """Return a DOM **fragment** representation of this Node.""" @@ -273,7 +268,15 @@ class Node: except IndexError: return None -class Text(Node, UserString): +class reprunicode(unicode): + """ + A class that removes the initial u from unicode's repr. + """ + + def __repr__(self): + return unicode.__repr__(self)[1:] + +class Text(Node, reprunicode): """ Instances are terminal nodes (leaves) containing text only; no child @@ -286,38 +289,44 @@ class Text(Node, UserString): children = () """Text nodes have no children, and cannot have children.""" + def __new__(cls, data, rawsource=None): + """Prevent the rawsource argument from propagating to str.""" + return reprunicode.__new__(cls, data) + def __init__(self, data, rawsource=''): - UserString.__init__(self, data) self.rawsource = rawsource """The raw text from which this element was constructed.""" def __repr__(self): - data = repr(self.data) + data = reprunicode.__repr__(self) if len(data) > 70: - data = repr(self.data[:64] + ' ...') + data = reprunicode.__repr__(self[:64] + ' ...') return '<%s: %s>' % (self.tagname, data) - def __len__(self): - return len(self.data) - def shortrepr(self): - data = repr(self.data) + data = reprunicode.__repr__(self) if len(data) > 20: - data = repr(self.data[:16] + ' ...') + data = reprunicode.__repr__(self[:16] + ' ...') return '<%s: %s>' % (self.tagname, data) def _dom_node(self, domroot): - return domroot.createTextNode(self.data) + return domroot.createTextNode(unicode(self)) def astext(self): - return self.data + return reprunicode(self) - def __unicode__(self): - return self.data + # Note about __unicode__: The implementation of __unicode__ here, + # and the one raising NotImplemented in the superclass Node had + # to be removed when changing Text to a subclass of unicode instead + # of UserString, since there is no way to delegate the __unicode__ + # call to the superclass unicode: + # unicode itself does not have __unicode__ method to delegate to + # and calling unicode(self) or unicode.__new__ directly creates + # an infinite loop def copy(self): - return self.__class__(self.data) + return self.__class__(reprunicode(self), rawsource=self.rawsource) def deepcopy(self): return self.copy() @@ -325,10 +334,19 @@ class Text(Node, UserString): def pformat(self, indent=' ', level=0): result = [] indent = indent * level - for line in self.data.splitlines(): + for line in self.splitlines(): result.append(indent + line + '\n') return ''.join(result) + # rstrip and lstrip are used by substitution definitions where + # they are expected to return a Text instance, this was formerly + # taken care of by UserString. Note that then and now the + # rawsource member is lost. + + def rstrip(self, chars=None): + return self.__class__(reprunicode.rstrip(self, chars)) + def lstrip(self, chars=None): + return self.__class__(reprunicode.lstrip(self, chars)) class Element(Node): @@ -539,10 +557,10 @@ class Element(Node): return self.attributes.get(key, failobj) def hasattr(self, attr): - return self.attributes.has_key(attr) + return attr in self.attributes def delattr(self, attr): - if self.attributes.has_key(attr): + if attr in self.attributes: del self.attributes[attr] def setdefault(self, key, failobj=None): @@ -933,18 +951,18 @@ class document(Root, Structural, Element): def set_id(self, node, msgnode=None): for id in node['ids']: - if self.ids.has_key(id) and self.ids[id] is not node: + if id in self.ids and self.ids[id] is not node: msg = self.reporter.severe('Duplicate ID: "%s".' % id) if msgnode != None: msgnode += msg if not node['ids']: for name in node['names']: id = self.settings.id_prefix + make_id(name) - if id and not self.ids.has_key(id): + if id and id not in self.ids: break else: id = '' - while not id or self.ids.has_key(id): + while not id or id in self.ids: id = (self.settings.id_prefix + self.settings.auto_id_prefix + str(self.id_start)) self.id_start += 1 @@ -985,7 +1003,7 @@ class document(Root, Structural, Element): The new target is invalidated regardless. """ for name in node['names']: - if self.nameids.has_key(name): + if name in self.nameids: self.set_duplicate_name_id(node, id, name, msgnode, explicit) else: self.nameids[name] = id @@ -1000,10 +1018,10 @@ class document(Root, Structural, Element): level = 2 if old_id is not None: old_node = self.ids[old_id] - if node.has_key('refuri'): + if 'refuri' in node: refuri = node['refuri'] if old_node['names'] \ - and old_node.has_key('refuri') \ + and 'refuri' in old_node \ and old_node['refuri'] == refuri: level = 1 # just inform if refuri's identical if level > 1: @@ -1034,7 +1052,7 @@ class document(Root, Structural, Element): msgnode += msg def has_name(self, name): - return self.nameids.has_key(name) + return name in self.nameids # "note" here is an imperative verb: "take note of". def note_implicit_target(self, target, msgnode=None): @@ -1094,7 +1112,7 @@ class document(Root, Structural, Element): def note_substitution_def(self, subdef, def_name, msgnode=None): name = whitespace_normalize_name(def_name) - if self.substitution_defs.has_key(name): + if name in self.substitution_defs: msg = self.reporter.error( 'Duplicate substitution definition name: "%s".' % name, base_node=subdef) diff --git a/docutils/parsers/__init__.py b/docutils/parsers/__init__.py index 125ab7674..2683376f9 100644 --- a/docutils/parsers/__init__.py +++ b/docutils/parsers/__init__.py @@ -41,7 +41,7 @@ _parser_aliases = { def get_parser_class(parser_name): """Return the Parser class from the `parser_name` module.""" parser_name = parser_name.lower() - if _parser_aliases.has_key(parser_name): + if parser_name in _parser_aliases: parser_name = _parser_aliases[parser_name] module = __import__(parser_name, globals(), locals()) return module.Parser diff --git a/docutils/parsers/rst/directives/__init__.py b/docutils/parsers/rst/directives/__init__.py index 14ac03a99..30da65ecd 100644 --- a/docutils/parsers/rst/directives/__init__.py +++ b/docutils/parsers/rst/directives/__init__.py @@ -76,7 +76,7 @@ def directive(directive_name, language_module, document): normname = directive_name.lower() messages = [] msg_text = [] - if _directives.has_key(normname): + if normname in _directives: return _directives[normname], messages canonicalname = None try: diff --git a/docutils/parsers/rst/directives/admonitions.py b/docutils/parsers/rst/directives/admonitions.py index bed3381b8..870b6659e 100644 --- a/docutils/parsers/rst/directives/admonitions.py +++ b/docutils/parsers/rst/directives/admonitions.py @@ -35,7 +35,7 @@ class BaseAdmonition(Directive): self.lineno) admonition_node += nodes.title(title_text, '', *textnodes) admonition_node += messages - if self.options.has_key('class'): + if 'class' in self.options: classes = self.options['class'] else: classes = ['admonition-' + nodes.make_id(title_text)] diff --git a/docutils/parsers/rst/directives/body.py b/docutils/parsers/rst/directives/body.py index 03c9c3fa6..0cc695726 100644 --- a/docutils/parsers/rst/directives/body.py +++ b/docutils/parsers/rst/directives/body.py @@ -39,7 +39,7 @@ class BasePseudoSection(Directive): textnodes, messages = self.state.inline_text(title_text, self.lineno) titles = [nodes.title(title_text, '', *textnodes)] # Sidebar uses this code. - if self.options.has_key('subtitle'): + if 'subtitle' in self.options: textnodes, more_messages = self.state.inline_text( self.options['subtitle'], self.lineno) titles.append(nodes.subtitle(self.options['subtitle'], '', diff --git a/docutils/parsers/rst/directives/images.py b/docutils/parsers/rst/directives/images.py index 96bdb3353..59323bba0 100644 --- a/docutils/parsers/rst/directives/images.py +++ b/docutils/parsers/rst/directives/images.py @@ -46,7 +46,7 @@ class Image(Directive): 'class': directives.class_option} def run(self): - if self.options.has_key('align'): + if 'align' in self.options: if isinstance(self.state, states.SubstitutionDef): # Check for align_v_values. if self.options['align'] not in self.align_v_values: @@ -66,7 +66,7 @@ class Image(Directive): reference = directives.uri(self.arguments[0]) self.options['uri'] = reference reference_node = None - if self.options.has_key('target'): + if 'target' in self.options: block = states.escape2null( self.options['target']).splitlines() block = [line for line in block] diff --git a/docutils/parsers/rst/directives/misc.py b/docutils/parsers/rst/directives/misc.py index 5d5d34729..89c8364c7 100644 --- a/docutils/parsers/rst/directives/misc.py +++ b/docutils/parsers/rst/directives/misc.py @@ -86,7 +86,7 @@ class Include(Directive): raise self.severe('Problem with "end-before" option of "%s" ' 'directive:\nText not found.' % self.name) include_text = include_text[:before_index] - if self.options.has_key('literal'): + if 'literal' in self.options: literal_block = nodes.literal_block(include_text, include_text, source=path) literal_block.line = 1 @@ -120,20 +120,20 @@ class Raw(Directive): def run(self): if (not self.state.document.settings.raw_enabled or (not self.state.document.settings.file_insertion_enabled - and (self.options.has_key('file') - or self.options.has_key('url')))): + and ('file' in self.options + or 'url' in self.options))): raise self.warning('"%s" directive disabled.' % self.name) attributes = {'format': ' '.join(self.arguments[0].lower().split())} encoding = self.options.get( 'encoding', self.state.document.settings.input_encoding) if self.content: - if self.options.has_key('file') or self.options.has_key('url'): + if 'file' in self.options or 'url' in self.options: raise self.error( '"%s" directive may not both specify an external file ' 'and have content.' % self.name) text = '\n'.join(self.content) - elif self.options.has_key('file'): - if self.options.has_key('url'): + elif 'file' in self.options: + if 'url' in self.options: raise self.error( 'The "file" and "url" options may not be simultaneously ' 'specified for the "%s" directive.' % self.name) @@ -159,7 +159,7 @@ class Raw(Directive): 'Problem with "%s" directive:\n%s: %s' % (self.name, error.__class__.__name__, error)) attributes['source'] = path - elif self.options.has_key('url'): + elif 'url' in self.options: source = self.options['url'] # Do not import urllib2 at the top of the module because # it may fail due to broken SSL dependencies, and it takes @@ -244,12 +244,12 @@ class Unicode(Directive): 'Invalid context: the "%s" directive can only be used within ' 'a substitution definition.' % self.name) substitution_definition = self.state_machine.node - if self.options.has_key('trim'): + if 'trim' in self.options: substitution_definition.attributes['ltrim'] = 1 substitution_definition.attributes['rtrim'] = 1 - if self.options.has_key('ltrim'): + if 'ltrim' in self.options: substitution_definition.attributes['ltrim'] = 1 - if self.options.has_key('rtrim'): + if 'rtrim' in self.options: substitution_definition.attributes['rtrim'] = 1 codes = self.comment_pattern.split(self.arguments[0])[0].split() element = nodes.Element() @@ -349,7 +349,7 @@ class Role(Directive): nodes.literal_block(self.block_text, self.block_text), line=self.lineno) return messages + [error] - if not options.has_key('class'): + if 'class' not in options: try: options['class'] = directives.class_option(new_role_name) except ValueError, detail: @@ -373,7 +373,7 @@ class DefaultRole(Directive): def run(self): if not self.arguments: - if roles._roles.has_key(''): + if '' in roles._roles: # restore the "default" default role del roles._roles[''] return [] diff --git a/docutils/parsers/rst/directives/parts.py b/docutils/parsers/rst/directives/parts.py index da1586275..6ef8c905c 100644 --- a/docutils/parsers/rst/directives/parts.py +++ b/docutils/parsers/rst/directives/parts.py @@ -57,13 +57,13 @@ class Contents(Directive): title = nodes.title(title_text, '', *text_nodes) else: messages = [] - if self.options.has_key('local'): + if 'local' in self.options: title = None else: title = nodes.title('', language.labels['contents']) topic = nodes.topic(classes=['contents']) topic['classes'] += self.options.get('class', []) - if self.options.has_key('local'): + if 'local' in self.options: topic['classes'].append('local') if title: name = title.astext() diff --git a/docutils/parsers/rst/directives/tables.py b/docutils/parsers/rst/directives/tables.py index 639ce8d1f..5527c9f0b 100644 --- a/docutils/parsers/rst/directives/tables.py +++ b/docutils/parsers/rst/directives/tables.py @@ -49,7 +49,7 @@ class Table(Directive): source = self.state_machine.get_source(self.lineno - 1) table_head = [] max_header_cols = 0 - if self.options.has_key('header'): # separate table header in option + if 'header' in self.options: # separate table header in option rows, max_header_cols = self.parse_csv_data_into_rows( self.options['header'].split('\n'), self.HeaderDialect(), source) @@ -88,7 +88,7 @@ class Table(Directive): raise SystemMessagePropagation(error) def get_column_widths(self, max_cols): - if self.options.has_key('widths'): + if 'widths' in self.options: col_widths = self.options['widths'] if len(col_widths) != max_cols: error = self.state_machine.reporter.error( @@ -170,13 +170,13 @@ class CSVTable(Table): quoting = csv.QUOTE_MINIMAL def __init__(self, options): - if options.has_key('delim'): + if 'delim' in options: self.delimiter = str(options['delim']) - if options.has_key('keepspace'): + if 'keepspace' in options: self.skipinitialspace = False - if options.has_key('quote'): + if 'quote' in options: self.quotechar = str(options['quote']) - if options.has_key('escape'): + if 'escape' in options: self.doublequote = False self.escapechar = str(options['escape']) csv.Dialect.__init__(self) @@ -206,8 +206,8 @@ class CSVTable(Table): def run(self): try: if (not self.state.document.settings.file_insertion_enabled - and (self.options.has_key('file') - or self.options.has_key('url'))): + and ('file' in self.options + or 'url' in self.options)): warning = self.state_machine.reporter.warning( 'File and URL access deactivated; ignoring "%s" ' 'directive.' % self.name, nodes.literal_block( @@ -253,7 +253,7 @@ class CSVTable(Table): 'encoding', self.state.document.settings.input_encoding) if self.content: # CSV data is from directive content. - if self.options.has_key('file') or self.options.has_key('url'): + if 'file' in self.options or 'url' in self.options: error = self.state_machine.reporter.error( '"%s" directive may not both specify an external file and' ' have content.' % self.name, nodes.literal_block( @@ -261,9 +261,9 @@ class CSVTable(Table): raise SystemMessagePropagation(error) source = self.content.source(0) csv_data = self.content - elif self.options.has_key('file'): + elif 'file' in self.options: # CSV data is from an external file. - if self.options.has_key('url'): + if 'url' in self.options: error = self.state_machine.reporter.error( 'The "file" and "url" options may not be simultaneously' ' specified for the "%s" directive.' % self.name, @@ -289,7 +289,7 @@ class CSVTable(Table): % (self.name, error), nodes.literal_block( self.block_text, self.block_text), line=self.lineno) raise SystemMessagePropagation(severe) - elif self.options.has_key('url'): + elif 'url' in self.options: # CSV data is from a URL. # Do not import urllib2 at the top of the module because # it may fail due to broken SSL dependencies, and it takes diff --git a/docutils/parsers/rst/languages/__init__.py b/docutils/parsers/rst/languages/__init__.py index 18c884748..962802245 100644 --- a/docutils/parsers/rst/languages/__init__.py +++ b/docutils/parsers/rst/languages/__init__.py @@ -15,7 +15,7 @@ __docformat__ = 'reStructuredText' _languages = {} def get_language(language_code): - if _languages.has_key(language_code): + if language_code in _languages: return _languages[language_code] try: module = __import__(language_code, globals(), locals()) diff --git a/docutils/parsers/rst/roles.py b/docutils/parsers/rst/roles.py index 1da1395e9..062d53e50 100644 --- a/docutils/parsers/rst/roles.py +++ b/docutils/parsers/rst/roles.py @@ -101,7 +101,7 @@ def role(role_name, language_module, lineno, reporter): messages = [] msg_text = [] - if _roles.has_key(normname): + if normname in _roles: return _roles[normname], messages if role_name: @@ -135,7 +135,7 @@ def role(role_name, language_module, lineno, reporter): messages.append(message) # Look the role up in the registry, and return it. - if _role_registry.has_key(canonicalname): + if canonicalname in _role_registry: role_fn = _role_registry[canonicalname] register_local_role(normname, role_fn) return role_fn, messages @@ -171,7 +171,7 @@ def set_implicit_options(role_fn): """ if not hasattr(role_fn, 'options') or role_fn.options is None: role_fn.options = {'class': directives.class_option} - elif not role_fn.options.has_key('class'): + elif 'class' not in role_fn.options: role_fn.options['class'] = directives.class_option def register_generic_role(canonical_name, node_class): @@ -294,7 +294,7 @@ def rfc_reference_role(role, rawtext, text, lineno, inliner, register_canonical_role('rfc-reference', rfc_reference_role) def raw_role(role, rawtext, text, lineno, inliner, options={}, content=[]): - if not options.has_key('format'): + if 'format' not in options: msg = inliner.reporter.error( 'No format (Writer name) is associated with this role: "%s".\n' 'The "raw" role cannot be used directly.\n' @@ -340,7 +340,7 @@ def set_classes(options): Auxiliary function to set options['classes'] and delete options['class']. """ - if options.has_key('class'): - assert not options.has_key('classes') + if 'class' in options: + assert 'classes' not in options options['classes'] = options['class'] del options['class'] diff --git a/docutils/parsers/rst/states.py b/docutils/parsers/rst/states.py index eabc179ef..d5efb20e5 100644 --- a/docutils/parsers/rst/states.py +++ b/docutils/parsers/rst/states.py @@ -901,8 +901,8 @@ class Inliner: return self.reference(match, lineno, anonymous=1) def standalone_uri(self, match, lineno): - if not match.group('scheme') or urischemes.schemes.has_key( - match.group('scheme').lower()): + if (not match.group('scheme') + or match.group('scheme').lower() in urischemes.schemes): if match.group('email'): addscheme = 'mailto:' else: @@ -2249,7 +2249,8 @@ class Body(RSTState): if expmatch: try: return method(self, expmatch) - except MarkupError, (message, lineno): # never reached? + except MarkupError, error: # never reached? + message, lineno = error.args errors.append(self.reporter.warning(message, line=lineno)) break nodelist, blank_finish = self.comment(match) diff --git a/docutils/readers/__init__.py b/docutils/readers/__init__.py index 74db893f9..a28248f70 100644 --- a/docutils/readers/__init__.py +++ b/docutils/readers/__init__.py @@ -101,7 +101,7 @@ _reader_aliases = {} def get_reader_class(reader_name): """Return the Reader class from the `reader_name` module.""" reader_name = reader_name.lower() - if _reader_aliases.has_key(reader_name): + if reader_name in _reader_aliases: reader_name = _reader_aliases[reader_name] module = __import__(reader_name, globals(), locals()) return module.Reader diff --git a/docutils/readers/python/__init__.py b/docutils/readers/python/__init__.py index da8fb22d2..eac284a7e 100644 --- a/docutils/readers/python/__init__.py +++ b/docutils/readers/python/__init__.py @@ -94,7 +94,7 @@ class DocstringFormattingVisitor(nodes.SparseNodeVisitor): visitation, so parser instances are cached. """ parser_name = parsers._parser_aliases.get(parser_name, parser_name) - if not self.parsers.has_key(parser_name): + if parser_name not in self.parsers: cls = parsers.get_parser_class(parser_name) self.parsers[parser_name] = cls() return self.parsers[parser_name] diff --git a/docutils/readers/python/moduleparser.py b/docutils/readers/python/moduleparser.py index e874ee204..fadb3586b 100644 --- a/docutils/readers/python/moduleparser.py +++ b/docutils/readers/python/moduleparser.py @@ -525,14 +525,14 @@ class TokenParser: def note_token(self): if self.type == tokenize.NL: return - del_ws = self.del_ws_prefix.has_key(self.string) - append_ws = not self.no_ws_suffix.has_key(self.string) - if self.openers.has_key(self.string): + del_ws = self.string in self.del_ws_prefix + append_ws = self.string not in self.no_ws_suffix + if self.string in self.openers: self.stack.append(self.string) if (self._type == token.NAME - or self.closers.has_key(self._string)): + or self._string in self.closers): del_ws = 1 - elif self.closers.has_key(self.string): + elif self.string in self.closers: assert self.stack[-1] == self.closers[self.string] self.stack.pop() elif self.string == '`': diff --git a/docutils/statemachine.py b/docutils/statemachine.py index 514e5dbd1..c29f128a7 100644 --- a/docutils/statemachine.py +++ b/docutils/statemachine.py @@ -377,7 +377,7 @@ class StateMachine: self.next_line(len(block) - 1) return block except UnexpectedIndentationError, error: - block, source, lineno = error + block, source, lineno = error.args self.next_line(len(block) - 1) # advance to last line of block raise @@ -441,7 +441,7 @@ class StateMachine: added. """ statename = state_class.__name__ - if self.states.has_key(statename): + if statename in self.states: raise DuplicateStateError(statename) self.states[statename] = state_class(self, self.debug) @@ -629,9 +629,9 @@ class State: Exceptions: `DuplicateTransitionError`, `UnknownTransitionError`. """ for name in names: - if self.transitions.has_key(name): + if name in self.transitions: raise DuplicateTransitionError(name) - if not transitions.has_key(name): + if name not in transitions: raise UnknownTransitionError(name) self.transition_order[:0] = names self.transitions.update(transitions) @@ -644,7 +644,7 @@ class State: Exception: `DuplicateTransitionError`. """ - if self.transitions.has_key(name): + if name in self.transitions: raise DuplicateTransitionError(name) self.transition_order[:0] = [name] self.transitions[name] = transition diff --git a/docutils/transforms/frontmatter.py b/docutils/transforms/frontmatter.py index eae149a44..cd537f910 100644 --- a/docutils/transforms/frontmatter.py +++ b/docutils/transforms/frontmatter.py @@ -388,7 +388,7 @@ class DocInfo(Transform): try: name = field[0][0].astext() normedname = nodes.fully_normalize_name(name) - if not (len(field) == 2 and bibliofields.has_key(normedname) + if not (len(field) == 2 and normedname in bibliofields and self.check_empty_biblio_field(field, name)): raise TransformError canonical = bibliofields[normedname] diff --git a/docutils/transforms/parts.py b/docutils/transforms/parts.py index 39cb74f75..26fcdb684 100644 --- a/docutils/transforms/parts.py +++ b/docutils/transforms/parts.py @@ -80,7 +80,7 @@ class Contents(Transform): def apply(self): details = self.startnode.details - if details.has_key('local'): + if 'local' in details: startnode = self.startnode.parent.parent while not (isinstance(startnode, nodes.section) or isinstance(startnode, nodes.document)): @@ -89,7 +89,7 @@ class Contents(Transform): else: startnode = self.document self.toc_id = self.startnode.parent['ids'][0] - if details.has_key('backlinks'): + if 'backlinks' in details: self.backlinks = details['backlinks'] else: self.backlinks = self.document.settings.toc_backlinks diff --git a/docutils/transforms/references.py b/docutils/transforms/references.py index 097877ee9..c45fdb0da 100644 --- a/docutils/transforms/references.py +++ b/docutils/transforms/references.py @@ -240,7 +240,7 @@ class IndirectHyperlinks(Transform): del target.multiply_indirect if reftarget.hasattr('refuri'): target['refuri'] = reftarget['refuri'] - if target.has_key('refid'): + if 'refid' in target: del target['refid'] elif reftarget.hasattr('refid'): target['refid'] = reftarget['refid'] @@ -257,7 +257,7 @@ class IndirectHyperlinks(Transform): target.resolved = 1 def nonexistent_indirect_target(self, target): - if self.document.nameids.has_key(target['refname']): + if target['refname'] in self.document.nameids: self.indirect_target_error(target, 'which is a duplicate, and ' 'cannot be used as a unique reference') else: @@ -505,7 +505,7 @@ class Footnotes(Transform): while 1: label = str(startnum) startnum += 1 - if not self.document.nameids.has_key(label): + if label not in self.document.nameids: break footnote.insert(0, nodes.label('', label)) for name in footnote['names']: @@ -600,12 +600,12 @@ class Footnotes(Transform): """ for footnote in self.document.footnotes: for label in footnote['names']: - if self.document.footnote_refs.has_key(label): + if label in self.document.footnote_refs: reflist = self.document.footnote_refs[label] self.resolve_references(footnote, reflist) for citation in self.document.citations: for label in citation['names']: - if self.document.citation_refs.has_key(label): + if label in self.document.citation_refs: reflist = self.document.citation_refs[label] self.resolve_references(citation, reflist) @@ -666,11 +666,11 @@ class Substitutions(Transform): for ref in subreflist: refname = ref['refname'] key = None - if defs.has_key(refname): + if refname in defs: key = refname else: normed_name = refname.lower() - if normed.has_key(normed_name): + if normed_name in normed: key = normed[normed_name] if key is None: msg = self.document.reporter.error( @@ -686,14 +686,14 @@ class Substitutions(Transform): subdef = defs[key] parent = ref.parent index = parent.index(ref) - if (subdef.attributes.has_key('ltrim') - or subdef.attributes.has_key('trim')): + if ('ltrim' in subdef.attributes + or 'trim' in subdef.attributes): if index > 0 and isinstance(parent[index - 1], nodes.Text): parent.replace(parent[index - 1], parent[index - 1].rstrip()) - if (subdef.attributes.has_key('rtrim') - or subdef.attributes.has_key('trim')): + if ('rtrim' in subdef.attributes + or 'trim' in subdef.attributes): if (len(parent) > index + 1 and isinstance(parent[index + 1], nodes.Text)): parent.replace(parent[index + 1], @@ -764,7 +764,7 @@ class TargetNotes(Transform): continue footnote = self.make_target_footnote(target['refuri'], refs, notes) - if not notes.has_key(target['refuri']): + if target['refuri'] not in notes: notes[target['refuri']] = footnote nodelist.append(footnote) # Take care of anonymous references. @@ -774,13 +774,13 @@ class TargetNotes(Transform): if ref.hasattr('refuri'): footnote = self.make_target_footnote(ref['refuri'], [ref], notes) - if not notes.has_key(ref['refuri']): + if ref['refuri'] not in notes: notes[ref['refuri']] = footnote nodelist.append(footnote) self.startnode.replace_self(nodelist) def make_target_footnote(self, refuri, refs, notes): - if notes.has_key(refuri): # duplicate? + if refuri in notes: # duplicate? footnote = notes[refuri] assert len(footnote['names']) == 1 footnote_name = footnote['names'][0] @@ -873,7 +873,7 @@ class DanglingReferencesVisitor(nodes.SparseNodeVisitor): if resolver_function(node): break else: - if self.document.nameids.has_key(refname): + if refname in self.document.nameids: msg = self.document.reporter.error( 'Duplicate target name, cannot be used as a unique ' 'reference: "%s".' % (node['refname']), base_node=node) diff --git a/docutils/utils.py b/docutils/utils.py index 456f3eed9..b88ffbbc1 100644 --- a/docutils/utils.py +++ b/docutils/utils.py @@ -161,7 +161,7 @@ class Reporter: Raise an exception or generate a warning if appropriate. """ attributes = kwargs.copy() - if kwargs.has_key('base_node'): + if 'base_node' in kwargs: source, line = get_source_line(kwargs['base_node']) del attributes['base_node'] if source is not None: @@ -308,7 +308,7 @@ def assemble_option_dict(option_list, options_spec): convertor = options_spec[name] # raises KeyError if unknown if convertor is None: raise KeyError(name) # or if explicitly disabled - if options.has_key(name): + if name in options: raise DuplicateOptionError('duplicate option "%s"' % name) try: options[name] = convertor(value) @@ -404,9 +404,9 @@ def clean_rcs_keywords(paragraph, keyword_substitutions): if len(paragraph) == 1 and isinstance(paragraph[0], nodes.Text): textnode = paragraph[0] for pattern, substitution in keyword_substitutions: - match = pattern.search(textnode.data) + match = pattern.search(textnode) if match: - textnode.data = pattern.sub(substitution, textnode.data) + paragraph[0] = nodes.Text(pattern.sub(substitution, textnode)) return def relative_path(source, target): diff --git a/docutils/writers/__init__.py b/docutils/writers/__init__.py index 39e1ecd5b..8e3bd1aaa 100644 --- a/docutils/writers/__init__.py +++ b/docutils/writers/__init__.py @@ -127,7 +127,7 @@ _writer_aliases = { def get_writer_class(writer_name): """Return the Writer class from the `writer_name` module.""" writer_name = writer_name.lower() - if _writer_aliases.has_key(writer_name): + if writer_name in _writer_aliases: writer_name = _writer_aliases[writer_name] module = __import__(writer_name, globals(), locals()) return module.Writer diff --git a/docutils/writers/html4css1/__init__.py b/docutils/writers/html4css1/__init__.py index 634a74d1d..57d2c6ef0 100644 --- a/docutils/writers/html4css1/__init__.py +++ b/docutils/writers/html4css1/__init__.py @@ -353,13 +353,13 @@ class HTMLTranslator(nodes.NodeVisitor): for (name, value) in attributes.items(): atts[name.lower()] = value classes = node.get('classes', []) - if atts.has_key('class'): + if 'class' in atts: classes.append(atts['class']) if classes: atts['class'] = ' '.join(classes) - assert not atts.has_key('id') + assert 'id' not in atts ids.extend(node.get('ids', [])) - if atts.has_key('ids'): + if 'ids' in atts: ids.extend(atts['ids']) del atts['ids'] if ids: @@ -731,9 +731,9 @@ class HTMLTranslator(nodes.NodeVisitor): tagname = 'td' del atts['class'] node.parent.column += 1 - if node.has_key('morerows'): + if 'morerows' in node: atts['rowspan'] = node['morerows'] + 1 - if node.has_key('morecols'): + if 'morecols' in node: atts['colspan'] = node['morecols'] + 1 node.parent.column += node['morecols'] self.body.append(self.starttag(node, tagname, '', **atts)) @@ -752,9 +752,9 @@ class HTMLTranslator(nodes.NodeVisitor): usable. """ atts = {} - if node.has_key('start'): + if 'start' in node: atts['start'] = node['start'] - if node.has_key('enumtype'): + if 'enumtype' in node: atts['class'] = node['enumtype'] # @@@ To do: prefix, suffix. How? Change prefix/suffix to a # single "format" attribute? Use CSS2? @@ -941,26 +941,26 @@ class HTMLTranslator(nodes.NodeVisitor): def visit_image(self, node): atts = {} atts['src'] = node['uri'] - if node.has_key('width'): + if 'width' in node: atts['width'] = node['width'] - if node.has_key('height'): + if 'height' in node: atts['height'] = node['height'] - if node.has_key('scale'): - if Image and not (node.has_key('width') - and node.has_key('height')): + if 'scale' in node: + if Image and not ('width' in node + and 'height' in node): try: im = Image.open(str(atts['src'])) except (IOError, # Source image can't be found or opened UnicodeError): # PIL doesn't like Unicode paths. pass else: - if not atts.has_key('width'): + if 'width' not in atts: atts['width'] = str(im.size[0]) - if not atts.has_key('height'): + if 'height' not in atts: atts['height'] = str(im.size[1]) del im for att_name in 'width', 'height': - if atts.has_key(att_name): + if att_name in atts: match = re.match(r'([0-9.]+)(\S*)$', atts[att_name]) assert match atts[att_name] = '%s%s' % ( @@ -968,7 +968,7 @@ class HTMLTranslator(nodes.NodeVisitor): match.group(2)) style = [] for att_name in 'width', 'height': - if atts.has_key(att_name): + if att_name in atts: if re.match(r'^[0-9.]+$', atts[att_name]): # Interpret unitless values as pixels. atts[att_name] += 'px' @@ -984,7 +984,7 @@ class HTMLTranslator(nodes.NodeVisitor): suffix = '' else: suffix = '\n' - if node.has_key('align'): + if 'align' in node: if node['align'] == 'center': # "align" attribute is set in surrounding "div" element. self.body.append('<div align="center" class="align-center">') @@ -1210,7 +1210,7 @@ class HTMLTranslator(nodes.NodeVisitor): def visit_reference(self, node): atts = {'class': 'reference'} - if node.has_key('refuri'): + if 'refuri' in node: atts['href'] = node['refuri'] if ( self.settings.cloak_email_addresses and atts['href'].startswith('mailto:')): @@ -1218,7 +1218,7 @@ class HTMLTranslator(nodes.NodeVisitor): self.in_mailto = 1 atts['class'] += ' external' else: - assert node.has_key('refid'), \ + assert 'refid' in node, \ 'References must have "refuri" or "refid" attribute.' atts['href'] = '#' + node['refid'] atts['class'] += ' internal' @@ -1364,8 +1364,8 @@ class HTMLTranslator(nodes.NodeVisitor): self.body.append('</table>\n') def visit_target(self, node): - if not (node.has_key('refuri') or node.has_key('refid') - or node.has_key('refname')): + if not ('refuri' in node or 'refid' in node + or 'refname' in node): self.body.append(self.starttag(node, 'span', '', CLASS='target')) self.context.append('</span>') else: diff --git a/docutils/writers/latex2e/__init__.py b/docutils/writers/latex2e/__init__.py index a4245a173..70a158b64 100644 --- a/docutils/writers/latex2e/__init__.py +++ b/docutils/writers/latex2e/__init__.py @@ -1124,9 +1124,9 @@ class LaTeXTranslator(nodes.NodeVisitor): self.inside_citation_reference_label = 1 else: href = '' - if node.has_key('refid'): + if 'refid' in node: href = node['refid'] - elif node.has_key('refname'): + elif 'refname' in node: href = self.document.nameids[node['refname']] self.body.append('[\\hyperlink{%s}{' % href) @@ -1343,17 +1343,17 @@ class LaTeXTranslator(nodes.NodeVisitor): # IN WORK BUG TODO HACK continues here # multirow in LaTeX simply will enlarge the cell over several rows # (the following n if n is positive, the former if negative). - if node.has_key('morerows') and node.has_key('morecols'): + if 'morerows' in node and 'morecols' in node: raise NotImplementedError('Cells that ' 'span multiple rows *and* columns are not supported, sorry.') - if node.has_key('morerows'): + if 'morerows' in node: count = node['morerows'] + 1 self.active_table.set_rowspan(self.active_table.get_entry_number()-1,count) self.body.append('\\multirow{%d}{%s}{' % \ (count,self.active_table.get_column_width())) self.context.append('}') # BUG following rows must have empty cells. - elif node.has_key('morecols'): + elif 'morecols' in node: # the vertical bar before column is missing if it is the first column. # the one after always. if self.active_table.get_entry_number() == 1: @@ -1401,10 +1401,10 @@ class LaTeXTranslator(nodes.NodeVisitor): 'lowerroman':'roman', 'upperroman':'Roman' } enum_suffix = "" - if node.has_key('suffix'): + if 'suffix' in node: enum_suffix = node['suffix'] enum_prefix = "" - if node.has_key('prefix'): + if 'prefix' in node: enum_prefix = node['prefix'] if self.compound_enumerators: pref = "" @@ -1416,7 +1416,7 @@ class LaTeXTranslator(nodes.NodeVisitor): for ctype, cname in self._enumeration_counters: enum_prefix += '\\%s{%s}.' % (ctype, cname) enum_type = "arabic" - if node.has_key('enumtype'): + if 'enumtype' in node: enum_type = node['enumtype'] if enum_type in enum_style: enum_type = enum_style[enum_type] @@ -1436,7 +1436,7 @@ class LaTeXTranslator(nodes.NodeVisitor): self.body.append('{\n') self.body.append('\\usecounter{%s}\n' % counter_name) # set start after usecounter, because it initializes to zero. - if node.has_key('start'): + if 'start' in node: self.body.append('\\addtocounter{%s}{%d}\n' \ % (counter_name,node['start']-1)) ## set rightmargin equal to leftmargin @@ -1500,7 +1500,7 @@ class LaTeXTranslator(nodes.NodeVisitor): self.body.append(':]') def visit_figure(self, node): - if (not node.attributes.has_key('align') or + if ('align' not in node.attributes or node.attributes['align'] == 'center'): # centering does not add vertical space like center. align = '\n\\centering' @@ -1547,9 +1547,9 @@ class LaTeXTranslator(nodes.NodeVisitor): self.body.append("\\footnotemark["+self.encode(node.astext())+"]") raise nodes.SkipNode href = '' - if node.has_key('refid'): + if 'refid' in node: href = node['refid'] - elif node.has_key('refname'): + elif 'refname' in node: href = self.document.nameids[node['refname']] format = self.settings.footnote_references if format == 'brackets': @@ -1633,18 +1633,18 @@ class LaTeXTranslator(nodes.NodeVisitor): post = [] include_graphics_options = [] inline = isinstance(node.parent, nodes.TextElement) - if attrs.has_key('scale'): + if 'scale' in attrs: # Could also be done with ``scale`` option to # ``\includegraphics``; doing it this way for consistency. pre.append('\\scalebox{%f}{' % (attrs['scale'] / 100.0,)) post.append('}') - if attrs.has_key('width'): + if 'width' in attrs: include_graphics_options.append('width=%s' % ( self.latex_image_length(attrs['width']), )) - if attrs.has_key('height'): + if 'height' in attrs: include_graphics_options.append('height=%s' % ( self.latex_image_length(attrs['height']), )) - if attrs.has_key('align'): + if 'align' in attrs: align_prepost = { # By default latex aligns the top of an image. (1, 'top'): ('', ''), @@ -1870,16 +1870,16 @@ class LaTeXTranslator(nodes.NodeVisitor): # BUG: hash_char "#" is trouble some in LaTeX. # mbox and other environment do not like the '#'. hash_char = '\\#' - if node.has_key('refuri'): + if 'refuri' in node: href = node['refuri'].replace('#',hash_char) - elif node.has_key('refid'): + elif 'refid' in node: href = hash_char + node['refid'] - elif node.has_key('refname'): + elif 'refname' in node: href = hash_char + self.document.nameids[node['refname']] else: raise AssertionError('Unknown reference.') self.body.append('\\href{%s}{' % href.replace("%", "\\%")) - if self._reference_label and not node.has_key('refuri'): + if self._reference_label and 'refuri' not in node: self.body.append('\\%s{%s}}' % (self._reference_label, href.replace(hash_char, ''))) raise nodes.SkipNode @@ -1993,8 +1993,8 @@ class LaTeXTranslator(nodes.NodeVisitor): def visit_target(self, node): # BUG: why not (refuri or refid or refname) means not footnote ? - if not (node.has_key('refuri') or node.has_key('refid') - or node.has_key('refname')): + if not ('refuri' in node or 'refid' in node + or 'refname' in node): for id in node['ids']: self.body.append('\\hypertarget{%s}{' % id) self.context.append('}' * len(node['ids'])) diff --git a/docutils/writers/newlatex2e/__init__.py b/docutils/writers/newlatex2e/__init__.py index 8c360876e..2830fd556 100644 --- a/docutils/writers/newlatex2e/__init__.py +++ b/docutils/writers/newlatex2e/__init__.py @@ -676,7 +676,7 @@ class LaTeXTranslator(nodes.SparseNodeVisitor): # Move IDs into TextElements. This won't work for images. # Need to review this. for node in document.traverse(nodes.Element): - if node.has_key('ids') and not isinstance(node, + if 'ids' in node and not isinstance(node, nodes.TextElement): next_text_element = node.next_node(nodes.TextElement) if next_text_element: diff --git a/docutils/writers/s5_html/__init__.py b/docutils/writers/s5_html/__init__.py index 486c03f4a..73a1ec66f 100644 --- a/docutils/writers/s5_html/__init__.py +++ b/docutils/writers/s5_html/__init__.py @@ -251,7 +251,7 @@ class S5HTMLTranslator(html4css1.HTMLTranslator): """ source = os.path.join(source_dir, name) dest = os.path.join(dest_dir, name) - if self.theme_files_copied.has_key(dest): + if dest in self.theme_files_copied: return 1 else: self.theme_files_copied[dest] = 1 diff --git a/extras/optparse.py b/extras/optparse.py index c21663c55..dcc36fd84 100644 --- a/extras/optparse.py +++ b/extras/optparse.py @@ -472,7 +472,7 @@ class Option: def _set_attrs (self, attrs): for attr in self.ATTRS: - if attrs.has_key(attr): + if attr in attrs: setattr(self, attr, attrs[attr]) del attrs[attr] else: @@ -676,7 +676,7 @@ class Values: are silently ignored. """ for attr in dir(self): - if dict.has_key(attr): + if attr in dict: dval = dict[attr] if dval is not None: setattr(self, attr, dval) @@ -704,7 +704,7 @@ class Values: def read_file (self, filename, mode="careful"): vars = {} - execfile(filename, vars) + exec(open(filename).read(), vars) self._update(vars, mode) def ensure_value (self, attr, value): @@ -786,10 +786,10 @@ class OptionContainer: def _check_conflict (self, option): conflict_opts = [] for opt in option._short_opts: - if self._short_opt.has_key(opt): + if opt in self._short_opt: conflict_opts.append((opt, self._short_opt[opt])) for opt in option._long_opts: - if self._long_opt.has_key(opt): + if opt in self._long_opt: conflict_opts.append((opt, self._long_opt[opt])) if conflict_opts: @@ -837,7 +837,7 @@ class OptionContainer: if option.dest is not None: # option has a dest, we need a default if option.default is not NO_DEFAULT: self.defaults[option.dest] = option.default - elif not self.defaults.has_key(option.dest): + elif option.dest not in self.defaults: self.defaults[option.dest] = None return option @@ -853,8 +853,8 @@ class OptionContainer: self._long_opt.get(opt_str)) def has_option (self, opt_str): - return (self._short_opt.has_key(opt_str) or - self._long_opt.has_key(opt_str)) + return (opt_str in self._short_opt or + opt_str in self._long_opt) def remove_option (self, opt_str): option = self._short_opt.get(opt_str) @@ -1393,7 +1393,7 @@ def _match_abbrev (s, wordmap): 'words', raise BadOptionError. """ # Is there an exact match? - if wordmap.has_key(s): + if s in wordmap: return s else: # Isolate all words with s as a prefix. diff --git a/extras/roman.py b/extras/roman.py index ebe088308..0335f29f8 100644 --- a/extras/roman.py +++ b/extras/roman.py @@ -41,7 +41,7 @@ def toRoman(n): """convert integer to Roman numeral""" if not (0 < n < 5000): raise OutOfRangeError, "number out of range (must be 1..4999)" - if int(n) <> n: + if int(n) != n: raise NotIntegerError, "decimals can not be converted" result = "" diff --git a/test/DocutilsTestSupport.py b/test/DocutilsTestSupport.py index 24858c624..ce67ab262 100644 --- a/test/DocutilsTestSupport.py +++ b/test/DocutilsTestSupport.py @@ -668,7 +668,7 @@ class WriterPublishTestCase(CustomTestCase, docutils.SettingsSpec): writer_name = '' # set in subclasses or constructor def __init__(self, *args, **kwargs): - if kwargs.has_key('writer_name'): + if 'writer_name' in kwargs: self.writer_name = kwargs['writer_name'] del kwargs['writer_name'] CustomTestCase.__init__(self, *args, **kwargs) diff --git a/test/docutils_difflib.py b/test/docutils_difflib.py index a41d4d5ba..cc84c485a 100644 --- a/test/docutils_difflib.py +++ b/test/docutils_difflib.py @@ -163,8 +163,6 @@ class SequenceMatcher: # b2j # for x in b, b2j[x] is a list of the indices (into b) # at which x appears; junk elements do not appear - # b2jhas - # b2j.has_key # fullbcount # for x in b, fullbcount[x] == the number of times x # appears in b; only materialized if really needed (used @@ -188,7 +186,7 @@ class SequenceMatcher: # DON'T USE! Only __chain_b uses this. Use isbjunk. # isbjunk # for x in b, isbjunk(x) == isjunk(x) but much faster; - # it's really the has_key method of a hidden dict. + # it's really the in operator of a hidden dict. # DOES NOT WORK for x in a! self.isjunk = isjunk @@ -285,10 +283,9 @@ class SequenceMatcher: # from the start. b = self.b self.b2j = b2j = {} - self.b2jhas = b2jhas = b2j.has_key for i in xrange(len(b)): elt = b[i] - if b2jhas(elt): + if elt in b2j: b2j[elt].append(i) else: b2j[elt] = [i] @@ -304,12 +301,12 @@ class SequenceMatcher: junkdict[elt] = 1 # value irrelevant; it's a set del b2j[elt] - # Now for x in b, isjunk(x) == junkdict.has_key(x), but the + # Now for x in b, isjunk(x) == x in junkdict, but the # latter is much faster. Note too that while there may be a # lot of junk in the sequence, the number of *unique* junk # elements is probably small. So the memory burden of keeping # this dict alive is likely trivial compared to the size of b2j. - self.isbjunk = junkdict.has_key + self.isbjunk = lambda elt: elt in junkdict def find_longest_match(self, alo, ahi, blo, bhi): """Find longest matching block in a[alo:ahi] and b[blo:bhi]. @@ -528,8 +525,9 @@ class SequenceMatcher: 1.0 """ - matches = reduce(lambda sum, triple: sum + triple[-1], - self.get_matching_blocks(), 0) + matches = 0 + for triple in self.get_matching_blocks(): + matches += triple[-1] return 2.0 * matches / (len(self.a) + len(self.b)) def quick_ratio(self): @@ -550,9 +548,9 @@ class SequenceMatcher: # avail[x] is the number of times x appears in 'b' less the # number of times we've seen it in 'a' so far ... kinda avail = {} - availhas, matches = avail.has_key, 0 + matches = 0 for elt in self.a: - if availhas(elt): + if elt in avail: numb = avail[elt] else: numb = fullbcount.get(elt, 0) @@ -603,9 +601,9 @@ def get_close_matches(word, possibilities, n=3, cutoff=0.6): """ if not n > 0: - raise ValueError("n must be > 0: " + `n`) + raise ValueError("n must be > 0: " + repr(n)) if not 0.0 <= cutoff <= 1.0: - raise ValueError("cutoff must be in [0.0, 1.0]: " + `cutoff`) + raise ValueError("cutoff must be in [0.0, 1.0]: " + repr(cutoff)) result = [] s = SequenceMatcher() s.set_seq2(word) @@ -791,7 +789,7 @@ class Differ: elif tag == 'equal': self._dump(' ', a, alo, ahi) else: - raise ValueError, 'unknown tag ' + `tag` + raise ValueError, 'unknown tag ' + repr(tag) results = self.results self.results = [] return results @@ -907,7 +905,7 @@ class Differ: atags += ' ' * la btags += ' ' * lb else: - raise ValueError, 'unknown tag ' + `tag` + raise ValueError, 'unknown tag ' + repr(tag) self._qformat(aelt, belt, atags, btags) else: # the synch pair is identical diff --git a/test/functional/tests/standalone_rst_html4css1.py b/test/functional/tests/standalone_rst_html4css1.py index c34298eab..9f80e6d79 100644 --- a/test/functional/tests/standalone_rst_html4css1.py +++ b/test/functional/tests/standalone_rst_html4css1.py @@ -1,4 +1,4 @@ -execfile('functional/tests/_standalone_rst_defaults.py') +exec(open('functional/tests/_standalone_rst_defaults.py').read()) # Source and destination file names. test_source = "standalone_rst_html4css1.txt" diff --git a/test/functional/tests/standalone_rst_latex.py b/test/functional/tests/standalone_rst_latex.py index f0c40b75a..39a5e1e5e 100644 --- a/test/functional/tests/standalone_rst_latex.py +++ b/test/functional/tests/standalone_rst_latex.py @@ -1,4 +1,4 @@ -execfile('functional/tests/_standalone_rst_defaults.py') +exec(open('functional/tests/_standalone_rst_defaults.py').read()) # Source and destination file names. test_source = "standalone_rst_latex.txt" diff --git a/test/functional/tests/standalone_rst_pseudoxml.py b/test/functional/tests/standalone_rst_pseudoxml.py index b9b2df309..7f9b06f04 100644 --- a/test/functional/tests/standalone_rst_pseudoxml.py +++ b/test/functional/tests/standalone_rst_pseudoxml.py @@ -1,4 +1,4 @@ -execfile('functional/tests/_standalone_rst_defaults.py') +exec(open('functional/tests/_standalone_rst_defaults.py').read()) # Source and destination file names. test_source = "standalone_rst_pseudoxml.txt" diff --git a/test/functional/tests/standalone_rst_s5_html_1.py b/test/functional/tests/standalone_rst_s5_html_1.py index ce27f687a..9939ad688 100755 --- a/test/functional/tests/standalone_rst_s5_html_1.py +++ b/test/functional/tests/standalone_rst_s5_html_1.py @@ -1,4 +1,4 @@ -execfile('functional/tests/_standalone_rst_defaults.py') +exec(open('functional/tests/_standalone_rst_defaults.py').read()) # Source and destination file names: test_source = 'standalone_rst_s5_html.txt' diff --git a/test/functional/tests/standalone_rst_s5_html_2.py b/test/functional/tests/standalone_rst_s5_html_2.py index aea7a9207..385558ac3 100755 --- a/test/functional/tests/standalone_rst_s5_html_2.py +++ b/test/functional/tests/standalone_rst_s5_html_2.py @@ -1,5 +1,5 @@ # initialize with the settings & definitions from test 1: -execfile('functional/tests/standalone_rst_s5_html_1.py') +exec(open('functional/tests/standalone_rst_s5_html_1.py').read()) # overrides specific to this test: test_destination = 'standalone_rst_s5_html_2.html' diff --git a/test/test_dependencies.py b/test/test_dependencies.py index d82f52c55..c9463b440 100755 --- a/test/test_dependencies.py +++ b/test/test_dependencies.py @@ -28,7 +28,7 @@ class RecordDependenciesTests(unittest.TestCase): settings.setdefault('settings_overrides', {}) settings['settings_overrides'] = settings['settings_overrides'].copy() settings['settings_overrides']['_disable_config'] = 1 - if not settings['settings_overrides'].has_key('record_dependencies'): + if 'record_dependencies' not in settings['settings_overrides']: settings['settings_overrides']['record_dependencies'] = \ docutils.utils.DependencyList(recordfile) docutils.core.publish_file(destination=DocutilsTestSupport.DevNull(), diff --git a/test/test_functional.py b/test/test_functional.py index 26f4533c6..d2dff949d 100755 --- a/test/test_functional.py +++ b/test/test_functional.py @@ -92,12 +92,13 @@ class FunctionalTestCase(DocutilsTestSupport.CustomTestCase): namespace['settings_overrides'] = {'_disable_config': 1} # Read the variables set in the default config file and in # the current config file into namespace: - execfile(join_path(datadir, 'tests', '_default.py'), namespace) - execfile(self.configfile, namespace) + defaultpy = open(join_path(datadir, 'tests', '_default.py')).read() + exec(defaultpy, namespace) + exec(open(self.configfile).read(), namespace) # Check for required settings: - assert namespace.has_key('test_source'),\ + assert 'test_source' in namespace,\ "No 'test_source' supplied in " + self.configfile - assert namespace.has_key('test_destination'),\ + assert 'test_destination' in namespace,\ "No 'test_destination' supplied in " + self.configfile # Set source_path and destination_path if not given: namespace.setdefault('source_path', @@ -151,7 +152,7 @@ class FunctionalTestCase(DocutilsTestSupport.CustomTestCase): print >>sys.stderr, diff raise # Execute optional function containing extra tests: - if namespace.has_key('_test_more'): + if '_test_more' in namespace: namespace['_test_more'](join_path(datadir, 'expected'), join_path(datadir, 'output'), self, namespace) diff --git a/test/test_language.py b/test/test_language.py index 3f929bd05..6fd0ee546 100755 --- a/test/test_language.py +++ b/test/test_language.py @@ -76,10 +76,10 @@ class LanguageTestCase(DocutilsTestSupport.CustomTestCase): missing = [] # in ref but not in l. too_much = [] # in l but not in ref. for label in ref_dict.keys(): - if not l_dict.has_key(label): + if label not in l_dict: missing.append(label) for label in l_dict.keys(): - if not ref_dict.has_key(label): + if label not in ref_dict: too_much.append(label) return (missing, too_much) @@ -140,7 +140,7 @@ class LanguageTestCase(DocutilsTestSupport.CustomTestCase): canonical.sort() canonical.remove('restructuredtext-test-directive') for name in canonical: - if not inverted.has_key(name): + if name not in inverted: failures.append('"%s": translation missing' % name) if failures: text = ('Module docutils.parsers.rst.languages.%s:\n %s' @@ -175,7 +175,7 @@ class LanguageTestCase(DocutilsTestSupport.CustomTestCase): canonical.sort() canonical.remove('restructuredtext-unimplemented-role') for name in canonical: - if not inverted.has_key(name): + if name not in inverted: failures.append('"%s": translation missing' % name) if failures: text = ('Module docutils.parsers.rst.languages.%s:\n %s' diff --git a/test/test_nodes.py b/test/test_nodes.py index c981a4e96..ff6aac940 100755 --- a/test/test_nodes.py +++ b/test/test_nodes.py @@ -39,6 +39,10 @@ class TextTests(unittest.TestCase): def test_pformat(self): self.assertEquals(self.text.pformat(), 'Line 1.\nLine 2.\n') + def test_asciirestriction(self): + self.assertRaises(UnicodeError, nodes.Text, 'hol%s' % chr(224)) + # more specifically: UnicodeDecodeError since py2.3 + class ElementTests(unittest.TestCase): @@ -91,7 +95,7 @@ class ElementTests(unittest.TestCase): def test_normal_attributes(self): element = nodes.Element() - self.assert_(not element.has_key('foo')) + self.assert_('foo' not in element) self.assertRaises(KeyError, element.__getitem__, 'foo') element['foo'] = 'sometext' self.assertEquals(element['foo'], 'sometext') diff --git a/test/test_parsers/test_parser.py b/test/test_parsers/test_parser.py new file mode 100644 index 000000000..1d684bdad --- /dev/null +++ b/test/test_parsers/test_parser.py @@ -0,0 +1,31 @@ +#! /usr/bin/env python + +# $Id$ +# Author: Stefan Rank <strank(AT)strank(DOT)info> +# Copyright: This module has been placed in the public domain. + +""" +Tests for basic functionality of parser classes. +""" + +import unittest +import DocutilsTestSupport # must be imported before docutils +import docutils +from docutils import parsers, utils, frontend + + + +class RstParserTests(unittest.TestCase): + + def test_inputrestrictions(self): + parser_class = parsers.get_parser_class('rst') + parser = parser_class() + document = utils.new_document('test data', frontend.OptionParser( + components=(parser, )).get_default_values()) + + self.assertRaises(UnicodeError, # UnicodeDecodeError since py2.3 + parser.parse, 'hol%s' % chr(224), document) + + +if __name__ == '__main__': + unittest.main() diff --git a/test/test_parsers/test_rst/test_directives/test_images.py b/test/test_parsers/test_rst/test_directives/test_images.py index 1ce24d4a4..7c8fa2299 100755 --- a/test/test_parsers/test_rst/test_directives/test_images.py +++ b/test/test_parsers/test_rst/test_directives/test_images.py @@ -385,7 +385,7 @@ u"""\ <system_message level="3" line="1" source="test data" type="ERROR"> <paragraph> Error in "image" directive: - invalid option value: (option: "align"; value: u\'\\xe4\') + invalid option value: (option: "align"; value: \'\\xe4\') "\xe4" unknown; choose from "top", "middle", "bottom", "left", "center", or "right". <literal_block xml:space="preserve"> .. image:: picture.png diff --git a/test/test_parsers/test_rst/test_directives/test_raw.py b/test/test_parsers/test_rst/test_directives/test_raw.py index 63cee274f..1e2d9c5ca 100755 --- a/test/test_parsers/test_rst/test_directives/test_raw.py +++ b/test/test_parsers/test_rst/test_directives/test_raw.py @@ -122,12 +122,12 @@ Raw input file is UTF-16-encoded, and is not valid ASCII. :file: %s :encoding: ascii """ % utf_16_file_rel], -["""\ +[unicode("""\ .. raw:: html :encoding: utf-8 Should the parser complain becau\xdfe there is no :file:? BUG? -""", +""", 'iso-8859-1'), """\ <document source="test data"> <raw format="html" xml:space="preserve"> @@ -153,11 +153,11 @@ Raw input file is UTF-16-encoded, and is not valid ASCII. <system_message level="4" line="1" source="test data" type="SEVERE"> <paragraph> Problems with "raw" directive path: - [Errno 2] No such file or directory: 'non-existent.file'. + [Errno 2] No such file or directory: u'non-existent.file'. <literal_block xml:space="preserve"> .. raw:: html :file: non-existent.file -"""], +"""], # note that this output is rewritten below for certain python versions ] # Skip tests whose output contains "UnicodeDecodeError" if we are not @@ -171,6 +171,16 @@ if sys.version_info < (2, 3): # Assume we have only one of these tests. break +# Rewrite tests that depend on the output of IOError as it is +# platform-dependent before python 2.4 for a unicode path. +if sys.version_info < (2, 4): + # remove the unicode repr u except for py2.3 on windows: + if not sys.platform.startswith('win') or sys.version_info < (2, 3): + for i in range(len(totest['raw'])): + if totest['raw'][i][1].find("u'non-existent.file'") != -1: + totest['raw'][i][1] = totest['raw'][i][1].replace( + "u'non-existent.file'", "'non-existent.file'") + if __name__ == '__main__': import unittest diff --git a/test/test_parsers/test_rst/test_directives/test_tables.py b/test/test_parsers/test_rst/test_directives/test_tables.py index 862c08b13..d97516767 100755 --- a/test/test_parsers/test_rst/test_directives/test_tables.py +++ b/test/test_parsers/test_rst/test_directives/test_tables.py @@ -562,11 +562,11 @@ u"""\ <system_message level="4" line="1" source="test data" type="SEVERE"> <paragraph> Problems with "csv-table" directive path: - [Errno 2] No such file or directory: 'bogus.csv'. + [Errno 2] No such file or directory: u'bogus.csv'. <literal_block xml:space="preserve"> .. csv-table:: no such file :file: bogus.csv -"""], +"""], # note that this output is rewritten below for certain python versions ["""\ .. csv-table:: bad URL :url: bogus.csv @@ -1074,6 +1074,18 @@ totest['list-table'] = [ ] +if csv: + # Rewrite csv tests that depend on the output of IOError as it is + # platform-dependent before python 2.4 for a unicode path. + # Here only needed for python 2.3 on non-windows + import sys + if sys.version_info < (2, 4) and not sys.platform.startswith('win'): + for i in range(len(totest['csv-table'])): + if totest['csv-table'][i][1].find("u'bogus.csv'") != -1: + totest['csv-table'][i][1] = totest['csv-table'][i][1].replace( + "u'bogus.csv'", "'bogus.csv'") + + if __name__ == '__main__': import unittest unittest.main(defaultTest='suite') diff --git a/test/test_publisher.py b/test/test_publisher.py index 45427d532..b532229b0 100755 --- a/test/test_publisher.py +++ b/test/test_publisher.py @@ -37,7 +37,7 @@ pseudoxml_output = """\ Unknown target name: "nonexistent". """ exposed_pseudoxml_output = """\ -<document ids="test-document" internal:refnames="{u\'nonexistent\': [<reference: <#text: u\'nonexistent\'>>]}" names="test\ document" source="<string>" title="Test Document"> +<document ids="test-document" internal:refnames="{u\'nonexistent\': [<reference: <#text: \'nonexistent\'>>]}" names="test\ document" source="<string>" title="Test Document"> <title> Test Document <paragraph> diff --git a/test/test_settings.py b/test/test_settings.py index 2cf4e080c..fb050b2ad 100755 --- a/test/test_settings.py +++ b/test/test_settings.py @@ -92,8 +92,8 @@ class ConfigFileTests(unittest.TestCase): def compare_output(self, result, expected): """`result` and `expected` should both be dicts.""" - self.assert_(result.has_key('record_dependencies')) - if not expected.has_key('record_dependencies'): + self.assert_('record_dependencies' in result) + if 'record_dependencies' not in expected: # Delete it if we don't want to test it. del result['record_dependencies'] result = pprint.pformat(result) + '\n' diff --git a/test/test_utils.py b/test/test_utils.py index 9461ca248..9f0eda54b 100755 --- a/test/test_utils.py +++ b/test/test_utils.py @@ -172,12 +172,14 @@ class ExtensionOptionTests(unittest.TestCase): nodes.field_body('', nodes.paragraph('', '2.0'))) field_list += nodes.field( '', nodes.field_name('', 'cdef'), - nodes.field_body('', nodes.paragraph('', 'hol%s' % chr(224)))) + nodes.field_body('', nodes.paragraph('', + unicode('hol%s' % chr(224), 'iso-8859-1')))) field_list += nodes.field( '', nodes.field_name('', 'empty'), nodes.field_body()) self.assertEquals( utils.extract_extension_options(field_list, self.optionspec), - {'a': 1, 'bbb': 2.0, 'cdef': ('hol%s' % chr(224)), + {'a': 1, 'bbb': 2.0, + 'cdef': unicode('hol%s' % chr(224), 'iso-8859-1'), 'empty': None}) self.assertRaises(KeyError, utils.extract_extension_options, field_list, {}) diff --git a/tools/dev/profile_docutils.py b/tools/dev/profile_docutils.py index e342b0239..90b083787 100755 --- a/tools/dev/profile_docutils.py +++ b/tools/dev/profile_docutils.py @@ -34,6 +34,6 @@ stats.sort_stats('time') stats.print_stats(40) try: - execfile(os.environ['PYTHONSTARTUP']) + exec(open(os.environ['PYTHONSTARTUP']).read()) except: pass diff --git a/tools/dev/unicode2rstsubs.py b/tools/dev/unicode2rstsubs.py index 9161e10c1..22ac07ecc 100755 --- a/tools/dev/unicode2rstsubs.py +++ b/tools/dev/unicode2rstsubs.py @@ -129,11 +129,11 @@ class CharacterEntitySetExtractor: set = self.entity_set_name(attributes['set']) if not set: return - if not self.sets.has_key(set): + if set not in self.sets: print 'bad set: %r' % set return entity = attributes['id'] - assert (not self.sets[set].has_key(entity) + assert (entity not in self.sets[set] or self.sets[set][entity] == self.charid), \ ('sets[%r][%r] == %r (!= %r)' % (set, entity, self.sets[set][entity], self.charid)) |