nltk--nltk
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
228 行
6.6 KiB
Plaintext
228 行
6.6 KiB
Plaintext
.. Copyright (C) 2001-2026 NLTK Project
|
|
.. For license information, see LICENSE.TXT
|
|
|
|
==========================================
|
|
Unit tests for the nltk.utilities module
|
|
==========================================
|
|
|
|
overridden()
|
|
~~~~~~~~~~~~
|
|
>>> from nltk.internals import overridden
|
|
|
|
The typical use case is in defining methods for an interface or
|
|
abstract base class, in such a way that subclasses don't have to
|
|
implement all of the methods:
|
|
|
|
>>> class EaterI(object):
|
|
... '''Subclass must define eat() or batch_eat().'''
|
|
... def eat(self, food):
|
|
... if overridden(self.batch_eat):
|
|
... return self.batch_eat([food])[0]
|
|
... else:
|
|
... raise NotImplementedError()
|
|
... def batch_eat(self, foods):
|
|
... return [self.eat(food) for food in foods]
|
|
|
|
As long as a subclass implements one method, it will be used to
|
|
perform the other method:
|
|
|
|
>>> class GoodEater1(EaterI):
|
|
... def eat(self, food):
|
|
... return 'yum'
|
|
>>> GoodEater1().eat('steak')
|
|
'yum'
|
|
>>> GoodEater1().batch_eat(['steak', 'peas'])
|
|
['yum', 'yum']
|
|
|
|
>>> class GoodEater2(EaterI):
|
|
... def batch_eat(self, foods):
|
|
... return ['yum' for food in foods]
|
|
>>> GoodEater2().eat('steak')
|
|
'yum'
|
|
>>> GoodEater2().batch_eat(['steak', 'peas'])
|
|
['yum', 'yum']
|
|
|
|
But if a subclass doesn't implement either one, then they'll get an
|
|
error when they try to call them. (nb this is better than infinite
|
|
recursion):
|
|
|
|
>>> class BadEater1(EaterI):
|
|
... pass
|
|
>>> BadEater1().eat('steak')
|
|
Traceback (most recent call last):
|
|
. . .
|
|
NotImplementedError
|
|
>>> BadEater1().batch_eat(['steak', 'peas'])
|
|
Traceback (most recent call last):
|
|
. . .
|
|
NotImplementedError
|
|
|
|
Trying to use the abstract base class itself will also result in an
|
|
error:
|
|
|
|
>>> class EaterI(EaterI):
|
|
... pass
|
|
>>> EaterI().eat('steak')
|
|
Traceback (most recent call last):
|
|
. . .
|
|
NotImplementedError
|
|
>>> EaterI().batch_eat(['steak', 'peas'])
|
|
Traceback (most recent call last):
|
|
. . .
|
|
NotImplementedError
|
|
|
|
It's ok to use intermediate abstract classes:
|
|
|
|
>>> class AbstractEater(EaterI):
|
|
... pass
|
|
|
|
>>> class GoodEater3(AbstractEater):
|
|
... def eat(self, food):
|
|
... return 'yum'
|
|
...
|
|
>>> GoodEater3().eat('steak')
|
|
'yum'
|
|
>>> GoodEater3().batch_eat(['steak', 'peas'])
|
|
['yum', 'yum']
|
|
|
|
>>> class GoodEater4(AbstractEater):
|
|
... def batch_eat(self, foods):
|
|
... return ['yum' for food in foods]
|
|
>>> GoodEater4().eat('steak')
|
|
'yum'
|
|
>>> GoodEater4().batch_eat(['steak', 'peas'])
|
|
['yum', 'yum']
|
|
|
|
>>> class BadEater2(AbstractEater):
|
|
... pass
|
|
>>> BadEater2().eat('steak')
|
|
Traceback (most recent call last):
|
|
. . .
|
|
NotImplementedError
|
|
>>> BadEater2().batch_eat(['steak', 'peas'])
|
|
Traceback (most recent call last):
|
|
. . .
|
|
NotImplementedError
|
|
|
|
Here's some extra tests:
|
|
|
|
>>> class A(object):
|
|
... def f(x): pass
|
|
>>> class B(A):
|
|
... def f(x): pass
|
|
>>> class C(A): pass
|
|
>>> class D(B): pass
|
|
|
|
>>> overridden(A().f)
|
|
False
|
|
>>> overridden(B().f)
|
|
True
|
|
>>> overridden(C().f)
|
|
False
|
|
>>> overridden(D().f)
|
|
True
|
|
|
|
It works for classic classes, too:
|
|
|
|
>>> class A:
|
|
... def f(x): pass
|
|
>>> class B(A):
|
|
... def f(x): pass
|
|
>>> class C(A): pass
|
|
>>> class D(B): pass
|
|
>>> overridden(A().f)
|
|
False
|
|
>>> overridden(B().f)
|
|
True
|
|
>>> overridden(C().f)
|
|
False
|
|
>>> overridden(D().f)
|
|
True
|
|
|
|
|
|
read_str()
|
|
~~~~~~~~~~~~
|
|
>>> from nltk.internals import read_str
|
|
|
|
Test valid scenarios
|
|
|
|
>>> read_str("'valid string'", 0)
|
|
('valid string', 14)
|
|
|
|
Now test invalid scenarios
|
|
|
|
>>> read_str("should error", 0)
|
|
Traceback (most recent call last):
|
|
...
|
|
nltk.internals.ReadError: Expected open quote at 0
|
|
>>> read_str("'should error", 0)
|
|
Traceback (most recent call last):
|
|
...
|
|
nltk.internals.ReadError: Expected close quote at 1
|
|
|
|
=====================================================
|
|
_validate_java_options (CVE-2026-12841, CWE-88)
|
|
=====================================================
|
|
|
|
>>> from nltk.internals import _validate_java_options
|
|
|
|
Safe JVM tuning flags are permitted (no exception raised):
|
|
|
|
>>> _validate_java_options(["-Xmx512m"])
|
|
>>> _validate_java_options(["-Xms128m"])
|
|
>>> _validate_java_options(["-Xss4m"])
|
|
|
|
The legacy short aliases (-mx / -ms / -ss) that Stanford and CoreNLP
|
|
wrappers pass are equivalent and also permitted:
|
|
|
|
>>> _validate_java_options(["-mx2g"])
|
|
>>> _validate_java_options(["-ms128m"])
|
|
>>> _validate_java_options(["-ss4m"])
|
|
>>> _validate_java_options(["-XX:+UseG1GC"])
|
|
>>> _validate_java_options(["-verbose:gc"])
|
|
>>> _validate_java_options(["-server"])
|
|
>>> _validate_java_options(["-client"])
|
|
>>> _validate_java_options(["-Dsome.property=value"])
|
|
>>> _validate_java_options(["-Xmx1g", "-Dsome.key=val", "-server"])
|
|
|
|
Agent-loading and JDWP flags are blocked:
|
|
|
|
>>> _validate_java_options(["-agentlib:jdwp=transport=dt_socket,server=y"]) # doctest: +ELLIPSIS
|
|
Traceback (most recent call last):
|
|
...
|
|
ValueError: java_options contains a disallowed JVM/launcher flag: '-agentlib:jdwp=transport=dt_socket,server=y'...
|
|
|
|
>>> _validate_java_options(["-agentpath:/tmp/agent.so"]) # doctest: +ELLIPSIS
|
|
Traceback (most recent call last):
|
|
...
|
|
ValueError: java_options contains a disallowed JVM/launcher flag: '-agentpath:/tmp/agent.so'...
|
|
|
|
>>> _validate_java_options(["-javaagent:/tmp/agent.jar"]) # doctest: +ELLIPSIS
|
|
Traceback (most recent call last):
|
|
...
|
|
ValueError: java_options contains a disallowed JVM/launcher flag: '-javaagent:/tmp/agent.jar'...
|
|
|
|
>>> _validate_java_options(["-Xrunjdwp:transport=dt_socket"]) # doctest: +ELLIPSIS
|
|
Traceback (most recent call last):
|
|
...
|
|
ValueError: java_options contains a disallowed JVM/launcher flag: '-Xrunjdwp:transport=dt_socket'...
|
|
|
|
-jar and @argfile bypasses are also blocked:
|
|
|
|
>>> _validate_java_options(["-jar", "/tmp/evil.jar"]) # doctest: +ELLIPSIS
|
|
Traceback (most recent call last):
|
|
...
|
|
ValueError: java_options contains a disallowed JVM/launcher flag: '-jar'...
|
|
|
|
>>> _validate_java_options(["@evil.args"]) # doctest: +ELLIPSIS
|
|
Traceback (most recent call last):
|
|
...
|
|
ValueError: java_options contains a disallowed Java argument file reference: '@evil.args'...
|
|
|
|
Matching is case-insensitive:
|
|
|
|
>>> _validate_java_options(["-AGENTLIB:jdwp=transport=dt_socket"]) # doctest: +ELLIPSIS
|
|
Traceback (most recent call last):
|
|
...
|
|
ValueError: java_options contains a disallowed JVM/launcher flag: '-AGENTLIB:jdwp=transport=dt_socket'...
|