Skip to content

Allow importing PyPI packages on wasm #2442

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Mar 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[flake8]
# black's line length
max-line-length = 88
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ on:
name: CI

env:
CARGO_ARGS: --features "ssl jit"
CARGO_ARGS: --features ssl,jit
NON_WASM_PACKAGES: >
-p rustpython-bytecode
-p rustpython-common
Expand Down
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@ members = [
]

[features]
default = ["threading", "pylib"]
default = ["threading", "pylib", "zlib"]
flame-it = ["rustpython-vm/flame-it", "flame", "flamescope"]
freeze-stdlib = ["rustpython-vm/freeze-stdlib"]
jit = ["rustpython-vm/jit"]
threading = ["rustpython-vm/threading"]
zlib = ["rustpython-vm/zlib"]

ssl = ["rustpython-vm/ssl"]

Expand Down
66 changes: 66 additions & 0 deletions Lib/_dummy_os.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
"""
A shim of the os module containing only simple path-related utilities
"""

try:
from os import *
except ImportError:
import abc

def __getattr__(name):
raise OSError("no os specific module found")

def _shim():
import _dummy_os, sys
sys.modules['os'] = _dummy_os
sys.modules['os.path'] = _dummy_os.path

import posixpath as path
import sys
sys.modules['os.path'] = path
del sys

sep = path.sep


def fspath(path):
"""Return the path representation of a path-like object.

If str or bytes is passed in, it is returned unchanged. Otherwise the
os.PathLike interface is used to get the path representation. If the
path representation is not str or bytes, TypeError is raised. If the
provided path is not str, bytes, or os.PathLike, TypeError is raised.
"""
if isinstance(path, (str, bytes)):
return path

# Work from the object's type to match method resolution of other magic
# methods.
path_type = type(path)
try:
path_repr = path_type.__fspath__(path)
except AttributeError:
if hasattr(path_type, '__fspath__'):
raise
else:
raise TypeError("expected str, bytes or os.PathLike object, "
"not " + path_type.__name__)
if isinstance(path_repr, (str, bytes)):
return path_repr
else:
raise TypeError("expected {}.__fspath__() to return str or bytes, "
"not {}".format(path_type.__name__,
type(path_repr).__name__))

class PathLike(abc.ABC):

"""Abstract base class for implementing the file system path protocol."""

@abc.abstractmethod
def __fspath__(self):
"""Return the file system path representation of the object."""
raise NotImplementedError

@classmethod
def __subclasshook__(cls, subclass):
return hasattr(subclass, '__fspath__')
5 changes: 4 additions & 1 deletion Lib/fnmatch.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@
The function translate(PATTERN) returns a regular expression
corresponding to PATTERN. (It does not compile it.)
"""
import os
try:
import os
except ImportError:
import _dummy_os as os
import posixpath
import re
import functools
Expand Down
5 changes: 4 additions & 1 deletion Lib/genericpath.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
Do not use directly. The OS specific modules import the appropriate
functions from this module themselves.
"""
import os
try:
import os
except ImportError:
import _dummy_os as os
import stat

__all__ = ['commonprefix', 'exists', 'getatime', 'getctime', 'getmtime',
Expand Down
7 changes: 6 additions & 1 deletion Lib/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,17 @@
import abc

from _io import (DEFAULT_BUFFER_SIZE, BlockingIOError, UnsupportedOperation,
open, open_code, FileIO, BytesIO, StringIO, BufferedReader,
open, open_code, BytesIO, StringIO, BufferedReader,
BufferedWriter, BufferedRWPair, BufferedRandom,
# XXX RUSTPYTHON TODO: IncrementalNewlineDecoder
# IncrementalNewlineDecoder, TextIOWrapper)
TextIOWrapper)

try:
from _io import FileIO
except ImportError:
pass

OpenWrapper = _io.open # for compatibility with _pyio

# Pretend this exception was created here.
Expand Down
5 changes: 4 additions & 1 deletion Lib/linecache.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@

import functools
import sys
import os
try:
import os
except ImportError:
import _dummy_os as os
import tokenize

__all__ = ["getline", "clearcache", "checkcache"]
Expand Down
5 changes: 4 additions & 1 deletion Lib/posixpath.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@
altsep = None
devnull = '/dev/null'

import os
try:
import os
except ImportError:
import _dummy_os as os
import sys
import stat
import genericpath
Expand Down
15 changes: 12 additions & 3 deletions Lib/zipfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,22 @@
import importlib.util
import io
import itertools
import os
try:
import os
except ImportError:
import _dummy_os as os
import posixpath
import shutil
try:
import shutil
except ImportError:
pass
import stat
import struct
import sys
import threading
try:
import threading
except ImportError:
import _dummy_thread as threading
import time
import contextlib
from collections import OrderedDict
Expand Down
4 changes: 2 additions & 2 deletions common/src/lock/cell_lock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ unsafe impl RawRwLock for RawCellRwLock {

unsafe impl RawRwLockDowngrade for RawCellRwLock {
unsafe fn downgrade(&self) {
// no-op -- we're always exclusively locked for this thread
self.state.set(ONE_READER);
}
}

Expand Down Expand Up @@ -170,7 +170,7 @@ unsafe impl RawRwLockUpgradeDowngrade for RawCellRwLock {

#[inline]
unsafe fn downgrade_to_upgradable(&self) {
// no-op -- we're always exclusively locked for this thread
self.state.set(ONE_READER);
}
}

Expand Down
10 changes: 6 additions & 4 deletions vm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ include = ["src/**/*.rs", "Cargo.toml", "build.rs", "Lib/**/*.py"]

[features]
default = ["compile-parse", "threading"]
# TODO: use resolver = "2" instead of features
zlib = ["libz-sys", "flate2/zlib"]
vm-tracing-logging = []
flame-it = ["flame", "flamer"]
freeze-stdlib = ["rustpython-pylib"]
Expand Down Expand Up @@ -84,6 +86,10 @@ atty = "0.2"
static_assertions = "1.1"
half = "1.6"
memchr = "2"
crc32fast = "1.2.0"
adler32 = "1.0.3"
flate2 = "1.0.20"
libz-sys = { version = "1.0", optional = true }

# RustPython crates implementing functionality based on CPython
mt19937 = "2.0"
Expand Down Expand Up @@ -114,8 +120,6 @@ exitcode = "1.1.2"
uname = "0.1.1"

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
crc32fast = "1.2.0"
adler32 = "1.0.3"
gethostname = "0.2.0"
socket2 = "0.3.19"
rustyline = "6.0"
Expand All @@ -129,8 +133,6 @@ num_cpus = "1"

[target.'cfg(not(any(target_arch = "wasm32", target_os = "redox")))'.dependencies]
dns-lookup = "1.0"
flate2 = { version = "1.0.20", features = ["zlib"], default-features = false }
libz-sys = "1.0"

[target.'cfg(windows)'.dependencies]
winreg = "0.7"
Expand Down
2 changes: 1 addition & 1 deletion vm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ pub mod frame;
mod frozen;
pub mod function;
pub mod import;
mod iterator;
pub mod iterator;
mod py_io;
pub mod py_serde;
pub mod pyobject;
Expand Down
5 changes: 4 additions & 1 deletion vm/src/pyobjectrc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ impl Drop for PyObjectRef {
// CPython-compatible drop implementation
let zelf = self.clone();
if let Some(del_slot) = self.class().mro_find_map(|cls| cls.slots.del.load()) {
crate::vm::thread::with_vm(&zelf, |vm| {
let ret = crate::vm::thread::with_vm(&zelf, |vm| {
if let Err(e) = del_slot(&zelf, vm) {
// exception in del will be ignored but printed
print!("Exception ignored in: ",);
Expand All @@ -327,6 +327,9 @@ impl Drop for PyObjectRef {
}
}
});
if ret.is_none() {
warn!("couldn't run __del__ method for object")
}
}

// __del__ might have resurrected the object at this point, but that's fine,
Expand Down
6 changes: 2 additions & 4 deletions vm/src/stdlib/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ mod tokenize;
mod unicodedata;
mod warnings;
mod weakref;
mod zlib;

#[cfg(any(not(target_arch = "wasm32"), target_os = "wasi"))]
#[macro_use]
Expand All @@ -67,8 +68,6 @@ mod ssl;
mod winapi;
#[cfg(windows)]
mod winreg;
#[cfg(not(any(target_arch = "wasm32", target_os = "redox")))]
mod zlib;

pub type StdlibInitFunc = Box<py_dyn_fn!(dyn Fn(&VirtualMachine) -> PyObjectRef)>;

Expand Down Expand Up @@ -103,6 +102,7 @@ pub fn get_module_inits() -> HashMap<String, StdlibInitFunc, ahash::RandomState>
"_imp".to_owned() => Box::new(imp::make_module),
"unicodedata".to_owned() => Box::new(unicodedata::make_module),
"_warnings".to_owned() => Box::new(warnings::make_module),
"zlib".to_owned() => Box::new(zlib::make_module),
crate::sysmodule::sysconfigdata_name() => Box::new(sysconfigdata::make_module),
};

Expand Down Expand Up @@ -144,8 +144,6 @@ pub fn get_module_inits() -> HashMap<String, StdlibInitFunc, ahash::RandomState>
modules.insert("_ssl".to_owned(), Box::new(ssl::make_module));
#[cfg(feature = "threading")]
modules.insert("_thread".to_owned(), Box::new(thread::make_module));
#[cfg(not(target_os = "redox"))]
modules.insert("zlib".to_owned(), Box::new(zlib::make_module));
modules.insert(
"faulthandler".to_owned(),
Box::new(faulthandler::make_module),
Expand Down
Loading