Mini Shell
# pyenchant
#
# Copyright (C) 2004-2009, Ryan Kelly
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
#
# In addition, as a special exception, you are
# given permission to link the code of this program with
# non-LGPL Spelling Provider libraries (eg: a MSFT Office
# spell checker backend) and distribute linked combinations including
# the two. You must obey the GNU Lesser General Public License in all
# respects for all of the code used other than said providers. If you modify
# this file, you may extend this exception to your version of the
# file, but you are not obligated to do so. If you do not wish to
# do so, delete this exception statement from your version.
#
"""
enchant.tests: testcases for pyenchant
"""
import os
import sys
import unittest
import pickle
try:
import subprocess
except ImportError:
subprocess = None
import enchant
from enchant import *
from enchant import _enchant as _e
from enchant.utils import unicode, raw_unicode, printf, trim_suggestions
def runcmd(cmd, **kwds):
if subprocess is not None:
kwds["stdout"] = subprocess.PIPE
kwds["stderr"] = subprocess.PIPE
kwds["shell"] = True
p = subprocess.Popen(cmd,**kwds)
(stdout,stderr) = p.communicate()
if p.returncode:
if sys.version_info[0] >= 3:
stderr = stderr.decode(sys.getdefaultencoding(),"replace")
sys.stderr.write(stderr)
return p.returncode
else:
return os.system(cmd)
class TestBroker(unittest.TestCase):
"""Test cases for the proper functioning of Broker objects.
These tests assume that there is at least one working provider
with a dictionary for the "en_US" language.
"""
def setUp(self):
self.broker = Broker()
def tearDown(self):
del self.broker
def test_HasENUS(self):
"""Test that the en_US language is available."""
self.assertTrue(self.broker.dict_exists("en_US"))
def test_LangsAreAvail(self):
"""Test whether all advertised languages are in fact available."""
for lang in self.broker.list_languages():
if not self.broker.dict_exists(lang):
assert False, "language '"+lang+"' advertised but non-existent"
def test_ProvsAreAvail(self):
"""Test whether all advertised providers are in fact available."""
for (lang,prov) in self.broker.list_dicts():
self.assertTrue(self.broker.dict_exists(lang))
if not self.broker.dict_exists(lang):
assert False, "language '"+lang+"' advertised but non-existent"
if prov not in self.broker.describe():
assert False, "provier '"+str(prov)+"' advertised but non-existent"
def test_ProvOrdering(self):
"""Test that provider ordering works correctly."""
langs = {}
provs = []
# Find the providers for each language, and a list of all providers
for (tag,prov) in self.broker.list_dicts():
# Skip hyphenation dictionaries installed by OOo
if tag.startswith("hyph_") and prov.name == "myspell":
continue
# Canonicalize separators
tag = tag.replace("-","_")
langs[tag] = []
# NOTE: we are excluding Zemberek here as it appears to return
# a broker for any language, even nonexistent ones
if prov not in provs and prov.name != "zemberek":
provs.append(prov)
for prov in provs:
for tag in langs:
b2 = Broker()
b2.set_ordering(tag,prov.name)
try:
d = b2.request_dict(tag)
if d.provider != prov:
raise ValueError()
langs[tag].append(prov)
except:
pass
# Check availability using a single entry in ordering
for tag in langs:
for prov in langs[tag]:
b2 = Broker()
b2.set_ordering(tag,prov.name)
d = b2.request_dict(tag)
self.assertEqual((d.provider,tag),(prov,tag))
del d
del b2
# Place providers that don't have the language in the ordering
for tag in langs:
for prov in langs[tag]:
order = prov.name
for prov2 in provs:
if prov2 not in langs[tag]:
order = prov2.name + "," + order
b2 = Broker()
b2.set_ordering(tag,order)
d = b2.request_dict(tag)
self.assertEqual((d.provider,tag,order),(prov,tag,order))
del d
del b2
def test_UnicodeTag(self):
"""Test that unicode language tags are accepted"""
d1 = self.broker._request_dict_data(raw_unicode("en_US"))
self.assertTrue(d1)
self.broker._free_dict_data(d1)
d1 = Dict(raw_unicode("en_US"))
self.assertTrue(d1)
def test_GetSetParam(self):
# Older enchnt versions do not have these functions.
if not hasattr(_e.broker_get_param,"argtypes"):
return
self.assertEqual(self.broker.get_param("pyenchant.unittest"),None)
self.broker.set_param("pyenchant.unittest","testing")
self.assertEqual(self.broker.get_param("pyenchant.unittest"),"testing")
self.assertEqual(Broker().get_param("pyenchant.unittest"),None)
class TestDict(unittest.TestCase):
"""Test cases for the proper functioning of Dict objects.
These tests assume that there is at least one working provider
with a dictionary for the "en_US" language.
"""
def setUp(self):
self.dict = Dict("en_US")
def tearDown(self):
del self.dict
def test_HasENUS(self):
"""Test that the en_US language is available through default broker."""
self.assertTrue(dict_exists("en_US"))
def test_check(self):
"""Test that check() works on some common words."""
self.assertTrue(self.dict.check("hello"))
self.assertTrue(self.dict.check("test"))
self.assertFalse(self.dict.check("helo"))
self.assertFalse(self.dict.check("testt"))
self.assertRaises(ValueError, self.dict.check, "")
def test_broker(self):
"""Test that the dict's broker is set correctly."""
self.assertTrue(self.dict._broker is enchant._broker)
def test_tag(self):
"""Test that the dict's tag is set correctly."""
self.assertEqual(self.dict.tag,"en_US")
def test_suggest(self):
"""Test that suggest() gets simple suggestions right."""
self.assertTrue(self.dict.check("hello"))
self.assertTrue("hello" in self.dict.suggest("helo"))
self.assertRaises(ValueError, self.dict.suggest, "")
def test_suggestHang1(self):
"""Test whether suggest() hangs on some inputs (Bug #1404196)"""
self.assertTrue(len(self.dict.suggest("Thiis")) >= 0)
self.assertTrue(len(self.dict.suggest("Thiiis")) >= 0)
self.assertTrue(len(self.dict.suggest("Thiiiis")) >= 0)
def test_unicode1(self):
"""Test checking/suggesting for unicode strings"""
# TODO: find something that actually returns suggestions
us1 = raw_unicode(r"he\u2149lo")
self.assertTrue(type(us1) is unicode)
self.assertFalse(self.dict.check(us1))
for s in self.dict.suggest(us1):
self.assertTrue(type(s) is unicode)
def test_session(self):
"""Test that adding words to the session works as required."""
self.assertFalse(self.dict.check("Lozz"))
self.assertFalse(self.dict.is_added("Lozz"))
self.dict.add_to_session("Lozz")
self.assertTrue(self.dict.is_added("Lozz"))
self.assertTrue(self.dict.check("Lozz"))
self.dict.remove_from_session("Lozz")
self.assertFalse(self.dict.check("Lozz"))
self.assertFalse(self.dict.is_added("Lozz"))
self.dict.remove_from_session("hello")
self.assertFalse(self.dict.check("hello"))
self.assertTrue(self.dict.is_removed("hello"))
self.dict.add_to_session("hello")
def test_AddRemove(self):
"""Test adding/removing from default user dictionary."""
nonsense = "kxhjsddsi"
self.assertFalse(self.dict.check(nonsense))
self.dict.add(nonsense)
self.assertTrue(self.dict.is_added(nonsense))
self.assertTrue(self.dict.check(nonsense))
self.dict.remove(nonsense)
self.assertFalse(self.dict.is_added(nonsense))
self.assertFalse(self.dict.check(nonsense))
self.dict.remove("pineapple")
self.assertFalse(self.dict.check("pineapple"))
self.assertTrue(self.dict.is_removed("pineapple"))
self.assertFalse(self.dict.is_added("pineapple"))
self.dict.add("pineapple")
self.assertTrue(self.dict.check("pineapple"))
def test_DefaultLang(self):
"""Test behaviour of default language selection."""
defLang = utils.get_default_language()
if defLang is None:
# If no default language, shouldn't work
self.assertRaises(Error,Dict)
else:
# If there is a default language, should use it
# Of course, no need for the dict to actually exist
try:
d = Dict()
self.assertEqual(d.tag,defLang)
except DictNotFoundError:
pass
def test_pickling(self):
"""Test that pickling doesn't corrupt internal state."""
d1 = Dict("en")
self.assertTrue(d1.check("hello"))
d2 = pickle.loads(pickle.dumps(d1))
self.assertTrue(d1.check("hello"))
self.assertTrue(d2.check("hello"))
d1._free()
self.assertTrue(d2.check("hello"))
class TestPWL(unittest.TestCase):
"""Test cases for the proper functioning of PWLs and DictWithPWL objects.
These tests assume that there is at least one working provider
with a dictionary for the "en_US" language.
"""
def setUp(self):
self._tempDir = self._mkdtemp()
self._fileName = "pwl.txt"
def tearDown(self):
import shutil
shutil.rmtree(self._tempDir)
def _mkdtemp(self):
import tempfile
return tempfile.mkdtemp()
def _path(self,nm=None):
if nm is None:
nm = self._fileName
nm = os.path.join(self._tempDir,nm)
if not os.path.exists(nm):
open(nm,'w').close()
return nm
def setPWLContents(self,contents):
"""Set the contents of the PWL file."""
pwlFile = open(self._path(),"w")
for ln in contents:
pwlFile.write(ln)
pwlFile.write("\n")
pwlFile.flush()
pwlFile.close()
def getPWLContents(self):
"""Retrieve the contents of the PWL file."""
pwlFile = open(self._path(),"r")
contents = pwlFile.readlines()
pwlFile.close()
return [c.strip() for c in contents]
def test_check(self):
"""Test that basic checking works for PWLs."""
self.setPWLContents(["Sazz","Lozz"])
d = request_pwl_dict(self._path())
self.assertTrue(d.check("Sazz"))
self.assertTrue(d.check("Lozz"))
self.assertFalse(d.check("hello"))
def test_UnicodeFN(self):
"""Test that unicode PWL filenames are accepted."""
d = request_pwl_dict(unicode(self._path()))
self.assertTrue(d)
def test_add(self):
"""Test that adding words to a PWL works correctly."""
d = request_pwl_dict(self._path())
self.assertFalse(d.check("Flagen"))
d.add("Esquilax")
d.add("Esquilam")
self.assertTrue(d.check("Esquilax"))
self.assertTrue("Esquilax" in self.getPWLContents())
self.assertTrue(d.is_added("Esquilax"))
def test_suggestions(self):
"""Test getting suggestions from a PWL."""
self.setPWLContents(["Sazz","Lozz"])
d = request_pwl_dict(self._path())
self.assertTrue("Sazz" in d.suggest("Saz"))
self.assertTrue("Lozz" in d.suggest("laz"))
self.assertTrue("Sazz" in d.suggest("laz"))
d.add("Flagen")
self.assertTrue("Flagen" in d.suggest("Flags"))
self.assertFalse("sazz" in d.suggest("Flags"))
def test_DWPWL(self):
"""Test functionality of DictWithPWL."""
self.setPWLContents(["Sazz","Lozz"])
d = DictWithPWL("en_US",self._path(),self._path("pel.txt"))
self.assertTrue(d.check("Sazz"))
self.assertTrue(d.check("Lozz"))
self.assertTrue(d.check("hello"))
self.assertFalse(d.check("helo"))
self.assertFalse(d.check("Flagen"))
d.add("Flagen")
self.assertTrue(d.check("Flagen"))
self.assertTrue("Flagen" in self.getPWLContents())
self.assertTrue("Flagen" in d.suggest("Flagn"))
self.assertTrue("hello" in d.suggest("helo"))
d.remove("hello")
self.assertFalse(d.check("hello"))
self.assertTrue("hello" not in d.suggest("helo"))
d.remove("Lozz")
self.assertFalse(d.check("Lozz"))
def test_DWPWL_empty(self):
"""Test functionality of DictWithPWL using transient dicts."""
d = DictWithPWL("en_US",None,None)
self.assertTrue(d.check("hello"))
self.assertFalse(d.check("helo"))
self.assertFalse(d.check("Flagen"))
d.add("Flagen")
self.assertTrue(d.check("Flagen"))
d.remove("hello")
self.assertFalse(d.check("hello"))
d.add("hello")
self.assertTrue(d.check("hello"))
def test_PyPWL(self):
"""Test our pure-python PWL implementation."""
d = PyPWL()
self.assertTrue(list(d._words) == [])
d.add("hello")
d.add("there")
d.add("duck")
ws = list(d._words)
self.assertTrue(len(ws) == 3)
self.assertTrue("hello" in ws)
self.assertTrue("there" in ws)
self.assertTrue("duck" in ws)
d.remove("duck")
d.remove("notinthere")
ws = list(d._words)
self.assertTrue(len(ws) == 2)
self.assertTrue("hello" in ws)
self.assertTrue("there" in ws)
def test_UnicodeCharsInPath(self):
"""Test that unicode chars in PWL paths are accepted."""
self._fileName = raw_unicode(r"test_\xe5\xe4\xf6_ing")
d = request_pwl_dict(self._path())
self.assertTrue(d)
class TestUtils(unittest.TestCase):
"""Test cases for various utility functions."""
def test_trim_suggestions(self):
word = "gud"
suggs = ["good","god","bad+"]
self.assertEqual(trim_suggestions(word,suggs,40),["god","good","bad+"])
self.assertEqual(trim_suggestions(word,suggs,4),["god","good","bad+"])
self.assertEqual(trim_suggestions(word,suggs,3),["god","good","bad+"])
self.assertEqual(trim_suggestions(word,suggs,2),["god","good"])
self.assertEqual(trim_suggestions(word,suggs,1),["god"])
self.assertEqual(trim_suggestions(word,suggs,0),[])
class TestDocStrings(unittest.TestCase):
"""Test the spelling on all docstrings we can find in this module.
This serves two purposes - to provide a lot of test data for the
checker routines, and to make sure we don't suffer the embarrassment
of having spelling errors in a spellchecking package!
"""
WORDS = ["spellchecking","utf","dict","unicode","bytestring","bytestrings",
"str","pyenchant","ascii", "utils","setup","distutils","pkg",
"filename", "tokenization", "tuple", "tuples", "tokenizer",
"tokenizers","testcase","testcases","whitespace","wxpython",
"spellchecker","dialog","urls","wikiwords","enchantobject",
"providerdesc", "spellcheck", "pwl", "aspell", "myspell",
"docstring", "docstrings", "stopiteration", "pwls","pypwl",
"dictwithpwl","skippable","dicts","dict's","filenames","fr",
"trie","api","ctypes","wxspellcheckerdialog","stateful",
"cmdlinechecker","spellchecks","callback","clunkier","iterator",
"ispell","cor","backends","subclasses","initialise","runtime"]
def test_docstrings(self):
"""Test that all our docstrings are error-free."""
import enchant
import enchant.utils
import enchant.pypwl
import enchant.tokenize
import enchant.tokenize.en
import enchant.checker
import enchant.checker.CmdLineChecker
try:
import enchant.checker.GtkSpellCheckerDialog
except ImportError:
pass
try:
import enchant.checker.wxSpellCheckerDialog
except ImportError:
pass
errors = []
# Naive recursion here would blow the stack, instead we
# simulate it with our own stack
tocheck = [enchant]
checked = []
while tocheck:
obj = tocheck.pop()
checked.append(obj)
newobjs = list(self._check_docstrings(obj,errors))
tocheck.extend([obj for obj in newobjs if obj not in checked])
self.assertEqual(len(errors),0)
def _check_docstrings(self,obj,errors):
import enchant
if hasattr(obj,"__doc__"):
skip_errors = [w for w in getattr(obj,"_DOC_ERRORS",[])]
chkr = enchant.checker.SpellChecker("en_AU",obj.__doc__,filters=[enchant.tokenize.URLFilter])
for err in chkr:
if len(err.word) == 1:
continue
if err.word.lower() in self.WORDS:
continue
if skip_errors and skip_errors[0] == err.word:
skip_errors.pop(0)
continue
errors.append((obj,err.word,err.wordpos))
msg = "\nDOCSTRING SPELLING ERROR: %s %s %d %s\n" % (obj,err.word,err.wordpos,chkr.suggest())
printf([msg],file=sys.stderr)
# Find and yield all child objects that should be checked
for name in dir(obj):
if name.startswith("__"):
continue
child = getattr(obj,name)
if hasattr(child,"__file__"):
if not hasattr(globals(),"__file__"):
continue
if not child.__file__.startswith(os.path.dirname(__file__)):
continue
else:
cmod = getattr(child,"__module__",None)
if not cmod:
cclass = getattr(child,"__class__",None)
cmod = getattr(cclass,"__module__",None)
if cmod and not cmod.startswith("enchant"):
continue
yield child
class TestInstallEnv(unittest.TestCase):
"""Run all testcases in a variety of install environments."""
def setUp(self):
self._tempDir = self._mkdtemp()
self._insDir = "build"
def tearDown(self):
import shutil
shutil.rmtree(self._tempDir)
def _mkdtemp(self):
import tempfile
return tempfile.mkdtemp()
def install(self):
import os, sys, shutil
insdir = os.path.join(self._tempDir,self._insDir)
os.makedirs(insdir)
shutil.copytree("enchant",os.path.join(insdir,"enchant"))
def runtests(self):
import os, sys
insdir = os.path.join(self._tempDir,self._insDir)
if str is not unicode and isinstance(insdir,unicode):
insdir = insdir.encode(sys.getfilesystemencoding())
os.environ["PYTHONPATH"] = insdir
testCmd = "import enchant, os; " \
"from os.path import abspath; " \
"assert abspath(os.curdir) in abspath(enchant.__file__); " \
"enchant._runtestsuite()"
res = runcmd("\"%s\" -c \"%s\"" % (sys.executable, testCmd), cwd=insdir)
self.assertEqual(res,0)
def test_basic(self):
"""Test proper functioning of TestInstallEnv suite."""
self.install()
self.runtests()
test_basic._DOC_ERRORS = ["TestInstallEnv"]
def test_UnicodeInstallPath(self):
"""Test installation in a path containing unicode chars."""
self._insDir = raw_unicode(r'test_\xe5\xe4\xf6_ing')
self.install()
self.runtests()
class TestPy2exe(unittest.TestCase):
"""Run all testcases inside a py2exe executable"""
_DOC_ERRORS = ["py","exe"]
def setUp(self):
self._tempDir = self._mkdtemp()
def tearDown(self):
import shutil
shutil.rmtree(self._tempDir)
def test_py2exe(self):
"""Test pyenchant running inside a py2exe executable."""
import os, sys, shutil
from os import path
from os.path import dirname
try:
import py2exe
except ImportError:
return
os.environ["PYTHONPATH"] = dirname(dirname(__file__))
setup_py = path.join(dirname(__file__),"..","tools","setup.py2exe.py")
if not path.exists(setup_py):
return
buildCmd = '%s %s -q py2exe --dist-dir="%s"'
buildCmd = buildCmd % (sys.executable,setup_py,self._tempDir)
res = runcmd(buildCmd)
self.assertEqual(res,0)
testCmd = self._tempDir + "\\test_pyenchant.exe"
self.assertTrue(os.path.exists(testCmd))
res = runcmd(testCmd)
self.assertEqual(res,0)
test_py2exe._DOC_ERRORS = ["py","exe"]
def _mkdtemp(self):
import tempfile
return tempfile.mkdtemp()
def buildtestsuite(recurse=True):
from enchant.checker.tests import TestChecker
from enchant.tokenize.tests import TestTokenization, TestFilters
from enchant.tokenize.tests import TestTokenizeEN
suite = unittest.TestSuite()
if recurse:
suite.addTest(unittest.makeSuite(TestInstallEnv))
suite.addTest(unittest.makeSuite(TestPy2exe))
suite.addTest(unittest.makeSuite(TestBroker))
suite.addTest(unittest.makeSuite(TestDict))
suite.addTest(unittest.makeSuite(TestPWL))
suite.addTest(unittest.makeSuite(TestUtils))
suite.addTest(unittest.makeSuite(TestDocStrings))
suite.addTest(unittest.makeSuite(TestChecker))
suite.addTest(unittest.makeSuite(TestTokenization))
suite.addTest(unittest.makeSuite(TestTokenizeEN))
suite.addTest(unittest.makeSuite(TestFilters))
return suite
def runtestsuite(recurse=False):
return unittest.TextTestRunner(verbosity=0).run(buildtestsuite(recurse=recurse))