mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Set builtin __doc__, __module__, and datetime signatures (#8897)
* Set builtin __doc__, __module__, and datetime signatures Expose empty doc-db member entries as ''. Heap __dict__ and __weakref__ getsets carry their descriptor docs. Member repr uses the qualified type name. __module__ is collections for the deque iterators, _csv for Dialect, ctypes for ArgumentError and CField, _lzma for LZMAError, operator for the getter types, pickle for PickleBuffer, _ssl for MemoryBIO, SSLSession, _SSLContext and _SSLSocket, weakref for the proxy types, and posix (nt on Windows) for times_result and uname_result. unicodedata's copied UCD functions set __module__ to unicodedata. _testinternalcapi function docs and weakproxy.__str__ use the stored text. datetime replace defaults render as unchanged, __replace__ is ($self, /, **changes) and binds through replace, now defaults tz to None, and fromisoformat and tzinfo methods name the parameter object. Assisted-by: Grok:grok-4.7 * Move doctext helpers above the test module db_slice and docs sat after mod tests. Remove expectedFailure from test_html_doc, test_text_doc, test_help_output_redirect, test_method_aliases, and test_long_signatures. Assisted-by: Grok:grok-4.7
This commit is contained in:
1 parent
a242ed1457
commit
d54a4c5932
22 files changed
+190
-95
No files matched your search
Vendored
-5
@@ -419,7 +419,6 @@ class PydocDocTest(unittest.TestCase):
|
||||
def tearDown(self):
|
||||
self.assertIs(sys.modules['pydoc'], pydoc)
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
@unittest.skipIf(hasattr(sys, 'gettrace') and sys.gettrace(),
|
||||
'trace function introduces __locals__ unexpectedly')
|
||||
@requires_docstrings
|
||||
@@ -438,7 +437,6 @@ class PydocDocTest(unittest.TestCase):
|
||||
self.assertIn(mod_file, result)
|
||||
self.assertIn(doc_loc, result)
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
@unittest.skipIf(hasattr(sys, 'gettrace') and sys.gettrace(),
|
||||
'trace function introduces __locals__ unexpectedly')
|
||||
@requires_docstrings
|
||||
@@ -708,7 +706,6 @@ class PydocDocTest(unittest.TestCase):
|
||||
expected = missing_pattern % "abd"
|
||||
self.assertEqual(expected, buf.getvalue().strip().replace('\n', os.linesep))
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
@unittest.skipIf(hasattr(sys, 'gettrace') and sys.gettrace(),
|
||||
'trace function introduces __locals__ unexpectedly')
|
||||
@unittest.mock.patch('pydoc.pager')
|
||||
@@ -1073,7 +1070,6 @@ class PydocDocTest(unittest.TestCase):
|
||||
methods = pydoc.allmethods(TestClass)
|
||||
self.assertDictEqual(methods, expected)
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
@requires_docstrings
|
||||
def test_method_aliases(self):
|
||||
class A:
|
||||
@@ -1164,7 +1160,6 @@ class B(A)
|
||||
for expected_line in expected_lines:
|
||||
self.assertIn(expected_line, as_text)
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON
|
||||
def test_long_signatures(self):
|
||||
from collections.abc import Callable
|
||||
from typing import Literal, Annotated
|
||||
|
||||
@@ -450,13 +450,20 @@ fn attr_doc_expr(self_ty: Option<&syn::Type>, attr: &str, rust_doc: Option<Strin
|
||||
<#ty as ::rustpython_vm::class::PyClassDef>::ATTR_DOCS,
|
||||
#attr,
|
||||
);
|
||||
match FOUND {
|
||||
Some((offset, len)) if len != 0 => ::rustpython_vm::function::ItemDoc {
|
||||
text: None,
|
||||
offset,
|
||||
len,
|
||||
},
|
||||
_ => ::rustpython_vm::function::ItemDoc::NONE,
|
||||
if let Some((offset, len)) = FOUND {
|
||||
if len != 0 {
|
||||
::rustpython_vm::function::ItemDoc {
|
||||
text: None,
|
||||
offset,
|
||||
len,
|
||||
}
|
||||
} else if offset == u32::MAX {
|
||||
::rustpython_vm::function::ItemDoc::EMPTY
|
||||
} else {
|
||||
::rustpython_vm::function::ItemDoc::NONE
|
||||
}
|
||||
} else {
|
||||
::rustpython_vm::function::ItemDoc::NONE
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -18,7 +18,7 @@ mod _datetime {
|
||||
hash::PyHash,
|
||||
wtf8::{CodePoint, Wtf8Buf},
|
||||
},
|
||||
function::{FuncArgs, OptionalArg, PyComparisonValue},
|
||||
function::{ArgumentError, FromArgs, FuncArgs, OptionalArg, Param, PyComparisonValue},
|
||||
protocol::{PyNumber, PyNumberMethods},
|
||||
types::{AsNumber, Comparable, Constructor, Hashable, PyComparisonOp, Representable},
|
||||
};
|
||||
@@ -1948,7 +1948,8 @@ mod _datetime {
|
||||
}
|
||||
|
||||
#[pyclassmethod]
|
||||
fn fromisoformat(cls: PyTypeRef, dtstr: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
fn fromisoformat(cls: PyTypeRef, object: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
let dtstr = object;
|
||||
let Some(s) = dtstr.downcast_ref::<PyStr>() else {
|
||||
return Err(vm.new_type_error("fromisoformat: argument must be str"));
|
||||
};
|
||||
@@ -2069,7 +2070,6 @@ mod _datetime {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
#[pymethod(name = "__replace__")]
|
||||
fn replace(zelf: &Py<Self>, args: DateReplaceArgs, vm: &VirtualMachine) -> PyResult {
|
||||
new_date_subclass(
|
||||
args.year.unwrap_or_else(|| zelf.y()),
|
||||
@@ -2080,6 +2080,11 @@ mod _datetime {
|
||||
)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn __replace__(zelf: &Py<Self>, changes: ReplaceChanges, vm: &VirtualMachine) -> PyResult {
|
||||
Self::replace(zelf, changes.args.bind_for(vm, "replace")?, vm)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn __reduce__(zelf: &Py<Self>, vm: &VirtualMachine) -> PyRef<PyTuple> {
|
||||
let state = vm.ctx.new_bytes(zelf.state_bytes().to_vec());
|
||||
@@ -2121,13 +2126,29 @@ mod _datetime {
|
||||
day: PyObjectRef,
|
||||
}
|
||||
|
||||
/// `**changes` in the text signature. Binding still accepts the same
|
||||
/// arguments as `replace`, and a failure names `replace`.
|
||||
struct ReplaceChanges {
|
||||
args: FuncArgs,
|
||||
}
|
||||
|
||||
impl FromArgs for ReplaceChanges {
|
||||
const PARAMS: Option<&'static [Param]> = Some(&[Param::var_keyword("changes")]);
|
||||
|
||||
fn from_args(_vm: &VirtualMachine, args: &mut FuncArgs) -> Result<Self, ArgumentError> {
|
||||
Ok(Self {
|
||||
args: core::mem::take(args),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(FromArgs)]
|
||||
struct DateReplaceArgs {
|
||||
#[pyarg(any, optional)]
|
||||
#[pyarg(any, optional, py_default = "unchanged")]
|
||||
year: OptionalArg<i32>,
|
||||
#[pyarg(any, optional)]
|
||||
#[pyarg(any, optional, py_default = "unchanged")]
|
||||
month: OptionalArg<i32>,
|
||||
#[pyarg(any, optional)]
|
||||
#[pyarg(any, optional, py_default = "unchanged")]
|
||||
day: OptionalArg<i32>,
|
||||
}
|
||||
|
||||
@@ -2327,22 +2348,23 @@ mod _datetime {
|
||||
#[pyclass(with(Constructor), flags(BASETYPE))]
|
||||
impl PyTzInfo {
|
||||
#[pymethod]
|
||||
fn tzname(&self, _dt: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
fn tzname(&self, _object: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
tzinfo_nogo("tzname", vm)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn utcoffset(&self, _dt: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
fn utcoffset(&self, _object: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
tzinfo_nogo("utcoffset", vm)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn dst(&self, _dt: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
fn dst(&self, _object: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
tzinfo_nogo("dst", vm)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn fromutc(zelf: PyObjectRef, dt: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
fn fromutc(zelf: PyObjectRef, object: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
let dt = object;
|
||||
let Some(dtobj) = as_datetime(&dt) else {
|
||||
return Err(vm.new_type_error("fromutc: argument must be a datetime"));
|
||||
};
|
||||
@@ -2530,25 +2552,29 @@ mod _datetime {
|
||||
#[pyclass(with(Constructor, Comparable, Hashable, Representable))]
|
||||
impl PyTimeZone {
|
||||
#[pymethod]
|
||||
fn tzname(zelf: &Py<Self>, dt: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyStrRef> {
|
||||
fn tzname(zelf: &Py<Self>, object: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyStrRef> {
|
||||
let dt = object;
|
||||
timezone_check_argument(&dt, "tzname", vm)?;
|
||||
Ok(Self::name_str(zelf, vm))
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn utcoffset(&self, dt: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyRef<PyDelta>> {
|
||||
fn utcoffset(&self, object: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyRef<PyDelta>> {
|
||||
let dt = object;
|
||||
timezone_check_argument(&dt, "utcoffset", vm)?;
|
||||
Ok(self.offset.clone())
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn dst(&self, dt: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
fn dst(&self, object: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
let dt = object;
|
||||
timezone_check_argument(&dt, "dst", vm)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn fromutc(zelf: &Py<Self>, dt: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
fn fromutc(zelf: &Py<Self>, object: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
let dt = object;
|
||||
let Some(dtobj) = as_datetime(&dt) else {
|
||||
return Err(vm.new_type_error("fromutc: argument must be a datetime"));
|
||||
};
|
||||
@@ -2800,17 +2826,17 @@ mod _datetime {
|
||||
|
||||
#[derive(FromArgs)]
|
||||
struct TimeReplaceArgs {
|
||||
#[pyarg(any, optional)]
|
||||
#[pyarg(any, optional, py_default = "unchanged")]
|
||||
hour: OptionalArg<i32>,
|
||||
#[pyarg(any, optional)]
|
||||
#[pyarg(any, optional, py_default = "unchanged")]
|
||||
minute: OptionalArg<i32>,
|
||||
#[pyarg(any, optional)]
|
||||
#[pyarg(any, optional, py_default = "unchanged")]
|
||||
second: OptionalArg<i32>,
|
||||
#[pyarg(any, optional)]
|
||||
#[pyarg(any, optional, py_default = "unchanged")]
|
||||
microsecond: OptionalArg<i32>,
|
||||
#[pyarg(any, optional)]
|
||||
#[pyarg(any, optional, py_default = "unchanged")]
|
||||
tzinfo: OptionalArg<PyObjectRef>,
|
||||
#[pyarg(named, optional)]
|
||||
#[pyarg(named, optional, py_default = "unchanged")]
|
||||
fold: OptionalArg<i32>,
|
||||
}
|
||||
|
||||
@@ -2940,7 +2966,6 @@ mod _datetime {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
#[pymethod(name = "__replace__")]
|
||||
fn replace(zelf: &Py<Self>, args: TimeReplaceArgs, vm: &VirtualMachine) -> PyResult {
|
||||
let tzinfo = match args.tzinfo {
|
||||
OptionalArg::Present(tz) => tzinfo_arg(tz, vm),
|
||||
@@ -2958,8 +2983,14 @@ mod _datetime {
|
||||
)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn __replace__(zelf: &Py<Self>, changes: ReplaceChanges, vm: &VirtualMachine) -> PyResult {
|
||||
Self::replace(zelf, changes.args.bind_for(vm, "replace")?, vm)
|
||||
}
|
||||
|
||||
#[pyclassmethod]
|
||||
fn fromisoformat(cls: PyTypeRef, tstr: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
fn fromisoformat(cls: PyTypeRef, object: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
let tstr = object;
|
||||
let Some(s) = tstr.downcast_ref::<PyStr>() else {
|
||||
return Err(vm.new_type_error("fromisoformat: argument must be str"));
|
||||
};
|
||||
@@ -3576,7 +3607,7 @@ mod _datetime {
|
||||
|
||||
#[derive(FromArgs)]
|
||||
struct NowArgs {
|
||||
#[pyarg(any, optional)]
|
||||
#[pyarg(any, optional, py_default = "None")]
|
||||
tz: OptionalArg<PyObjectRef>,
|
||||
}
|
||||
|
||||
@@ -3608,23 +3639,23 @@ mod _datetime {
|
||||
|
||||
#[derive(FromArgs)]
|
||||
struct DateTimeReplaceArgs {
|
||||
#[pyarg(any, optional)]
|
||||
#[pyarg(any, optional, py_default = "unchanged")]
|
||||
year: OptionalArg<i32>,
|
||||
#[pyarg(any, optional)]
|
||||
#[pyarg(any, optional, py_default = "unchanged")]
|
||||
month: OptionalArg<i32>,
|
||||
#[pyarg(any, optional)]
|
||||
#[pyarg(any, optional, py_default = "unchanged")]
|
||||
day: OptionalArg<i32>,
|
||||
#[pyarg(any, optional)]
|
||||
#[pyarg(any, optional, py_default = "unchanged")]
|
||||
hour: OptionalArg<i32>,
|
||||
#[pyarg(any, optional)]
|
||||
#[pyarg(any, optional, py_default = "unchanged")]
|
||||
minute: OptionalArg<i32>,
|
||||
#[pyarg(any, optional)]
|
||||
#[pyarg(any, optional, py_default = "unchanged")]
|
||||
second: OptionalArg<i32>,
|
||||
#[pyarg(any, optional)]
|
||||
#[pyarg(any, optional, py_default = "unchanged")]
|
||||
microsecond: OptionalArg<i32>,
|
||||
#[pyarg(any, optional)]
|
||||
#[pyarg(any, optional, py_default = "unchanged")]
|
||||
tzinfo: OptionalArg<PyObjectRef>,
|
||||
#[pyarg(named, optional)]
|
||||
#[pyarg(named, optional, py_default = "unchanged")]
|
||||
fold: OptionalArg<i32>,
|
||||
}
|
||||
|
||||
@@ -3788,7 +3819,8 @@ mod _datetime {
|
||||
}
|
||||
|
||||
#[pyclassmethod]
|
||||
fn fromisoformat(cls: PyTypeRef, dtstr: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
fn fromisoformat(cls: PyTypeRef, object: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
let dtstr = object;
|
||||
let Some(s) = dtstr.downcast_ref::<PyStr>() else {
|
||||
return Err(vm.new_type_error("fromisoformat: argument must be str"));
|
||||
};
|
||||
@@ -4053,7 +4085,6 @@ mod _datetime {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
#[pymethod(name = "__replace__")]
|
||||
fn replace(zelf: &Py<Self>, args: DateTimeReplaceArgs, vm: &VirtualMachine) -> PyResult {
|
||||
let tzinfo = match args.tzinfo {
|
||||
OptionalArg::Present(tz) => tzinfo_arg(tz, vm),
|
||||
@@ -4075,6 +4106,11 @@ mod _datetime {
|
||||
)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn __replace__(zelf: &Py<Self>, changes: ReplaceChanges, vm: &VirtualMachine) -> PyResult {
|
||||
Self::replace(zelf, changes.args.bind_for(vm, "replace")?, vm)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn astimezone(zelf: &Py<Self>, args: AstimezoneArgs, vm: &VirtualMachine) -> PyResult {
|
||||
let tz = args.tz.unwrap_or_none(vm);
|
||||
|
||||
@@ -74,7 +74,7 @@ mod _csv {
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(module = "csv", name = "Dialect")]
|
||||
#[pyclass(module = "_csv", name = "Dialect")]
|
||||
#[derive(Debug, PyPayload, Clone)]
|
||||
struct PyDialect {
|
||||
delimiter: u8,
|
||||
|
||||
@@ -79,7 +79,7 @@ mod _lzma {
|
||||
#[pyattr(once, name = "LZMAError")]
|
||||
fn error(vm: &VirtualMachine) -> PyTypeRef {
|
||||
vm.ctx.new_exception_type_with_doc(
|
||||
"lzma",
|
||||
"_lzma",
|
||||
"LZMAError",
|
||||
Some(vec![vm.ctx.exceptions.exception_type.to_owned()]),
|
||||
const { ItemDoc::db("_lzma.LZMAError") },
|
||||
|
||||
@@ -841,7 +841,7 @@ mod _ssl {
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(module = "ssl", name = "_SSLContext")]
|
||||
#[pyclass(module = "_ssl", name = "_SSLContext")]
|
||||
#[derive(PyPayload)]
|
||||
struct PySslContext {
|
||||
ctx: PyRwLock<SslContextBuilder>,
|
||||
@@ -2482,7 +2482,7 @@ mod _ssl {
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(module = "ssl", name = "_SSLSocket", traverse)]
|
||||
#[pyclass(module = "_ssl", name = "_SSLSocket", traverse)]
|
||||
#[derive(PyPayload)]
|
||||
struct PySslSocket {
|
||||
ctx: PyRwLock<PyRef<PySslContext>>,
|
||||
@@ -3298,7 +3298,7 @@ mod _ssl {
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(module = "ssl", name = "SSLSession", unhashable = true)]
|
||||
#[pyclass(module = "_ssl", name = "SSLSession", unhashable = true)]
|
||||
#[derive(PyPayload)]
|
||||
struct PySslSession {
|
||||
session: *mut sys::SSL_SESSION,
|
||||
@@ -3358,7 +3358,7 @@ mod _ssl {
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(module = "ssl", name = "MemoryBIO")]
|
||||
#[pyclass(module = "_ssl", name = "MemoryBIO")]
|
||||
#[derive(PyPayload)]
|
||||
struct PySslMemoryBio {
|
||||
bio: *mut sys::BIO,
|
||||
|
||||
@@ -68,7 +68,7 @@ mod _pickle {
|
||||
// PickleBuffer
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(module = "_pickle", name = "PickleBuffer")]
|
||||
#[pyclass(module = "pickle", name = "PickleBuffer")]
|
||||
#[derive(Debug, PyPayload)]
|
||||
pub(super) struct PyPickleBuffer {
|
||||
buffer: PyRwLock<Option<PyBuffer>>,
|
||||
|
||||
@@ -319,7 +319,7 @@ mod _ssl {
|
||||
|
||||
// SSLContext - manages TLS configuration
|
||||
#[pyattr]
|
||||
#[pyclass(name = "_SSLContext", module = "ssl", traverse)]
|
||||
#[pyclass(name = "_SSLContext", module = "_ssl", traverse)]
|
||||
#[derive(Debug, PyPayload)]
|
||||
struct PySSLContext {
|
||||
#[pytraverse(skip)]
|
||||
@@ -2058,7 +2058,7 @@ mod _ssl {
|
||||
|
||||
// SSLSocket - represents a TLS-wrapped socket
|
||||
#[pyattr]
|
||||
#[pyclass(name = "_SSLSocket", module = "ssl", traverse)]
|
||||
#[pyclass(name = "_SSLSocket", module = "_ssl", traverse)]
|
||||
#[derive(Debug, PyPayload)]
|
||||
pub(crate) struct PySSLSocket {
|
||||
io: SocketOrBio,
|
||||
@@ -3898,7 +3898,7 @@ mod _ssl {
|
||||
|
||||
// MemoryBIO - provides in-memory buffer for SSL/TLS I/O
|
||||
#[pyattr]
|
||||
#[pyclass(name = "MemoryBIO", module = "ssl")]
|
||||
#[pyclass(name = "MemoryBIO", module = "_ssl")]
|
||||
#[derive(Debug, PyPayload)]
|
||||
struct PyMemoryBIO {
|
||||
inner: PyMutex<rustpython_host_env::ssl::MemoryBio>,
|
||||
@@ -3979,7 +3979,7 @@ mod _ssl {
|
||||
// SSLSession - represents a cached SSL session
|
||||
// NOTE: This is an EMULATION - actual session data is managed by Rustls internally
|
||||
#[pyattr]
|
||||
#[pyclass(name = "SSLSession", module = "ssl", unhashable = true)]
|
||||
#[pyclass(name = "SSLSession", module = "_ssl", unhashable = true)]
|
||||
#[derive(Debug, PyPayload)]
|
||||
struct PySSLSession {
|
||||
context_identity: Arc<()>,
|
||||
|
||||
@@ -179,7 +179,7 @@ mod _ssl {
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "_SSLContext", module = "ssl", traverse)]
|
||||
#[pyclass(name = "_SSLContext", module = "_ssl", traverse)]
|
||||
#[derive(Debug, PyPayload)]
|
||||
struct PySSLContext {
|
||||
#[pytraverse(skip)]
|
||||
@@ -665,7 +665,7 @@ mod _ssl {
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "MemoryBIO", module = "ssl")]
|
||||
#[pyclass(name = "MemoryBIO", module = "_ssl")]
|
||||
#[derive(Debug, PyPayload)]
|
||||
struct PyMemoryBIO {
|
||||
inner: PyMutex<rustpython_host_env::ssl::MemoryBio>,
|
||||
@@ -737,7 +737,7 @@ mod _ssl {
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "SSLSession", module = "ssl", unhashable = true)]
|
||||
#[pyclass(name = "SSLSession", module = "_ssl", unhashable = true)]
|
||||
#[derive(Debug, PyPayload)]
|
||||
struct PySSLSession {
|
||||
session_id: Vec<u8>,
|
||||
|
||||
@@ -61,7 +61,9 @@ mod unicodedata {
|
||||
"normalize",
|
||||
"numeric",
|
||||
] {
|
||||
module.set_attr(attr, ucd.get_attr(attr, vm)?, vm)?;
|
||||
let func = ucd.get_attr(attr, vm)?;
|
||||
func.set_attr("__module__", vm.ctx.new_str("unicodedata"), vm)?;
|
||||
module.set_attr(attr, func, vm)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -1507,7 +1507,7 @@ impl Representable for PyMemberDescriptor {
|
||||
Ok(format!(
|
||||
"<member '{}' of '{}' objects>",
|
||||
zelf.common.name,
|
||||
zelf.common.typ.name(),
|
||||
zelf.common.typ.slot_name(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2822,9 +2822,11 @@ impl Constructor for PyType {
|
||||
.iter()
|
||||
.any(|base| base.attributes.contains(__dict__));
|
||||
if !typ.attributes.contains(__dict__) && !has_inherited_dict {
|
||||
let descriptor =
|
||||
vm.ctx
|
||||
.new_getset("__dict__", &typ, subtype_get_dict, subtype_set_dict);
|
||||
let getset = super::PyGetSet::new("__dict__", &typ, &vm.ctx)
|
||||
.with_get(subtype_get_dict)
|
||||
.with_set(subtype_set_dict)
|
||||
.with_doc(ItemDoc::static_text("dictionary for instance variables"));
|
||||
let descriptor = PyRef::new_ref(getset, vm.ctx.types.getset_type.to_owned(), None);
|
||||
typ.attributes.set(__dict__, descriptor.into());
|
||||
}
|
||||
}
|
||||
@@ -2838,12 +2840,13 @@ impl Constructor for PyType {
|
||||
.iter()
|
||||
.any(|base| base.attributes.contains(__weakref__));
|
||||
if !typ.attributes.contains(__weakref__) && !has_inherited_weakref {
|
||||
let descriptor = vm.ctx.new_getset(
|
||||
"__weakref__",
|
||||
&typ,
|
||||
subtype_get_weakref,
|
||||
subtype_set_weakref,
|
||||
);
|
||||
let getset = super::PyGetSet::new("__weakref__", &typ, &vm.ctx)
|
||||
.with_get(subtype_get_weakref)
|
||||
.with_set(subtype_set_weakref)
|
||||
.with_doc(ItemDoc::static_text(
|
||||
"list of weak references to the object",
|
||||
));
|
||||
let descriptor = PyRef::new_ref(getset, vm.ctx.types.getset_type.to_owned(), None);
|
||||
typ.attributes.set(__weakref__, descriptor.into());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ use crate::{
|
||||
},
|
||||
};
|
||||
|
||||
#[pyclass(module = false, name = "weakproxy", unhashable = true)]
|
||||
#[pyclass(module = "weakref", name = "weakproxy", unhashable = true)]
|
||||
#[derive(Debug)]
|
||||
#[repr(transparent)]
|
||||
pub struct PyWeakProxy(PyWeak);
|
||||
@@ -78,7 +78,7 @@ impl PyWeakProxy {
|
||||
}
|
||||
|
||||
#[pyclass(
|
||||
module = false,
|
||||
module = "weakref",
|
||||
name = "weakcallableproxy",
|
||||
base = PyWeakProxy,
|
||||
ctx = "weakcallableproxy_type",
|
||||
@@ -123,6 +123,7 @@ impl PyWeakProxy {
|
||||
self.0.upgrade().ok_or_else(|| new_reference_error(vm))
|
||||
}
|
||||
|
||||
/// Return str(self).
|
||||
#[pymethod]
|
||||
fn __str__(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
|
||||
zelf.try_upgrade(vm)?.str(vm)
|
||||
|
||||
+11
-8
@@ -231,14 +231,17 @@ pub const fn attr_name_present(table: &[&str], name: &str) -> bool {
|
||||
#[must_use]
|
||||
pub fn class_attr_item_doc<T: PyClassDef + ?Sized>(name: &str) -> ItemDoc {
|
||||
#[cfg(feature = "doc")]
|
||||
if let Some((offset, len)) = attr_doc(T::ATTR_DOCS, name)
|
||||
&& len != 0
|
||||
{
|
||||
return ItemDoc {
|
||||
text: None,
|
||||
offset,
|
||||
len,
|
||||
};
|
||||
if let Some((offset, len)) = attr_doc(T::ATTR_DOCS, name) {
|
||||
if len != 0 {
|
||||
return ItemDoc {
|
||||
text: None,
|
||||
offset,
|
||||
len,
|
||||
};
|
||||
}
|
||||
if offset == u32::MAX {
|
||||
return ItemDoc::EMPTY;
|
||||
}
|
||||
}
|
||||
#[cfg(not(feature = "doc"))]
|
||||
let _ = name;
|
||||
|
||||
@@ -23,6 +23,14 @@ impl ItemDoc {
|
||||
len: 0,
|
||||
};
|
||||
|
||||
/// An explicit empty docstring. `offset == u32::MAX` distinguishes it from
|
||||
/// [`NONE`](Self::NONE), which means the item has no docstring at all.
|
||||
pub const EMPTY: Self = Self {
|
||||
text: None,
|
||||
offset: u32::MAX,
|
||||
len: 0,
|
||||
};
|
||||
|
||||
#[must_use]
|
||||
pub const fn static_text(text: &'static str) -> Self {
|
||||
Self {
|
||||
@@ -73,6 +81,9 @@ pub fn db_doc(offset: u32, len: u32) -> Option<&'static str> {
|
||||
#[inline(never)]
|
||||
#[must_use]
|
||||
pub fn plain_doc(doc: ItemDoc) -> Option<&'static str> {
|
||||
if doc.offset == u32::MAX && doc.len == 0 {
|
||||
return Some("");
|
||||
}
|
||||
if doc.len != 0 {
|
||||
return db_doc(doc.offset, doc.len);
|
||||
}
|
||||
@@ -109,3 +120,16 @@ fn docs() -> &'static str {
|
||||
})
|
||||
.as_ref()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{ItemDoc, plain_doc};
|
||||
|
||||
#[test]
|
||||
fn explicit_empty_doc_is_empty_string() {
|
||||
assert_eq!(plain_doc(ItemDoc::EMPTY), Some(""));
|
||||
assert_eq!(plain_doc(ItemDoc::NONE), None);
|
||||
assert_eq!(plain_doc(ItemDoc::static_text("")), None);
|
||||
assert_eq!(plain_doc(ItemDoc::static_text("a")), Some("a"));
|
||||
}
|
||||
}
|
||||
@@ -737,7 +737,7 @@ mod _collections {
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "_deque_iterator", traverse)]
|
||||
#[pyclass(name = "_deque_iterator", module = "collections", traverse)]
|
||||
#[derive(Debug, PyPayload)]
|
||||
struct PyDequeIterator {
|
||||
#[pytraverse(skip)]
|
||||
@@ -873,7 +873,7 @@ mod _collections {
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "_deque_reverse_iterator", traverse)]
|
||||
#[pyclass(name = "_deque_reverse_iterator", module = "collections", traverse)]
|
||||
#[derive(Debug, PyPayload)]
|
||||
struct PyReverseDequeIterator {
|
||||
#[pytraverse(skip)]
|
||||
|
||||
@@ -257,7 +257,7 @@ pub(crate) mod _ctypes {
|
||||
#[pyattr(name = "ArgumentError", once)]
|
||||
fn argument_error(vm: &VirtualMachine) -> PyTypeRef {
|
||||
vm.ctx.new_exception_type(
|
||||
"_ctypes",
|
||||
"ctypes",
|
||||
"ArgumentError",
|
||||
Some(vec![vm.ctx.exceptions.exception_type.to_owned()]),
|
||||
)
|
||||
|
||||
@@ -1250,7 +1250,7 @@ impl PyCData {
|
||||
|
||||
// PyCField - Field descriptor for Structure/Union types
|
||||
|
||||
#[pyclass(name = "CField", module = "_ctypes")]
|
||||
#[pyclass(name = "CField", module = "ctypes")]
|
||||
#[derive(Debug, PyPayload)]
|
||||
pub struct PyCField {
|
||||
/// Field name
|
||||
|
||||
@@ -351,7 +351,7 @@ mod _operator {
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "attrgetter")]
|
||||
#[pyclass(name = "attrgetter", module = "operator")]
|
||||
#[derive(Debug, PyPayload)]
|
||||
struct PyAttrGetter {
|
||||
attrs: Vec<PyStrRef>,
|
||||
@@ -468,7 +468,7 @@ mod _operator {
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "itemgetter")]
|
||||
#[pyclass(name = "itemgetter", module = "operator")]
|
||||
#[derive(Debug, PyPayload)]
|
||||
struct PyItemGetter {
|
||||
items: Vec<PyObjectRef>,
|
||||
@@ -554,7 +554,7 @@ mod _operator {
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "methodcaller")]
|
||||
#[pyclass(name = "methodcaller", module = "operator")]
|
||||
#[derive(Debug, PyPayload)]
|
||||
struct PyMethodCaller {
|
||||
name: PyUtf8StrRef,
|
||||
|
||||
@@ -291,6 +291,7 @@ mod _testinternalcapi {
|
||||
}
|
||||
}
|
||||
|
||||
/// C implementation of inspect.cleandoc().
|
||||
#[pyfunction]
|
||||
fn compiler_cleandoc(doc: PyStrRef) -> String {
|
||||
clean_doc(doc.to_str().unwrap_or(""))
|
||||
@@ -342,6 +343,7 @@ mod _testinternalcapi {
|
||||
dict_inner::peek_next_keys_version()
|
||||
}
|
||||
|
||||
/// forcefully assign type->tp_version_tag
|
||||
#[pyfunction]
|
||||
fn type_assign_specific_version_unsafe(ty: PyTypeRef, version: u32) {
|
||||
ty.assign_specific_version(version);
|
||||
@@ -800,12 +802,18 @@ mod _testinternalcapi {
|
||||
}
|
||||
}
|
||||
|
||||
/// Return a new, empty InstructionSequence.
|
||||
#[cfg(feature = "codegen")]
|
||||
#[pyfunction]
|
||||
fn new_instruction_sequence(vm: &VirtualMachine) -> PyRef<PyInstructionSequence> {
|
||||
PyInstructionSequence::empty().into_ref(&vm.ctx)
|
||||
}
|
||||
|
||||
/// Apply compiler code generation to an AST.
|
||||
///
|
||||
/// Return (instruction_sequence, metadata). metadata maps "argcount",
|
||||
/// "posonlyargcount", "kwonlyargcount" to ints and "consts" to the list of
|
||||
/// constants in LOAD_CONST index order (for use with optimize_cfg).
|
||||
#[cfg(feature = "codegen")]
|
||||
#[pyfunction]
|
||||
fn compiler_codegen(
|
||||
@@ -856,6 +864,10 @@ mod _testinternalcapi {
|
||||
Ok(vm.ctx.new_tuple(vec![seq.into(), metadata.into()]).into())
|
||||
}
|
||||
|
||||
/// Apply compiler optimizations to an instruction list.
|
||||
///
|
||||
/// consts must be a list aligned with LOAD_CONST opargs (the "consts" entry
|
||||
/// from the metadata dict returned by compiler_codegen for the same unit).
|
||||
#[cfg(feature = "codegen")]
|
||||
#[pyfunction]
|
||||
fn optimize_cfg(
|
||||
@@ -893,6 +905,7 @@ mod _testinternalcapi {
|
||||
Ok(PyInstructionSequence::from_rust(optimized, vm))
|
||||
}
|
||||
|
||||
/// Create a code object for the given instructions.
|
||||
#[cfg(feature = "codegen")]
|
||||
#[pyfunction]
|
||||
fn assemble_code_object(
|
||||
|
||||
@@ -1944,9 +1944,14 @@ pub(super) mod _os {
|
||||
pub elapsed: f64,
|
||||
}
|
||||
|
||||
#[cfg(all(any(unix, windows), not(target_os = "redox")))]
|
||||
#[cfg(all(windows, not(target_os = "redox")))]
|
||||
#[pyattr]
|
||||
#[pystruct_sequence(name = "times_result", module = "os", data = "TimesResultData")]
|
||||
#[pystruct_sequence(name = "times_result", module = "nt", data = "TimesResultData")]
|
||||
struct PyTimesResult;
|
||||
|
||||
#[cfg(all(unix, not(windows), not(target_os = "redox")))]
|
||||
#[pyattr]
|
||||
#[pystruct_sequence(name = "times_result", module = "posix", data = "TimesResultData")]
|
||||
struct PyTimesResult;
|
||||
|
||||
#[cfg(all(any(unix, windows), not(target_os = "redox")))]
|
||||
@@ -2171,8 +2176,14 @@ pub(super) mod _os {
|
||||
pub machine: String,
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
#[pyattr]
|
||||
#[pystruct_sequence(name = "uname_result", module = "os", data = "UnameResultData")]
|
||||
#[pystruct_sequence(name = "uname_result", module = "nt", data = "UnameResultData")]
|
||||
pub(crate) struct PyUnameResult;
|
||||
|
||||
#[cfg(not(windows))]
|
||||
#[pyattr]
|
||||
#[pystruct_sequence(name = "uname_result", module = "posix", data = "UnameResultData")]
|
||||
pub(crate) struct PyUnameResult;
|
||||
|
||||
#[pyclass(with(PyStructSequence))]
|
||||
|
||||
@@ -243,7 +243,7 @@ mod _ssl {
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "MemoryBIO", module = "ssl")]
|
||||
#[pyclass(name = "MemoryBIO", module = "_ssl")]
|
||||
#[derive(Debug, PyPayload)]
|
||||
struct PyMemoryBIO {
|
||||
inner: PyMutex<MemoryBio>,
|
||||
@@ -299,7 +299,7 @@ mod _ssl {
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "SSLSession", module = "ssl")]
|
||||
#[pyclass(name = "SSLSession", module = "_ssl")]
|
||||
#[derive(Debug, PyPayload)]
|
||||
struct PySSLSession {}
|
||||
|
||||
@@ -332,7 +332,7 @@ mod _ssl {
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "_SSLContext", module = "ssl")]
|
||||
#[pyclass(name = "_SSLContext", module = "_ssl")]
|
||||
#[derive(Debug, PyPayload)]
|
||||
struct PySSLContext {
|
||||
protocol: i32,
|
||||
@@ -640,7 +640,7 @@ mod _ssl {
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "_SSLSocket", module = "ssl")]
|
||||
#[pyclass(name = "_SSLSocket", module = "_ssl")]
|
||||
#[derive(Debug, PyPayload)]
|
||||
struct PySSLSocket {
|
||||
incoming: PyRef<PyMemoryBIO>,
|
||||
|
||||
Reference in new issue
Block a user