Permalink
Browse files

Merge pull request #213 from heatherleaf/py25-compatible

Backtracking some python 2.5 incompatible changes
  • Loading branch information...
2 parents 3380a2f + a3e7cad commit 517d93f4a6a3f47f6e9c7c11c93771be1076bda1 @stevenbird stevenbird committed Feb 9, 2012
Showing with 87 additions and 73 deletions.
  1. +3 −5 nltk/align.py
  2. +6 −10 nltk/downloader.py
  3. +2 −5 nltk/sem/logic.py
  4. +6 −6 nltk/test/tree.doctest
  5. +70 −47 nltk/tree.py
View
@@ -58,16 +58,14 @@ def words(self):
def mots(self):
return self._mots
- @property
- def alignment(self):
+ def _get_alignment(self):
return self._alignment
-
- @alignment.setter
- def alignment(self, alignment):
+ def _set_alignment(self, alignment):
if not isinstance(alignment, Alignment):
alignment = Alignment(alignment)
self._check_align(alignment)
self._alignment = alignment
+ alignment = property(_get_alignment, _set_alignment)
def _check_align(self, a):
"""
View
@@ -876,13 +876,10 @@ def xmlinfo(self, id):
# URL & Data Directory
#/////////////////////////////////////////////////////////////////
- @property
- def url(self):
+ def _get_url(self):
"""The URL for the data server's index file."""
return self._url
-
- @url.setter
- def url(self, url):
+ def _set_url(self, url):
"""
Set a new URL for the data server. If we're unable to contact
the given url, then the original url is kept.
@@ -893,6 +890,7 @@ def url(self, url):
except:
self._url = original_url
raise
+ url = property(_get_url, _set_url)
def default_download_dir(self):
"""
@@ -930,21 +928,19 @@ def default_download_dir(self):
# append "nltk_data" to the home directory
return os.path.join(homedir, 'nltk_data')
- @property
- def download_dir(self):
+ def _get_download_dir(self):
"""
The default directory to which packages will be downloaded.
This defaults to the value returned by ``default_download_dir()``.
To override this default on a case-by-case basis, use the
``download_dir`` argument when calling ``download()``.
"""
return self._download_dir
-
- @download_dir.setter
- def download_dir(self, download_dir):
+ def _set_download_dir(self, download_dir):
self._download_dir = download_dir
# Clear the status cache.
self._status_cache.clear()
+ download_dir = property(_get_download_dir, _set_download_dir)
#/////////////////////////////////////////////////////////////////
# Interactive Shell
View
@@ -861,11 +861,8 @@ def _set_type(self, other_type=ANY_TYPE, signature=None):
signature[self.variable.name].append(self)
- @property
- def type(self): return ENTITY_TYPE
-
- @type.setter
- def type(self, other): self._set_type(other)
+ def _get_type(self): return ENTITY_TYPE
+ type = property(_get_type, _set_type)
def free(self):
""":see: Expression.free()"""
View
@@ -683,7 +683,7 @@ operations:
>>> ptree.pop(-100)
Traceback (most recent call last):
. . .
- IndexError: list index out of range
+ IndexError: index out of range
**remove()**
@@ -697,13 +697,13 @@ operations:
>>> ptree[0,0].remove(make_ptree('(Q p)'))
Traceback (most recent call last):
. . .
- ValueError
+ ValueError: list.index(x): x not in list
>>> ptree.remove('h'); pcheck(ptree)
ok! (A (B (C (D )) g))
>>> ptree.remove('h');
Traceback (most recent call last):
. . .
- ValueError
+ ValueError: list.index(x): x not in list
>>> # remove() removes the first subtree that is equal (==) to the
>>> # given tree, which may not be the identical tree we give it:
>>> ptree = make_ptree('(A (X x) (Y y) (X x))')
@@ -998,7 +998,7 @@ multiple parents.)
>>> mptree.pop(-100)
Traceback (most recent call last):
. . .
- IndexError: list index out of range
+ IndexError: index out of range
**remove()**
@@ -1012,13 +1012,13 @@ multiple parents.)
>>> mptree[0,0].remove(make_mptree('(Q p)'))
Traceback (most recent call last):
. . .
- ValueError
+ ValueError: list.index(x): x not in list
>>> mptree.remove('h'); mpcheck(mptree)
ok! (A (B (C (D )) g))
>>> mptree.remove('h');
Traceback (most recent call last):
. . .
- ValueError
+ ValueError: list.index(x): x not in list
>>> # remove() removes the first subtree that is equal (==) to the
>>> # given tree, which may not be the identical tree we give it:
>>> mptree = make_mptree('(A (X x) (Y y) (X x))')
View
@@ -18,7 +18,6 @@
import re
import string
-from collections import MutableSequence
from nltk.grammar import Production, Nonterminal
from nltk.probability import ProbabilisticMixIn
@@ -28,7 +27,7 @@
## Trees
######################################################################
-class Tree(MutableSequence):
+class Tree(list):
"""
A Tree represents a hierarchical grouping of leaves and subtrees.
For example, each constituent in a syntax tree is represented by a single Tree.
@@ -98,13 +97,13 @@ def __init__(self, node_or_str, children=None):
raise TypeError("%s: Expected a node value and child list "
"or a single string" % type(self).__name__)
tree = type(self).parse(node_or_str)
- self.children = tree.children
+ list.__init__(self, tree)
self.node = tree.node
elif isinstance(children, basestring):
raise TypeError("%s() argument 2 should be a list, not a "
"string" % type(self).__name__)
else:
- self.children = list(children)
+ list.__init__(self, children)
self.node = node_or_str
#////////////////////////////////////////////////////////////
@@ -113,29 +112,42 @@ def __init__(self, node_or_str, children=None):
def __eq__(self, other):
if not isinstance(other, Tree): return False
- return self.node == other.node and self.children == other.children
+ return self.node == other.node and list.__eq__(self, other)
def __ne__(self, other):
return not (self == other)
def __lt__(self, other):
if not isinstance(other, Tree): return False
- return self.node < other.node or self.children < other.children
+ return self.node < other.node or list.__lt__(self, other)
def __le__(self, other):
if not isinstance(other, Tree): return False
- return self.node <= other.node or self.children <= other.children
+ return self.node <= other.node or list.__le__(self, other)
def __gt__(self, other):
if not isinstance(other, Tree): return True
- return self.node > other.node or self.children > other.children
+ return self.node > other.node or list.__gt__(self, other)
def __ge__(self, other):
if not isinstance(other, Tree): return False
- return self.node >= other.node or self.children >= other.children
+ return self.node >= other.node or list.__ge__(self, other)
#////////////////////////////////////////////////////////////
- # Required MutableSequence methods
+ # Disabled list operations
+ #////////////////////////////////////////////////////////////
+
+ def __mul__(self, v):
+ raise TypeError('Tree does not support multiplication')
+ def __rmul__(self, v):
+ raise TypeError('Tree does not support multiplication')
+ def __add__(self, v):
+ raise TypeError('Tree does not support addition')
+ def __radd__(self, v):
+ raise TypeError('Tree does not support addition')
+
+ #////////////////////////////////////////////////////////////
+ # Indexing (with support for tree positions)
#////////////////////////////////////////////////////////////
def __getitem__(self, index):
if isinstance(index, (int, slice)):
- return self.children[index]
+ return list.__getitem__(self, index)
elif isinstance(index, (list, tuple)):
if len(index) == 0:
return self
@@ -149,7 +161,7 @@ def __getitem__(self, index):
def __setitem__(self, index, value):
if isinstance(index, (int, slice)):
- self.children[index] = value
+ return list.__setitem__(self, index, value)
elif isinstance(index, (list, tuple)):
if len(index) == 0:
raise IndexError('The tree position () may not be '
@@ -164,7 +176,7 @@ def __setitem__(self, index, value):
def __delitem__(self, index):
if isinstance(index, (int, slice)):
- del self.children[index]
+ return list.__delitem__(self, index)
elif isinstance(index, (list, tuple)):
if len(index) == 0:
raise IndexError('The tree position () may not be deleted.')
@@ -176,18 +188,6 @@ def __delitem__(self, index):
raise TypeError("%s indices must be integers, not %s" %
(type(self).__name__, type(index).__name__))
- def __contains__(self, child):
- return child in self.children
-
- def __len__(self):
- return len(self.children)
-
- def __iter__(self):
- return iter(self.children)
-
- def insert(self, index, child):
- self.children.insert(index, child)
-
#////////////////////////////////////////////////////////////
# Basic tree operations
#////////////////////////////////////////////////////////////
@@ -482,7 +482,7 @@ def convert(cls, tree):
return tree
def copy(self, deep=False):
- if not deep: return type(self)(self.node, self.children[:])
+ if not deep: return type(self)(self.node, self)
else: return type(self).convert(self)
def _frozen_class(self): return ImmutableTree
@@ -738,7 +738,7 @@ def __init__(self, node_or_str, children=None):
# Precompute our hash value. This ensures that we're really
# immutable. It also means we only have to calculate it once.
try:
- self._hash = hash( (self.node, self.children) )
+ self._hash = hash( (self.node, tuple(self)) )
except (TypeError, ValueError):
raise ValueError("%s: node value and children "
"must be immutable" % type(self).__name__)
@@ -770,35 +770,19 @@ def sort(self):
def __hash__(self):
return self._hash
- @property
- def node(self):
- """Get the node value."""
+ def _get_node(self):
+ """Get the node value"""
return self._node
-
- @node.setter
- def node(self, value):
+ def _set_node(self, value):
"""
Set the node value. This will only succeed the first time the
node value is set, which should occur in ImmutableTree.__init__().
"""
if hasattr(self, 'node'):
raise ValueError('%s may not be modified' % type(self).__name__)
self._node = value
+ node = property(_get_node, _set_node)
- @property
- def children(self):
- """Get the list of children."""
- return self._children
-
- @children.setter
- def children(self, children):
- """
- Set the children. This will only succeed the first time the
- children are set, which should occur in ImmutableTree.__init__().
- """
- if hasattr(self, 'children'):
- raise ValueError('%s may not be modified' % type(self).__name__)
- self._children = tuple(children)
######################################################################
## Parented trees
@@ -977,6 +961,17 @@ def __setitem__(self, index, value):
raise TypeError("%s indices must be integers, not %s" %
(type(self).__name__, type(index).__name__))
+ def append(self, child):
+ if isinstance(child, Tree):
+ self._setparent(child, len(self))
+ super(AbstractParentedTree, self).append(child)
+
+ def extend(self, children):
+ for child in children:
+ if isinstance(child, Tree):
+ self._setparent(child, len(self))
+ super(AbstractParentedTree, self).append(child)
+
def insert(self, index, child):
# Handle negative indexes. Note that if index < -len(self),
# we do *not* raise an IndexError, unlike __getitem__. This
@@ -988,6 +983,34 @@ def insert(self, index, child):
self._setparent(child, index)
super(AbstractParentedTree, self).insert(index, child)
+ def pop(self, index=-1):
+ if index < 0: index += len(self)
+ if index < 0: raise IndexError('index out of range')
+ if isinstance(self[index], Tree):
+ self._delparent(self[index], index)
+ return super(AbstractParentedTree, self).pop(index)
+
+ # n.b.: like `list`, this is done by equality, not identity!
+ # To remove a specific child, use del ptree[i].
+ def remove(self, child):
+ index = self.index(child)
+ if isinstance(self[index], Tree):
+ self._delparent(self[index], index)
+ super(AbstractParentedTree, self).remove(child)
+
+ # We need to implement __getslice__ and friends, even though
+ # they're deprecated, because otherwise list.__getslice__ will get
+ # called (since we're subclassing from list). Just delegate to
+ # __getitem__ etc., but use max(0, start) and max(0, stop) because
+ # because negative indices are already handled *before*
+ # __getslice__ is called; and we don't want to double-count them.
+ if hasattr(list, '__getslice__'):
+ def __getslice__(self, start, stop):
+ return self.__getitem__(slice(max(0, start), max(0, stop)))
+ def __delslice__(self, start, stop):
+ return self.__delitem__(slice(max(0, start), max(0, stop)))
+ def __setslice__(self, start, stop, value):
+ return self.__setitem__(slice(max(0, start), max(0, stop)), value)
class ParentedTree(AbstractParentedTree):
"""

0 comments on commit 517d93f

Please sign in to comment.