Skip to content

Commit 8267ea4

Browse files
authored
Merge pull request RustPython#1599 from RustPython/coolreader18/asyncio-pre
Prerequisites for asyncio
2 parents 576d89f + 7c3340b commit 8267ea4

23 files changed

+487
-410
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/_threading_local.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ def thread_deleted(_, idt=idt):
193193

194194
@contextmanager
195195
def _patch(self):
196+
old = object.__getattribute__(self, '__dict__')
196197
impl = object.__getattribute__(self, '_local__impl')
197198
try:
198199
dct = impl.get_dict()
@@ -203,6 +204,7 @@ def _patch(self):
203204
with impl.locallock:
204205
object.__setattr__(self, '__dict__', dct)
205206
yield
207+
object.__setattr__(self, '__dict__', old)
206208

207209

208210
class local:

Lib/atexit.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Dummy implementation of atexit
2+
3+
4+
def register(func, *args, **kwargs):
5+
return func
6+
7+
8+
def unregister(func):
9+
pass

bytecode/src/bytecode.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,13 @@ impl Default for CodeFlags {
6565
}
6666
}
6767

68+
impl CodeFlags {
69+
pub const NAME_MAPPING: &'static [(&'static str, CodeFlags)] = &[
70+
("GENERATOR", CodeFlags::IS_GENERATOR),
71+
("COROUTINE", CodeFlags::IS_COROUTINE),
72+
];
73+
}
74+
6875
#[derive(Serialize, Debug, Deserialize, Clone, Copy, PartialEq, Eq, Hash)]
6976
pub struct Label(usize);
7077

tests/snippets/object.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,8 @@ class MyObject:
1717
assert MyObject().__le__(MyObject()) == NotImplemented
1818
assert MyObject().__gt__(MyObject()) == NotImplemented
1919
assert MyObject().__ge__(MyObject()) == NotImplemented
20+
21+
obj = MyObject()
22+
assert not hasattr(obj, 'a')
23+
obj.__dict__ = {'a': 1}
24+
assert obj.a == 1

vm/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ num-rational = "0.2.2"
3232
num-iter = "0.1.39"
3333
rand = "0.7"
3434
rand_distr = "0.2"
35+
getrandom = "0.1"
3536
log = "0.4"
3637
rustpython-derive = {path = "../derive", version = "0.1.1"}
3738
rustpython-parser = {path = "../parser", optional = true, version = "0.1.1"}
@@ -88,7 +89,7 @@ socket2 = { version = "0.3", features = ["unix"] }
8889

8990
[target."cfg(windows)".dependencies.winapi]
9091
version = "0.3"
91-
features = ["winsock2", "handleapi", "ws2def", "std"]
92+
features = ["winsock2", "handleapi", "ws2def", "std", "winbase"]
9293

9394
[target.'cfg(target_arch = "wasm32")'.dependencies]
9495
wasm-bindgen = "0.2"

vm/src/builtins.rs

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -252,9 +252,15 @@ fn make_scope(vm: &VirtualMachine, scope: ScopeArgs) -> PyResult<Scope> {
252252
let globals = match globals {
253253
Some(dict) => {
254254
if !dict.contains_key("__builtins__", vm) {
255-
let builtins_dict = vm.builtins.dict.as_ref().unwrap().as_object();
256-
dict.set_item("__builtins__", builtins_dict.clone(), vm)
257-
.unwrap();
255+
let builtins_dict = vm
256+
.builtins
257+
.dict
258+
.as_ref()
259+
.unwrap()
260+
.borrow()
261+
.as_object()
262+
.clone();
263+
dict.set_item("__builtins__", builtins_dict, vm).unwrap();
258264
}
259265
dict
260266
}
@@ -870,23 +876,31 @@ pub fn make_module(vm: &VirtualMachine, module: PyObjectRef) {
870876
"IndexError" => ctx.exceptions.index_error.clone(),
871877
"ImportError" => ctx.exceptions.import_error.clone(),
872878
"LookupError" => ctx.exceptions.lookup_error.clone(),
873-
"FileNotFoundError" => ctx.exceptions.file_not_found_error.clone(),
874-
"FileExistsError" => ctx.exceptions.file_exists_error.clone(),
875879
"StopIteration" => ctx.exceptions.stop_iteration.clone(),
876880
"StopAsyncIteration" => ctx.exceptions.stop_async_iteration.clone(),
877881
"SystemError" => ctx.exceptions.system_error.clone(),
878-
"PermissionError" => ctx.exceptions.permission_error.clone(),
879882
"UnicodeError" => ctx.exceptions.unicode_error.clone(),
880883
"UnicodeDecodeError" => ctx.exceptions.unicode_decode_error.clone(),
881884
"UnicodeEncodeError" => ctx.exceptions.unicode_encode_error.clone(),
882885
"UnicodeTranslateError" => ctx.exceptions.unicode_translate_error.clone(),
883886
"ZeroDivisionError" => ctx.exceptions.zero_division_error.clone(),
884887
"KeyError" => ctx.exceptions.key_error.clone(),
885-
"OSError" => ctx.exceptions.os_error.clone(),
886888
"ModuleNotFoundError" => ctx.exceptions.module_not_found_error.clone(),
887889
"EOFError" => ctx.exceptions.eof_error.clone(),
888890
"MemoryError" => ctx.exceptions.memory_error.clone(),
889891

892+
"OSError" => ctx.exceptions.os_error.clone(),
893+
"FileNotFoundError" => ctx.exceptions.file_not_found_error.clone(),
894+
"PermissionError" => ctx.exceptions.permission_error.clone(),
895+
"FileExistsError" => ctx.exceptions.file_exists_error.clone(),
896+
"BlockingIOError" => ctx.exceptions.blocking_io_error.clone(),
897+
"InterruptedError" => ctx.exceptions.interrupted_error.clone(),
898+
"ConnectionError" => ctx.exceptions.connection_error.clone(),
899+
"ConnectionResetError" => ctx.exceptions.connection_reset_error.clone(),
900+
"ConnectionRefusedError" => ctx.exceptions.connection_refused_error.clone(),
901+
"ConnectionAbortedError" => ctx.exceptions.connection_aborted_error.clone(),
902+
"BrokenPipeError" => ctx.exceptions.broken_pipe_error.clone(),
903+
890904
// Warnings
891905
"Warning" => ctx.exceptions.warning.clone(),
892906
"BytesWarning" => ctx.exceptions.bytes_warning.clone(),

vm/src/exceptions.rs

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -228,8 +228,6 @@ pub struct ExceptionZoo {
228228
pub attribute_error: PyClassRef,
229229
pub base_exception_type: PyClassRef,
230230
pub exception_type: PyClassRef,
231-
pub file_not_found_error: PyClassRef,
232-
pub file_exists_error: PyClassRef,
233231
pub import_error: PyClassRef,
234232
pub index_error: PyClassRef,
235233
pub key_error: PyClassRef,
@@ -238,9 +236,7 @@ pub struct ExceptionZoo {
238236
pub name_error: PyClassRef,
239237
pub not_implemented_error: PyClassRef,
240238
pub recursion_error: PyClassRef,
241-
pub os_error: PyClassRef,
242239
pub overflow_error: PyClassRef,
243-
pub permission_error: PyClassRef,
244240
pub reference_error: PyClassRef,
245241
pub runtime_error: PyClassRef,
246242
pub stop_iteration: PyClassRef,
@@ -259,6 +255,18 @@ pub struct ExceptionZoo {
259255
pub eof_error: PyClassRef,
260256
pub memory_error: PyClassRef,
261257

258+
pub os_error: PyClassRef,
259+
pub file_not_found_error: PyClassRef,
260+
pub permission_error: PyClassRef,
261+
pub file_exists_error: PyClassRef,
262+
pub blocking_io_error: PyClassRef,
263+
pub interrupted_error: PyClassRef,
264+
pub connection_error: PyClassRef,
265+
pub connection_reset_error: PyClassRef,
266+
pub connection_refused_error: PyClassRef,
267+
pub connection_aborted_error: PyClassRef,
268+
pub broken_pipe_error: PyClassRef,
269+
262270
pub warning: PyClassRef,
263271
pub bytes_warning: PyClassRef,
264272
pub unicode_warning: PyClassRef,
@@ -289,7 +297,6 @@ impl ExceptionZoo {
289297
let key_error = create_type("KeyError", &type_type, &exception_type);
290298
let lookup_error = create_type("LookupError", &type_type, &exception_type);
291299
let name_error = create_type("NameError", &type_type, &exception_type);
292-
let os_error = create_type("OSError", &type_type, &exception_type);
293300
let runtime_error = create_type("RuntimeError", &type_type, &exception_type);
294301
let reference_error = create_type("ReferenceError", &type_type, &exception_type);
295302
let stop_iteration = create_type("StopIteration", &type_type, &exception_type);
@@ -303,9 +310,6 @@ impl ExceptionZoo {
303310
let module_not_found_error = create_type("ModuleNotFoundError", &type_type, &import_error);
304311
let not_implemented_error = create_type("NotImplementedError", &type_type, &runtime_error);
305312
let recursion_error = create_type("RecursionError", &type_type, &runtime_error);
306-
let file_not_found_error = create_type("FileNotFoundError", &type_type, &os_error);
307-
let permission_error = create_type("PermissionError", &type_type, &os_error);
308-
let file_exists_error = create_type("FileExistsError", &type_type, &os_error);
309313
let eof_error = create_type("EOFError", &type_type, &exception_type);
310314
let indentation_error = create_type("IndentationError", &type_type, &syntax_error);
311315
let tab_error = create_type("TabError", &type_type, &indentation_error);
@@ -316,6 +320,23 @@ impl ExceptionZoo {
316320
create_type("UnicodeTranslateError", &type_type, &unicode_error);
317321
let memory_error = create_type("MemoryError", &type_type, &exception_type);
318322

323+
// os errors
324+
let os_error = create_type("OSError", &type_type, &exception_type);
325+
326+
let file_not_found_error = create_type("FileNotFoundError", &type_type, &os_error);
327+
let permission_error = create_type("PermissionError", &type_type, &os_error);
328+
let file_exists_error = create_type("FileExistsError", &type_type, &os_error);
329+
let blocking_io_error = create_type("BlockingIOError", &type_type, &os_error);
330+
let interrupted_error = create_type("InterruptedError", &type_type, &os_error);
331+
let connection_error = create_type("ConnectionError", &type_type, &os_error);
332+
let connection_reset_error =
333+
create_type("ConnectionResetError", &type_type, &connection_error);
334+
let connection_refused_error =
335+
create_type("ConnectionRefusedError", &type_type, &connection_error);
336+
let connection_aborted_error =
337+
create_type("ConnectionAbortedError", &type_type, &connection_error);
338+
let broken_pipe_error = create_type("BrokenPipeError", &type_type, &connection_error);
339+
319340
let warning = create_type("Warning", &type_type, &exception_type);
320341
let bytes_warning = create_type("BytesWarning", &type_type, &warning);
321342
let unicode_warning = create_type("UnicodeWarning", &type_type, &warning);
@@ -339,8 +360,6 @@ impl ExceptionZoo {
339360
attribute_error,
340361
base_exception_type,
341362
exception_type,
342-
file_not_found_error,
343-
file_exists_error,
344363
import_error,
345364
index_error,
346365
key_error,
@@ -349,9 +368,7 @@ impl ExceptionZoo {
349368
name_error,
350369
not_implemented_error,
351370
recursion_error,
352-
os_error,
353371
overflow_error,
354-
permission_error,
355372
runtime_error,
356373
stop_iteration,
357374
stop_async_iteration,
@@ -368,6 +385,17 @@ impl ExceptionZoo {
368385
zero_division_error,
369386
eof_error,
370387
memory_error,
388+
os_error,
389+
file_not_found_error,
390+
permission_error,
391+
file_exists_error,
392+
blocking_io_error,
393+
interrupted_error,
394+
connection_error,
395+
connection_reset_error,
396+
connection_refused_error,
397+
connection_aborted_error,
398+
broken_pipe_error,
371399
warning,
372400
bytes_warning,
373401
unicode_warning,

vm/src/frame.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -699,7 +699,7 @@ impl Frame {
699699

700700
// Grab all the names from the module and put them in the context
701701
if let Some(dict) = &module.dict {
702-
for (k, v) in dict {
702+
for (k, v) in &*dict.borrow() {
703703
let k = vm.to_str(&k)?;
704704
let k = k.as_str();
705705
if !k.starts_with('_') {

vm/src/macros.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -116,22 +116,22 @@ macro_rules! no_kwargs {
116116

117117
#[macro_export]
118118
macro_rules! py_module {
119-
( $vm:expr, $module_name:expr, { $($name:expr => $value:expr),* $(,)* }) => {{
119+
( $vm:expr, $module_name:expr, { $($name:expr => $value:expr),* $(,)? }) => {{
120120
let module = $vm.new_module($module_name, $vm.ctx.new_dict());
121-
$(
122-
$vm.set_attr(&module, $name, $value).unwrap();
123-
)*
121+
$crate::extend_module!($vm, module, { $($name => $value),* });
124122
module
125123
}};
126124
}
127125

128126
#[macro_export]
129127
macro_rules! extend_module {
130-
( $vm:expr, $module:expr, { $($name:expr => $value:expr),* $(,)* }) => {
128+
( $vm:expr, $module:expr, { $($name:expr => $value:expr),* $(,)? }) => {{
129+
#[allow(unused_variables)]
130+
let module: &$crate::pyobject::PyObjectRef = &$module;
131131
$(
132-
$vm.set_attr(&$module, $name, $value).unwrap();
132+
$vm.__module_set_attr(&module, $name, $value).unwrap();
133133
)*
134-
}
134+
}};
135135
}
136136

137137
#[macro_export]

vm/src/obj/objcode.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,10 @@ impl PyCodeRef {
8686
fn co_name(self, _vm: &VirtualMachine) -> String {
8787
self.code.obj_name.clone()
8888
}
89+
90+
fn co_flags(self, _vm: &VirtualMachine) -> u8 {
91+
self.code.flags.bits()
92+
}
8993
}
9094

9195
pub fn init(context: &PyContext) {
@@ -99,5 +103,6 @@ pub fn init(context: &PyContext) {
99103
"co_firstlineno" => context.new_property(PyCodeRef::co_firstlineno),
100104
"co_kwonlyargcount" => context.new_property(PyCodeRef::co_kwonlyargcount),
101105
"co_name" => context.new_property(PyCodeRef::co_name),
106+
"co_flags" => context.new_property(PyCodeRef::co_flags),
102107
});
103108
}

vm/src/obj/objfunction.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,24 @@ pub struct PyMethod {
6464
// TODO: these shouldn't be public
6565
pub object: PyObjectRef,
6666
pub function: PyObjectRef,
67+
pub actually_bind: bool,
6768
}
6869

6970
impl PyMethod {
7071
pub fn new(object: PyObjectRef, function: PyObjectRef) -> Self {
71-
PyMethod { object, function }
72+
PyMethod {
73+
object,
74+
function,
75+
actually_bind: true,
76+
}
77+
}
78+
79+
pub fn new_nobind(object: PyObjectRef, function: PyObjectRef) -> Self {
80+
PyMethod {
81+
object,
82+
function,
83+
actually_bind: false,
84+
}
7285
}
7386

7487
fn getattribute(&self, name: PyStringRef, vm: &VirtualMachine) -> PyResult {

vm/src/obj/objmodule.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ impl PyModuleRef {
5050
let zelf = PyModule {}.into_ref_with_type(vm, cls)?;
5151
init_module_dict(
5252
vm,
53-
zelf.as_object().dict.as_ref().unwrap(),
53+
&zelf.as_object().dict.as_ref().unwrap().borrow(),
5454
name.into_object(),
5555
doc.flat_option()
5656
.map_or_else(|| vm.get_none(), PyRef::into_object),

vm/src/obj/objobject.rs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ fn object_setattr(
7777
}
7878

7979
if let Some(ref dict) = obj.clone().dict {
80-
dict.set_item(attr_name.as_str(), value, vm)?;
80+
dict.borrow().set_item(attr_name.as_str(), value, vm)?;
8181
Ok(())
8282
} else {
8383
Err(vm.new_attribute_error(format!(
@@ -98,7 +98,7 @@ fn object_delattr(obj: PyObjectRef, attr_name: PyStringRef, vm: &VirtualMachine)
9898
}
9999

100100
if let Some(ref dict) = obj.dict {
101-
dict.del_item(attr_name.as_str(), vm)?;
101+
dict.borrow().del_item(attr_name.as_str(), vm)?;
102102
Ok(())
103103
} else {
104104
Err(vm.new_attribute_error(format!(
@@ -130,7 +130,7 @@ pub fn object_dir(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyList> {
130130
if let Some(object_dict) = &obj.dict {
131131
vm.invoke(
132132
&vm.get_attribute(dict.clone().into_object(), "update")?,
133-
object_dict.clone().into_object(),
133+
object_dict.borrow().clone().into_object(),
134134
)?;
135135
}
136136

@@ -210,20 +210,22 @@ fn object_class_setter(
210210

211211
fn object_dict(object: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyDictRef> {
212212
if let Some(ref dict) = object.dict {
213-
Ok(dict.clone())
213+
Ok(dict.borrow().clone())
214214
} else {
215215
Err(vm.new_attribute_error("no dictionary.".to_string()))
216216
}
217217
}
218218

219-
fn object_dict_setter(
220-
_instance: PyObjectRef,
221-
_value: PyObjectRef,
222-
vm: &VirtualMachine,
223-
) -> PyResult {
224-
Err(vm.new_not_implemented_error(
225-
"Setting __dict__ attribute on an object isn't yet implemented".to_string(),
226-
))
219+
fn object_dict_setter(instance: PyObjectRef, value: PyDictRef, vm: &VirtualMachine) -> PyResult {
220+
if let Some(dict) = &instance.dict {
221+
*dict.borrow_mut() = value;
222+
Ok(vm.get_none())
223+
} else {
224+
Err(vm.new_attribute_error(format!(
225+
"'{}' object has no attribute '__dict__'",
226+
instance.class().name
227+
)))
228+
}
227229
}
228230

229231
fn object_getattribute(obj: PyObjectRef, name: PyStringRef, vm: &VirtualMachine) -> PyResult {

0 commit comments

Comments
 (0)