Merge pull request #3523 from hackerwins/staticmethod

Add staticmethod in macros and apply it to maketrans
This commit is contained in:
Jeong YunWon
2022-01-22 18:54:35 +09:00
committed by GitHub
9 changed files with 36 additions and 37 deletions

View File

@@ -76,6 +76,7 @@ class TestDecorators(unittest.TestCase):
self.assertEqual(C.foo(), 42)
self.assertEqual(C().foo(), 42)
@unittest.skip("TODO: 3.10.x changed staticmethod to be callable")
def test_staticmethod_function(self):
@staticmethod
def notamethod(x):

View File

@@ -183,8 +183,6 @@ class ShlexTest(unittest.TestCase):
"%s: %s != %s" %
(self.data[i][0], l, self.data[i][1:]))
# TODO: RUSTPYTHON
@unittest.expectedFailure
def testSyntaxSplitAmpersandAndPipe(self):
"""Test handling of syntax splitting of &, |"""
# Could take these forms: &&, &, |&, ;&, ;;&
@@ -202,8 +200,6 @@ class ShlexTest(unittest.TestCase):
self.assertEqual(ref, result,
"While splitting '%s' [ws=%s]" % (ss, ws))
# TODO: RUSTPYTHON
@unittest.expectedFailure
def testSyntaxSplitSemicolon(self):
"""Test handling of syntax splitting of ;"""
# Could take these forms: ;, ;;, ;&, ;;&
@@ -220,8 +216,6 @@ class ShlexTest(unittest.TestCase):
self.assertEqual(ref, result,
"While splitting '%s' [ws=%s]" % (ss, ws))
# TODO: RUSTPYTHON
@unittest.expectedFailure
def testSyntaxSplitRedirect(self):
"""Test handling of syntax splitting of >"""
# of course, the same applies to <, |
@@ -237,8 +231,6 @@ class ShlexTest(unittest.TestCase):
self.assertEqual(ref, result,
"While splitting '%s' [ws=%s]" % (ss, ws))
# TODO: RUSTPYTHON
@unittest.expectedFailure
def testSyntaxSplitParen(self):
"""Test handling of syntax splitting of ()"""
# these should all parse to the same output
@@ -252,8 +244,6 @@ class ShlexTest(unittest.TestCase):
self.assertEqual(ref, result,
"While splitting '%s' [ws=%s]" % (ss, ws))
# TODO: RUSTPYTHON
@unittest.expectedFailure
def testSyntaxSplitCustom(self):
"""Test handling of syntax splitting with custom chars"""
ss = "~/a&&b-c --color=auto||d *.py?"
@@ -267,8 +257,6 @@ class ShlexTest(unittest.TestCase):
result = list(s)
self.assertEqual(ref, result, "While splitting '%s' [ws=True]" % ss)
# TODO: RUSTPYTHON
@unittest.expectedFailure
def testTokenTypes(self):
"""Test that tokens are split with types as expected."""
for source, expected in (
@@ -289,16 +277,12 @@ class ShlexTest(unittest.TestCase):
observed.append((t, tt))
self.assertEqual(observed, expected)
# TODO: RUSTPYTHON
@unittest.expectedFailure
def testPunctuationInWordChars(self):
"""Test that any punctuation chars are removed from wordchars"""
s = shlex.shlex('a_b__c', punctuation_chars='_')
self.assertNotIn('_', s.wordchars)
self.assertEqual(list(s), ['a', '_', 'b', '__', 'c'])
# TODO: RUSTPYTHON
@unittest.expectedFailure
def testPunctuationWithWhitespaceSplit(self):
"""Test that with whitespace_split, behaviour is as expected"""
s = shlex.shlex('a && b || c', punctuation_chars='&')
@@ -311,8 +295,6 @@ class ShlexTest(unittest.TestCase):
# white space
self.assertEqual(list(s), ['a', '&&', 'b', '||', 'c'])
# TODO: RUSTPYTHON
@unittest.expectedFailure
def testPunctuationWithPosix(self):
"""Test that punctuation_chars and posix behave correctly together."""
# see Issue #29132
@@ -321,8 +303,6 @@ class ShlexTest(unittest.TestCase):
s = shlex.shlex('f >\\"abc\\"', posix=True, punctuation_chars=True)
self.assertEqual(list(s), ['f', '>', '"abc"'])
# TODO: RUSTPYTHON
@unittest.expectedFailure
def testEmptyStringHandling(self):
"""Test that parsing of empty strings is correctly handled."""
# see Issue #21999
@@ -386,8 +366,6 @@ class ShlexTest(unittest.TestCase):
resplit = shlex.split(joined)
self.assertEqual(split_command, resplit)
# TODO: RUSTPYTHON
@unittest.expectedFailure
def testPunctuationCharsReadOnly(self):
punctuation_chars = "/|$%^"
shlex_instance = shlex.shlex(punctuation_chars=punctuation_chars)

View File

@@ -437,8 +437,9 @@ where
let build_func = match self.method_type.as_str() {
"method" => quote!(.build_method(ctx, class.clone())),
"classmethod" => quote!(.build_classmethod(ctx, class.clone())),
"staticmethod" => quote!(.build_staticmethod(ctx, class.clone())),
other => unreachable!(
"Only 'method' and 'classmethod' are supported, got {}",
"Only 'method', 'classmethod' and 'staticmethod' are supported, got {}",
other
),
};
@@ -954,13 +955,15 @@ where
{
assert!(ALL_ALLOWED_NAMES.contains(&attr_name.as_str()));
Ok(match attr_name.as_str() {
attr_name @ "pymethod" | attr_name @ "pyclassmethod" => Box::new(MethodItem {
inner: ContentItemInner {
index,
attr_name: attr_name.to_owned(),
},
method_type: attr_name.strip_prefix("py").unwrap().to_owned(),
}),
attr_name @ "pymethod" | attr_name @ "pyclassmethod" | attr_name @ "pystaticmethod" => {
Box::new(MethodItem {
inner: ContentItemInner {
index,
attr_name: attr_name.to_owned(),
},
method_type: attr_name.strip_prefix("py").unwrap().to_owned(),
})
}
"pyproperty" => Box::new(PropertyItem {
inner: ContentItemInner { index, attr_name },
}),

View File

@@ -14,6 +14,7 @@ use syn_ext::{
pub(crate) const ALL_ALLOWED_NAMES: &[&str] = &[
"pymethod",
"pyclassmethod",
"pystaticmethod",
"pyproperty",
"pyfunction",
"pyclass",

View File

@@ -1,4 +1,4 @@
use super::{pytype, PyClassMethod, PyStr, PyStrRef, PyTypeRef};
use super::{pytype, PyClassMethod, PyStaticMethod, PyStr, PyStrRef, PyTypeRef};
use crate::{
builtins::PyBoundMethod,
function::{FuncArgs, IntoPyNativeFunc, PyNativeFunc},
@@ -45,6 +45,14 @@ impl PyNativeFuncDef {
let callable = self.build_method(ctx, class).into();
PyClassMethod::new_ref(callable, ctx)
}
pub fn build_staticmethod(self, ctx: &PyContext, class: PyTypeRef) -> PyRef<PyStaticMethod> {
let callable = self.build_method(ctx, class).into();
PyRef::new_ref(
PyStaticMethod { callable },
ctx.types.staticmethod_type.clone(),
None,
)
}
}
#[pyclass(name = "builtin_function_or_method", module = false)]

View File

@@ -227,7 +227,7 @@ impl PyByteArray {
}
}
#[pymethod]
#[pystaticmethod]
fn maketrans(from: PyBytesInner, to: PyBytesInner, vm: &VirtualMachine) -> PyResult<Vec<u8>> {
PyBytesInner::maketrans(from, to, vm)
}

View File

@@ -149,7 +149,7 @@ impl PyBytes {
self.inner.contains(needle, vm)
}
#[pymethod]
#[pystaticmethod]
fn maketrans(from: PyBytesInner, to: PyBytesInner, vm: &VirtualMachine) -> PyResult<Vec<u8>> {
PyBytesInner::maketrans(from, to, vm)
}

View File

@@ -1141,7 +1141,7 @@ impl PyStr {
Ok(translated)
}
#[pymethod]
#[pystaticmethod]
fn maketrans(
dict_or_str: PyObjectRef,
to_str: OptionalArg<PyStrRef>,

View File

@@ -1,8 +1,8 @@
use super::{PyStr, PyTypeRef};
use crate::{
builtins::builtinfunc::PyBuiltinMethod,
function::IntoPyNativeFunc,
types::{Constructor, GetDescriptor},
function::{FuncArgs, IntoPyNativeFunc},
types::{Callable, Constructor, GetDescriptor},
PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, VirtualMachine,
};
@@ -59,7 +59,7 @@ impl PyStaticMethod {
}
}
#[pyimpl(with(GetDescriptor, Constructor), flags(BASETYPE, HAS_DICT))]
#[pyimpl(with(Callable, GetDescriptor, Constructor), flags(BASETYPE, HAS_DICT))]
impl PyStaticMethod {
#[pyproperty(magic)]
fn isabstractmethod(&self, vm: &VirtualMachine) -> PyObjectRef {
@@ -76,6 +76,14 @@ impl PyStaticMethod {
}
}
impl Callable for PyStaticMethod {
type Args = FuncArgs;
#[inline]
fn call(zelf: &crate::PyObjectView<Self>, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
vm.invoke(&zelf.callable, args)
}
}
pub fn init(context: &PyContext) {
PyStaticMethod::extend_class(context, &context.types.staticmethod_type);
}