Skip to content

Commit a45d228

Browse files
committed
Improve metaclass handling
Also, no longer need u() and b()
1 parent 84099ad commit a45d228

File tree

3 files changed

+28
-35
lines changed

3 files changed

+28
-35
lines changed

text/base.py

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,11 @@
77
from __future__ import absolute_import
88
from abc import ABCMeta, abstractmethod
99
from text.packages import nltk
10-
from text.compat import add_metaclass
10+
from text.compat import with_metaclass
1111

1212
##### POS TAGGERS #####
1313

14-
@add_metaclass(ABCMeta)
15-
class BaseTagger(object):
14+
class BaseTagger(with_metaclass(ABCMeta)):
1615

1716
'''Abstract tagger class from which all taggers
1817
inherit from. All descendants must implement a
@@ -27,8 +26,7 @@ def tag(self, text, tokenize=True):
2726

2827
##### NOUN PHRASE EXTRACTORS #####
2928

30-
@add_metaclass(ABCMeta)
31-
class BaseNPExtractor(object):
29+
class BaseNPExtractor(with_metaclass(ABCMeta)):
3230

3331
'''Abstract base class from which all NPExtractor classes inherit.
3432
Descendant classes must implement an ``extract(text)`` method
@@ -42,8 +40,7 @@ def extract(self, text):
4240

4341
##### TOKENIZERS #####
4442

45-
@add_metaclass(ABCMeta)
46-
class BaseTokenizer(nltk.tokenize.api.TokenizerI):
43+
class BaseTokenizer(with_metaclass(ABCMeta), nltk.tokenize.api.TokenizerI):
4744

4845
'''Abstract base class from which all Tokenizer classes inherit.
4946
Descendant classes must implement a ``tokenize(text)`` method
@@ -71,8 +68,8 @@ def itokenize(self, text, *args, **kwargs):
7168
DISCRETE = 'ds'
7269
CONTINUOUS = 'co'
7370

74-
@add_metaclass(ABCMeta)
75-
class BaseSentimentAnalyzer(object):
71+
72+
class BaseSentimentAnalyzer(with_metaclass(ABCMeta)):
7673

7774
'''Abstract base class from which all sentiment analyzers inherit.
7875
Should implement an ``analyze(text)`` method which returns either the
@@ -99,8 +96,7 @@ def analyze(self, text):
9996

10097
##### PARSERS #####
10198

102-
@add_metaclass(ABCMeta)
103-
class BaseParser(object):
99+
class BaseParser(with_metaclass(ABCMeta)):
104100

105101
'''Abstract parser class from which all parsers inherit from. All
106102
descendants must implement a `parse()` method.

text/classifiers.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
from __future__ import absolute_import
3535
from text.packages import nltk
3636
from text.tokenizers import WordTokenizer
37-
from text.compat import basestring, u
37+
from text.compat import basestring
3838
import text.formats as formats
3939
from text.utils import lowerstrip
4040
from text.decorators import cached_property
@@ -74,7 +74,7 @@ def basic_extractor(document, train_set):
7474
for w in tokenizer.itokenize(document, include_punc=False)])
7575
else:
7676
tokens = set((lowerstrip(w, all=False) for w in document))
77-
features = dict([(u('contains({0})').format(word), (word in tokens))
77+
features = dict([(u'contains({0})'.format(word), (word in tokens))
7878
for word in word_features])
7979
return features
8080

@@ -89,7 +89,7 @@ def contains_extractor(document):
8989
for w in tokenizer.itokenize(document, include_punc=False)])
9090
else:
9191
tokens = set((lowerstrip(w, all=False) for w in document))
92-
features = dict((u('contains({0})'.format(w)), True) for w in tokens)
92+
features = dict((u'contains({0})'.format(w), True) for w in tokens)
9393
return features
9494

9595
##### CLASSIFIERS #####

text/compat.py

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,6 @@
44
PY2 = int(sys.version[0]) == 2
55

66
if PY2:
7-
def b(s):
8-
return s
9-
def u(s):
10-
return unicode(s, "unicode_escape")
117
from itertools import imap, izip
128
import urllib2 as request
139
from urllib import quote as urlquote
@@ -27,12 +23,7 @@ def implements_to_string(cls):
2723
cls.__unicode__ = cls.__str__
2824
cls.__str__ = lambda x: x.__unicode__().encode('utf-8')
2925
return cls
30-
3126
else: # PY3
32-
def b(s):
33-
return s.encode("latin-1")
34-
def u(s):
35-
return s
3627
from urllib import request
3728
from urllib.parse import quote as urlquote
3829
text_type = str
@@ -47,15 +38,21 @@ def u(s):
4738
implements_to_string = lambda x: x
4839

4940

50-
def add_metaclass(metaclass):
51-
"""Class decorator for creating a class with a metaclass.
52-
From the six library.
53-
"""
54-
def wrapper(cls):
55-
orig_vars = cls.__dict__.copy()
56-
orig_vars.pop('__dict__', None)
57-
orig_vars.pop('__weakref__', None)
58-
for slots_var in orig_vars.get('__slots__', ()):
59-
orig_vars.pop(slots_var)
60-
return metaclass(cls.__name__, cls.__bases__, orig_vars)
61-
return wrapper
41+
def with_metaclass(meta, *bases):
42+
'''Defines a metaclass.
43+
44+
Creates a dummy class with a dummy metaclass. When subclassed, the dummy
45+
metaclass is used, which has a constructor that instantiates a
46+
new class from the original parent. This ensures that the dummy class and
47+
dummy metaclass are not in the inheritance tree.
48+
49+
Credit to Armin Ronacher.
50+
'''
51+
class metaclass(meta):
52+
__call__ = type.__call__
53+
__init__ = type.__init__
54+
def __new__(cls, name, this_bases, d):
55+
if this_bases is None:
56+
return type.__new__(cls, name, (), d)
57+
return meta(name, bases, d)
58+
return metaclass('temporary_class', None, {})

0 commit comments

Comments
 (0)