Files
wehub-resource-sync 3454a55636
cffconvert / validate (push) Has been cancelled
ci-workflow / pre-commit (push) Has been cancelled
ci-workflow / Minimal NLTK Download Test (macos-latest) (push) Has been cancelled
ci-workflow / Minimal NLTK Download Test (ubuntu-latest) (push) Has been cancelled
ci-workflow / Minimal NLTK Download Test (windows-latest) (push) Has been cancelled
ci-workflow / Python 3.10 on macos-latest (push) Has been cancelled
ci-workflow / Python 3.11 on macos-latest (push) Has been cancelled
ci-workflow / Python 3.12 on macos-latest (push) Has been cancelled
ci-workflow / Python 3.13 on macos-latest (push) Has been cancelled
ci-workflow / Python 3.14 on macos-latest (push) Has been cancelled
ci-workflow / Python 3.14t on macos-latest (push) Has been cancelled
ci-workflow / Python 3.10 on ubuntu-latest (push) Has been cancelled
ci-workflow / Python 3.11 on ubuntu-latest (push) Has been cancelled
ci-workflow / Python 3.12 on ubuntu-latest (push) Has been cancelled
ci-workflow / Python 3.13 on ubuntu-latest (push) Has been cancelled
ci-workflow / Python 3.14 on ubuntu-latest (push) Has been cancelled
ci-workflow / Python 3.14t on ubuntu-latest (push) Has been cancelled
ci-workflow / Python 3.10 on windows-latest (push) Has been cancelled
ci-workflow / Python 3.11 on windows-latest (push) Has been cancelled
ci-workflow / Python 3.12 on windows-latest (push) Has been cancelled
ci-workflow / Python 3.13 on windows-latest (push) Has been cancelled
ci-workflow / Python 3.14 on windows-latest (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:46:15 +08:00

129 lines
4.1 KiB
Python

import unittest
from nltk.ccg import lexicon
from nltk.ccg.api import Direction, FunctionalCategory, PrimitiveCategory
class TestCCGDirection(unittest.TestCase):
# --- Parser and Unification Tests (PR #3556) ---
def test_parse_variable_direction(self):
"""
Ensures the string parser can successfully instantiate a Direction object
that correctly identifies as a variable.
"""
lex_str = r"""
:- S, NP
quickly => (S\_NP)/(S\_NP)
"""
lex = lexicon.fromstring(lex_str)
quickly_token = lex.categories("quickly")[0]
quickly_cat = quickly_token.categ()
var_direction = quickly_cat.res().dir()
self.assertTrue(
var_direction.is_variable(),
"Lexer failed to properly parse the direction as a variable.",
)
self.assertEqual(
var_direction.restrs(),
"_",
f"Expected restriction '_', got {var_direction.restrs()!r}",
)
def test_variable_direction_can_unify(self):
"""
Ensures that when a variable direction unifies with a concrete direction,
the substitution mapping is correctly extracted and returned to the caller.
"""
lex_str = r"""
:- S, NP
walked => S\NP
quickly => (S\_NP)/(S\_NP)
"""
lex = lexicon.fromstring(lex_str)
walked_cat = lex.categories("walked")[0].categ()
quickly_cat = lex.categories("quickly")[0].categ()
subs = quickly_cat.res().can_unify(walked_cat)
self.assertIsNotNone(subs, "Unification failed entirely.")
substituted_vars = [var for var, val in subs]
self.assertIn(
"_", substituted_vars, "can_unify dropped the direction variable mapping!"
)
def test_strict_regex_rejects_double_variable(self):
r"""
Ensures that the stricter APP_RE regex rejects invalid consecutive
variable modalities (e.g., `\__`).
"""
lex_str = r"""
:- S, NP
bad_word => (S\__NP)/(S\_NP)
"""
with self.assertRaises(AttributeError):
lex = lexicon.fromstring(lex_str)
def test_direction_equality_and_hashing(self):
"""
Ensures that a parsed variable direction (instantiated with a regex tuple)
and a hand-constructed variable direction (instantiated with a string)
evaluate as equal and share the same hash.
"""
manual_dir = Direction("\\", "_")
parsed_dir = Direction("\\", ("_", ""))
self.assertEqual(
manual_dir,
parsed_dir,
"Directions with coerced tuples do not evaluate as equal!",
)
self.assertEqual(
hash(manual_dir),
hash(parsed_dir),
"Directions with coerced tuples do not hash equally!",
)
# --- Substitution Tests (PR #3547 & Legacy) ---
def test_substitute_applies_to_direction(self):
"""
Direction substitutions must propagate through substitute().
Regression test updated to expect string restrictions instead of lists.
"""
res = PrimitiveCategory("S")
arg = PrimitiveCategory("NP")
variable_dir = Direction("/", "_")
category = FunctionalCategory(res, arg, variable_dir)
# Replaced list ["."] with string "."
new_restrictions = "."
subs = [("_", new_restrictions)]
result = category.substitute(subs)
self.assertFalse(result.dir().is_variable())
self.assertEqual(result.dir().restrs(), new_restrictions)
def test_substitute_no_op_on_concrete_direction(self):
"""
Substitution on a non-variable direction should be a no-op.
Regression test updated to pass and expect string restrictions.
"""
res = PrimitiveCategory("S")
arg = PrimitiveCategory("NP")
# Replaced list ["."] with string "."
concrete_dir = Direction("\\", ".")
category = FunctionalCategory(res, arg, concrete_dir)
result = category.substitute([("_", ",")])
self.assertEqual(result.dir().restrs(), ".")
if __name__ == "__main__":
unittest.main()