Merge pull request #1617 from RustPython/coolreader18/os-stuff

Fix some various issues with `os` and `binascii`
This commit is contained in:
Windel Bouwman
2019-12-21 12:31:59 +01:00
committed by GitHub
12 changed files with 376 additions and 274 deletions

67
Cargo.lock generated
View File

@@ -71,7 +71,7 @@ name = "atty"
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -87,7 +87,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -97,7 +97,7 @@ version = "0.1.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -108,6 +108,11 @@ dependencies = [
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "base64"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bincode"
version = "1.2.0"
@@ -246,7 +251,7 @@ version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"js-sys 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -285,7 +290,7 @@ name = "cpython"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"python3-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -367,7 +372,7 @@ name = "dirs"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -387,7 +392,7 @@ version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -397,7 +402,7 @@ name = "dns-lookup"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -513,7 +518,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
"miniz_oxide 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -546,7 +551,7 @@ name = "gethostname"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -556,7 +561,7 @@ version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -680,7 +685,7 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.62"
version = "0.2.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -689,7 +694,7 @@ version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -736,7 +741,7 @@ name = "memchr"
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -760,7 +765,7 @@ dependencies = [
"bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -772,7 +777,7 @@ dependencies = [
"bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -854,7 +859,7 @@ name = "num_cpus"
version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -960,7 +965,7 @@ version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -968,7 +973,7 @@ name = "python3-sys"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -999,7 +1004,7 @@ version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1017,7 +1022,7 @@ version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1099,7 +1104,7 @@ name = "rand_jitter"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1111,7 +1116,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1291,6 +1296,7 @@ version = "0.1.1"
dependencies = [
"adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"arr_macro 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"blake2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1313,7 +1319,7 @@ dependencies = [
"itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lexical 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1380,7 +1386,7 @@ version = "5.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1497,7 +1503,7 @@ version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1567,7 +1573,7 @@ version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1638,7 +1644,7 @@ name = "thread-id"
version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1656,7 +1662,7 @@ name = "time"
version = "0.1.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -2159,6 +2165,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)" = "690a62be8920ccf773ee00ef0968649b0e724cda8bd5b12286302b4ae955fdf5"
"checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b"
"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
"checksum base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7"
"checksum bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8ab639324e3ee8774d296864fbc0dbbb256cf1a41c490b94cba90c082915f92"
"checksum bit-set 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e84c238982c4b1e1ee668d136c510c67a13465279c0cb367ea6baf6310620a80"
"checksum bit-vec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f59bbe95d4e52a6398ec21238d31577f2b28a9d86807f06ca59d191d8440d0bb"
@@ -2229,7 +2236,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
"checksum lexical 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0afaeae1c07c575338ef6809875bfea8daa9ea8b2ee381ef1f93ba0c6e32f003"
"checksum lexical-core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d7043aa5c05dd34fb73b47acb8c3708eac428de4545ea3682ed2f11293ebd890"
"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba"
"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558"
"checksum libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe"
"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
"checksum lz4-compress 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f966533a922a9bba9e95e594c1fdb3b9bf5fdcdb11e37e51ad84cd76e468b91"

View File

@@ -1,5 +1,5 @@
import binascii
from testutils import assert_raises
from testutils import assert_raises, assert_equal
# hexlify tests
@@ -25,8 +25,7 @@ assert uh(h(x)) == x
assert uh(b"ABCDEF") == b"\xab\xcd\xef"
assert binascii.a2b_hex(b"6161") == b"aa"
# unhexlify on strings not supported yet
# assert uh("abcd") == b"\xab\xcd"
assert uh("abcd") == b"\xab\xcd"
with assert_raises(ValueError):
uh(b"a") # Odd-length string
@@ -36,4 +35,18 @@ with assert_raises(ValueError):
assert binascii.crc32(b"hello world") == 222957957
assert binascii.crc32(b"hello world", 555555) == 1216827162
assert binascii.crc32(b"goodbye interesting world",777777) == 1885538403
assert binascii.crc32(b"goodbye interesting world", 777777) == 1885538403
enc_b64 = binascii.b2a_base64
assert_equal(enc_b64(b"213"), b"MjEz\n")
assert_equal(enc_b64(b"213", newline=False), b"MjEz")
dec_b64 = binascii.a2b_base64
assert_equal(dec_b64(b"UnVzdFB5dGhvbg==\n"), b"RustPython")
assert_equal(
dec_b64(b"4pii8J+QoyAg4ZaH8J2TpPCdlYrRguKTn/CdlZDwnZWl5Y2Ez4PwnZSrICDimazwn5Gj\n"),
"☢🐣 ᖇ𝓤𝕊тⓟ𝕐𝕥卄σ𝔫 ♬👣".encode(),
)

View File

@@ -125,6 +125,17 @@ with TestWithTempDir() as tmpdir:
assert os.read(fd, len(CONTENT2) + len(CONTENT3)) == CONTENT2 + CONTENT3
os.close(fd)
assert not os.isatty(fd)
# TODO: get os.lseek working on windows
if os.name != 'nt':
fd = os.open(fname3, 0)
assert os.read(fd, len(CONTENT2)) == CONTENT2
assert os.read(fd, len(CONTENT3)) == CONTENT3
os.lseek(fd, len(CONTENT2), os.SEEK_SET)
assert os.read(fd, len(CONTENT3)) == CONTENT3
os.close(fd)
os.rename(fname3, fname)
assert os.path.exists(fname3) == False
assert os.path.exists(fname) == True
@@ -383,11 +394,6 @@ if "win" not in sys.platform:
assert os.system('{') != 0
for arg in [None, 1, 1.0, TabError]:
try:
os.system(arg)
except TypeError:
pass
else:
raise AssertionError(f'os.system failed to raise TypeError with arg {arg}')
assert_raises(TypeError, os.system, arg)

View File

@@ -67,6 +67,7 @@ wtf8 = "0.0.3"
arr_macro = "0.1.2"
csv = "1.1.1"
paste = "0.1"
base64 = "0.11"
flame = { version = "0.2", optional = true }
flamer = { version = "0.3", optional = true }

View File

@@ -1418,7 +1418,6 @@ fn split_slice_reverse<'a>(slice: &'a [u8], sep: &[u8], maxsplit: i32) -> Vec<&'
pub enum PyBytesLike {
Bytes(PyBytesRef),
Bytearray(PyByteArrayRef),
Vec(Vec<u8>),
}
impl TryFromObject for PyBytesLike {
@@ -1426,8 +1425,6 @@ impl TryFromObject for PyBytesLike {
match_class!(match obj {
b @ PyBytes => Ok(PyBytesLike::Bytes(b)),
b @ PyByteArray => Ok(PyBytesLike::Bytearray(b)),
m @ PyMemoryView => Ok(PyBytesLike::Vec(m.get_obj_value().unwrap())),
l @ PyList => Ok(PyBytesLike::Vec(l.get_byte_inner(vm)?.elements)),
obj => Err(vm.new_type_error(format!(
"a bytes-like object is required, not {}",
obj.class()
@@ -1441,7 +1438,14 @@ impl PyBytesLike {
match self {
PyBytesLike::Bytes(b) => b.get_value().into(),
PyBytesLike::Bytearray(b) => b.inner.borrow().elements.clone().into(),
PyBytesLike::Vec(b) => b.as_slice().into(),
}
}
#[inline]
pub fn with_ref<R>(&self, f: impl FnOnce(&[u8]) -> R) -> R {
match self {
PyBytesLike::Bytes(b) => f(b.get_value()),
PyBytesLike::Bytearray(b) => f(&b.inner.borrow().elements),
}
}
}

View File

@@ -1,8 +1,52 @@
use crate::function::OptionalArg;
use crate::obj::objbytes::PyBytesRef;
use crate::pyobject::{PyObjectRef, PyResult};
use crate::obj::objbytearray::{PyByteArray, PyByteArrayRef};
use crate::obj::objbyteinner::PyBytesLike;
use crate::obj::objbytes::{PyBytes, PyBytesRef};
use crate::obj::objstr::{PyString, PyStringRef};
use crate::pyobject::{PyObjectRef, PyResult, TryFromObject, TypeProtocol};
use crate::vm::VirtualMachine;
use crc::{crc32, Hasher32};
use itertools::Itertools;
enum SerializedData {
Bytes(PyBytesRef),
Buffer(PyByteArrayRef),
Ascii(PyStringRef),
}
impl TryFromObject for SerializedData {
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
match_class!(match obj {
b @ PyBytes => Ok(SerializedData::Bytes(b)),
b @ PyByteArray => Ok(SerializedData::Buffer(b)),
a @ PyString => {
if a.as_str().is_ascii() {
Ok(SerializedData::Ascii(a))
} else {
Err(vm.new_value_error(
"string argument should contain only ASCII characters".to_string(),
))
}
}
obj => Err(vm.new_type_error(format!(
"argument should be bytes, buffer or ASCII string, not '{}'",
obj.class().name,
))),
})
}
}
impl SerializedData {
#[inline]
pub fn with_ref<R>(&self, f: impl FnOnce(&[u8]) -> R) -> R {
match self {
SerializedData::Bytes(b) => f(b.get_value()),
SerializedData::Buffer(b) => f(&b.inner.borrow().elements),
SerializedData::Ascii(a) => f(a.as_str().as_bytes()),
}
}
}
fn hex_nibble(n: u8) -> u8 {
match n {
@@ -12,15 +56,15 @@ fn hex_nibble(n: u8) -> u8 {
}
}
fn binascii_hexlify(data: PyBytesRef, vm: &VirtualMachine) -> PyResult {
let bytes = data.get_value();
let mut hex = Vec::<u8>::with_capacity(bytes.len() * 2);
for b in bytes.iter() {
hex.push(hex_nibble(b >> 4));
hex.push(hex_nibble(b & 0xf));
}
Ok(vm.ctx.new_bytes(hex))
fn binascii_hexlify(data: PyBytesLike, _vm: &VirtualMachine) -> Vec<u8> {
data.with_ref(|bytes| {
let mut hex = Vec::<u8>::with_capacity(bytes.len() * 2);
for b in bytes.iter() {
hex.push(hex_nibble(b >> 4));
hex.push(hex_nibble(b & 0xf));
}
hex
})
}
fn unhex_nibble(c: u8) -> Option<u8> {
@@ -32,37 +76,66 @@ fn unhex_nibble(c: u8) -> Option<u8> {
}
}
fn binascii_unhexlify(hexstr: PyBytesRef, vm: &VirtualMachine) -> PyResult {
// TODO: allow 'str' hexstrings as well
let hex_bytes = hexstr.get_value();
if hex_bytes.len() % 2 != 0 {
return Err(vm.new_value_error("Odd-length string".to_string()));
}
let mut unhex = Vec::<u8>::with_capacity(hex_bytes.len() / 2);
for i in (0..hex_bytes.len()).step_by(2) {
let n1 = unhex_nibble(hex_bytes[i]);
let n2 = unhex_nibble(hex_bytes[i + 1]);
if let (Some(n1), Some(n2)) = (n1, n2) {
unhex.push(n1 << 4 | n2);
} else {
return Err(vm.new_value_error("Non-hexadecimal digit found".to_string()));
fn binascii_unhexlify(data: SerializedData, vm: &VirtualMachine) -> PyResult<Vec<u8>> {
data.with_ref(|hex_bytes| {
if hex_bytes.len() % 2 != 0 {
return Err(vm.new_value_error("Odd-length string".to_string()));
}
}
Ok(vm.ctx.new_bytes(unhex))
let mut unhex = Vec::<u8>::with_capacity(hex_bytes.len() / 2);
for (n1, n2) in hex_bytes.iter().tuples() {
if let (Some(n1), Some(n2)) = (unhex_nibble(*n1), unhex_nibble(*n2)) {
unhex.push(n1 << 4 | n2);
} else {
return Err(vm.new_value_error("Non-hexadecimal digit found".to_string()));
}
}
Ok(unhex)
})
}
fn binascii_crc32(data: PyBytesRef, value: OptionalArg<u32>, vm: &VirtualMachine) -> PyResult {
let bytes = data.get_value();
let crc = value.unwrap_or(0u32);
fn binascii_crc32(data: SerializedData, value: OptionalArg<u32>, vm: &VirtualMachine) -> PyResult {
let crc = value.unwrap_or(0);
let mut digest = crc32::Digest::new_with_initial(crc32::IEEE, crc);
digest.write(&bytes);
data.with_ref(|bytes| digest.write(&bytes));
Ok(vm.ctx.new_int(digest.sum32()))
}
#[derive(FromArgs)]
struct NewlineArg {
#[pyarg(keyword_only, default = "true")]
newline: bool,
}
/// trim a newline from the end of the bytestring, if it exists
fn trim_newline(b: &[u8]) -> &[u8] {
if b.ends_with(b"\n") {
&b[..b.len() - 1]
} else {
b
}
}
fn binascii_a2b_base64(s: SerializedData, vm: &VirtualMachine) -> PyResult<Vec<u8>> {
s.with_ref(|b| base64::decode(trim_newline(b)))
.map_err(|err| vm.new_value_error(format!("error decoding base64: {}", err)))
}
fn binascii_b2a_base64(
data: PyBytesLike,
NewlineArg { newline }: NewlineArg,
_vm: &VirtualMachine,
) -> Vec<u8> {
let mut encoded = data.with_ref(base64::encode).into_bytes();
if newline {
encoded.push(b'\n');
}
encoded
}
pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
let ctx = &vm.ctx;
@@ -72,5 +145,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
"unhexlify" => ctx.new_rustfunc(binascii_unhexlify),
"a2b_hex" => ctx.new_rustfunc(binascii_unhexlify),
"crc32" => ctx.new_rustfunc(binascii_crc32),
"a2b_base64" => ctx.new_rustfunc(binascii_a2b_base64),
"b2a_base64" => ctx.new_rustfunc(binascii_b2a_base64),
})
}

View File

@@ -169,6 +169,7 @@ const ERROR_CODES: &[(&str, i32)] = &[
e!(EINPROGRESS),
e!(ENXIO),
e!(ECANCELED),
e!(EWOULDBLOCK),
e!(cfg(not(windows)), EOWNERDEAD),
e!(cfg(not(windows)), ENOTRECOVERABLE),
e!(cfg(windows), WSAEAFNOSUPPORT),

View File

@@ -244,7 +244,8 @@ impl PyBytesIORef {
}
fn write(self, data: PyBytesLike, vm: &VirtualMachine) -> PyResult<u64> {
match self.buffer(vm)?.write(data.to_cow().as_ref()) {
let mut buffer = self.buffer(vm)?;
match data.with_ref(|b| buffer.write(b)) {
Some(value) => Ok(value),
None => Err(vm.new_type_error("Error Writing Bytes".to_string())),
}
@@ -358,11 +359,10 @@ fn io_base_readline(
let read = vm.get_attribute(instance, "read")?;
while size < 0 || res.len() < size as usize {
let read_res = PyBytesLike::try_from_object(vm, vm.invoke(&read, vec![vm.new_int(1)])?)?;
let b = read_res.to_cow();
if b.is_empty() {
if read_res.with_ref(|b| b.is_empty()) {
break;
}
res.extend_from_slice(b.as_ref());
read_res.with_ref(|b| res.extend_from_slice(b));
if res.ends_with(b"\n") {
break;
}
@@ -643,8 +643,8 @@ mod fileio {
) -> PyResult<usize> {
let mut handle = fio_get_fileno(&instance, vm)?;
let len = handle
.write(obj.to_cow().as_ref())
let len = obj
.with_ref(|b| handle.write(b))
.map_err(|e| os::convert_io_error(vm, e))?;
fio_set_fileno(&instance, handle, vm)?;

View File

@@ -11,10 +11,7 @@ use winapi::um::winsock2::{self, SOCKET};
fn multiprocessing_closesocket(socket: usize, vm: &VirtualMachine) -> PyResult<()> {
let res = unsafe { winsock2::closesocket(socket as SOCKET) };
if res == 0 {
Err(super::os::convert_io_error(
vm,
std::io::Error::last_os_error(),
))
Err(super::os::errno_err(vm))
} else {
Ok(())
}
@@ -26,10 +23,7 @@ fn multiprocessing_recv(socket: usize, size: usize, vm: &VirtualMachine) -> PyRe
let nread =
unsafe { winsock2::recv(socket as SOCKET, buf.as_mut_ptr() as *mut _, size as i32, 0) };
if nread < 0 {
Err(super::os::convert_io_error(
vm,
std::io::Error::last_os_error(),
))
Err(super::os::errno_err(vm))
} else {
Ok(nread)
}
@@ -41,20 +35,11 @@ fn multiprocessing_send(
buf: PyBytesLike,
vm: &VirtualMachine,
) -> PyResult<libc::c_int> {
let buf = buf.to_cow();
let ret = unsafe {
winsock2::send(
socket as SOCKET,
buf.as_ptr() as *const _,
buf.len() as i32,
0,
)
};
let ret = buf.with_ref(|b| unsafe {
winsock2::send(socket as SOCKET, b.as_ptr() as *const _, b.len() as i32, 0)
});
if ret < 0 {
Err(super::os::convert_io_error(
vm,
std::io::Error::last_os_error(),
))
Err(super::os::errno_err(vm))
} else {
Ok(ret)
}

View File

@@ -25,6 +25,7 @@ use std::os::unix::io::RawFd;
use super::errno::errors;
use crate::function::{IntoPyNativeFunc, OptionalArg, PyFuncArgs};
use crate::obj::objbyteinner::PyBytesLike;
use crate::obj::objbytes::PyBytesRef;
use crate::obj::objdict::PyDictRef;
use crate::obj::objint::PyIntRef;
@@ -170,10 +171,11 @@ pub fn convert_io_error(vm: &VirtualMachine, err: io::Error) -> PyObjectRef {
},
};
let os_error = vm.new_exception(exc_type, err.to_string());
if let Some(errno) = err.raw_os_error() {
vm.set_attr(&os_error, "errno", vm.ctx.new_int(errno))
.unwrap();
}
let errno = match err.raw_os_error() {
Some(errno) => vm.new_int(errno),
None => vm.get_none(),
};
vm.set_attr(&os_error, "errno", errno).unwrap();
os_error
}
@@ -214,6 +216,12 @@ fn convert_nix_errno(vm: &VirtualMachine, errno: Errno) -> PyClassRef {
}
}
/// Convert the error stored in the `errno` variable into an Exception
#[inline]
pub fn errno_err(vm: &VirtualMachine) -> PyObjectRef {
convert_io_error(vm, io::Error::last_os_error())
}
// Flags for os_access
bitflags! {
pub struct AccessFlags: u8{
@@ -347,17 +355,21 @@ fn os_fsync(fd: i64, vm: &VirtualMachine) -> PyResult<()> {
fn os_read(fd: i64, n: usize, vm: &VirtualMachine) -> PyResult {
let mut buffer = vec![0u8; n];
let mut file = rust_file(fd);
file.read_exact(&mut buffer)
let n = file
.read(&mut buffer)
.map_err(|err| convert_io_error(vm, err))?;
buffer.truncate(n);
// Avoid closing the fd
raw_file_number(file);
Ok(vm.ctx.new_bytes(buffer))
}
fn os_write(fd: i64, data: PyBytesRef, vm: &VirtualMachine) -> PyResult {
fn os_write(fd: i64, data: PyBytesLike, vm: &VirtualMachine) -> PyResult {
let mut file = rust_file(fd);
let written = file.write(&data).map_err(|err| convert_io_error(vm, err))?;
let written = data
.with_ref(|b| file.write(b))
.map_err(|err| convert_io_error(vm, err))?;
// Avoid closing the fd
raw_file_number(file);
@@ -548,13 +560,13 @@ impl DirEntryRef {
.is_symlink())
}
fn stat(
self,
dir_fd: DirFd,
follow_symlinks: FollowSymlinks,
vm: &VirtualMachine,
) -> PyResult<StatResult> {
os_stat(self.path(vm).try_into_ref(vm)?, dir_fd, follow_symlinks, vm)
fn stat(self, dir_fd: DirFd, follow_symlinks: FollowSymlinks, vm: &VirtualMachine) -> PyResult {
os_stat(
Either::A(self.path(vm).try_into_ref(vm)?),
dir_fd,
follow_symlinks,
vm,
)
}
}
@@ -629,6 +641,7 @@ fn os_scandir(path: OptionalArg<PyStringRef>, vm: &VirtualMachine) -> PyResult {
}
}
#[pystruct_sequence(name = "os.stat_result")]
#[derive(Debug)]
struct StatResult {
st_mode: u32,
@@ -639,57 +652,15 @@ struct StatResult {
st_gid: u32,
st_size: u64,
st_atime: f64,
st_ctime: f64,
st_mtime: f64,
st_ctime: f64,
}
impl PyValue for StatResult {
fn class(vm: &VirtualMachine) -> PyClassRef {
vm.class("_os", "stat_result")
}
}
type StatResultRef = PyRef<StatResult>;
impl StatResultRef {
fn st_mode(self, _vm: &VirtualMachine) -> u32 {
self.st_mode
}
fn st_ino(self, _vm: &VirtualMachine) -> u64 {
self.st_ino
}
fn st_dev(self, _vm: &VirtualMachine) -> u64 {
self.st_dev
}
fn st_nlink(self, _vm: &VirtualMachine) -> u64 {
self.st_nlink
}
fn st_uid(self, _vm: &VirtualMachine) -> u32 {
self.st_uid
}
fn st_gid(self, _vm: &VirtualMachine) -> u32 {
self.st_gid
}
fn st_size(self, _vm: &VirtualMachine) -> u64 {
self.st_size
}
fn st_atime(self, _vm: &VirtualMachine) -> f64 {
self.st_atime
}
fn st_ctime(self, _vm: &VirtualMachine) -> f64 {
self.st_ctime
}
fn st_mtime(self, _vm: &VirtualMachine) -> f64 {
self.st_mtime
impl StatResult {
fn into_obj(self, vm: &VirtualMachine) -> PyObjectRef {
self.into_struct_sequence(vm, vm.class("_os", "stat_result"))
.unwrap()
.into_object()
}
}
@@ -712,80 +683,56 @@ fn to_seconds_from_nanos(secs: i64, nanos: i64) -> f64 {
}
#[cfg(unix)]
macro_rules! os_unix_stat_inner {
( $path:expr, $follow_symlinks:expr, $vm:expr ) => {{
#[allow(clippy::match_bool)]
fn get_stats(path: &str, follow_symlinks: bool) -> io::Result<StatResult> {
let meta = match follow_symlinks {
true => fs::metadata(path)?,
false => fs::symlink_metadata(path)?,
};
Ok(StatResult {
st_mode: meta.st_mode(),
st_ino: meta.st_ino(),
st_dev: meta.st_dev(),
st_nlink: meta.st_nlink(),
st_uid: meta.st_uid(),
st_gid: meta.st_gid(),
st_size: meta.st_size(),
st_atime: to_seconds_from_unix_epoch(meta.accessed()?),
st_mtime: to_seconds_from_unix_epoch(meta.modified()?),
st_ctime: to_seconds_from_nanos(meta.st_ctime(), meta.st_ctime_nsec()),
})
}
get_stats($path.as_str(), $follow_symlinks.follow_symlinks)
.map_err(|err| convert_io_error($vm, err))
}};
}
#[cfg(target_os = "linux")]
fn os_stat(
path: PyStringRef,
file: Either<PyStringRef, i64>,
dir_fd: DirFd,
follow_symlinks: FollowSymlinks,
vm: &VirtualMachine,
) -> PyResult<StatResult> {
use std::os::linux::fs::MetadataExt;
let path = make_path(vm, path, &dir_fd);
os_unix_stat_inner!(path, follow_symlinks, vm)
}
#[cfg(target_os = "macos")]
fn os_stat(
path: PyStringRef,
dir_fd: DirFd,
follow_symlinks: FollowSymlinks,
vm: &VirtualMachine,
) -> PyResult<StatResult> {
use std::os::macos::fs::MetadataExt;
let path = make_path(vm, path, &dir_fd);
os_unix_stat_inner!(path, follow_symlinks, vm)
}
#[cfg(target_os = "android")]
fn os_stat(
path: PyStringRef,
dir_fd: DirFd,
follow_symlinks: FollowSymlinks,
vm: &VirtualMachine,
) -> PyResult<StatResult> {
) -> PyResult {
#[cfg(target_os = "android")]
use std::os::android::fs::MetadataExt;
let path = make_path(vm, path, &dir_fd);
os_unix_stat_inner!(path, follow_symlinks, vm)
}
#[cfg(target_os = "redox")]
fn os_stat(
path: PyStringRef,
dir_fd: DirFd,
follow_symlinks: FollowSymlinks,
vm: &VirtualMachine,
) -> PyResult<StatResult> {
#[cfg(target_os = "linux")]
use std::os::linux::fs::MetadataExt;
#[cfg(target_os = "macos")]
use std::os::macos::fs::MetadataExt;
#[cfg(target_os = "redox")]
use std::os::redox::fs::MetadataExt;
let path = make_path(vm, path, &dir_fd);
os_unix_stat_inner!(path, follow_symlinks, vm)
let get_stats = move || -> io::Result<PyObjectRef> {
let meta = match file {
Either::A(path) => {
let path = make_path(vm, path, &dir_fd);
let path = path.as_str();
if follow_symlinks.follow_symlinks {
fs::metadata(path)?
} else {
fs::symlink_metadata(path)?
}
}
Either::B(fno) => {
let file = rust_file(fno);
let meta = file.metadata()?;
raw_file_number(file);
meta
}
};
Ok(StatResult {
st_mode: meta.st_mode(),
st_ino: meta.st_ino(),
st_dev: meta.st_dev(),
st_nlink: meta.st_nlink(),
st_uid: meta.st_uid(),
st_gid: meta.st_gid(),
st_size: meta.st_size(),
st_atime: to_seconds_from_unix_epoch(meta.accessed()?),
st_mtime: to_seconds_from_unix_epoch(meta.modified()?),
st_ctime: to_seconds_from_nanos(meta.st_ctime(), meta.st_ctime_nsec()),
}
.into_obj(vm))
};
get_stats().map_err(|err| convert_io_error(vm, err))
}
// Copied from CPython fileutils.c
@@ -811,17 +758,25 @@ fn attributes_to_mode(attr: u32) -> u32 {
#[cfg(windows)]
fn os_stat(
path: PyStringRef,
file: Either<PyStringRef, i64>,
_dir_fd: DirFd, // TODO: error
follow_symlinks: FollowSymlinks,
vm: &VirtualMachine,
) -> PyResult<StatResult> {
) -> PyResult {
use std::os::windows::fs::MetadataExt;
fn get_stats(path: &str, follow_symlinks: bool) -> io::Result<StatResult> {
let meta = match follow_symlinks {
true => fs::metadata(path)?,
false => fs::symlink_metadata(path)?,
let get_stats = move || -> io::Result<PyObjectRef> {
let meta = match file {
Either::A(path) => match follow_symlinks.follow_symlinks {
true => fs::metadata(path.as_str())?,
false => fs::symlink_metadata(path.as_str())?,
},
Either::B(fno) => {
let f = rust_file(fno);
let meta = f.metadata()?;
raw_file_number(f);
meta
}
};
Ok(StatResult {
@@ -835,11 +790,11 @@ fn os_stat(
st_atime: to_seconds_from_unix_epoch(meta.accessed()?),
st_mtime: to_seconds_from_unix_epoch(meta.modified()?),
st_ctime: to_seconds_from_unix_epoch(meta.created()?),
})
}
}
.into_obj(vm))
};
get_stats(path.as_str(), follow_symlinks.follow_symlinks)
.map_err(|s| vm.new_os_error(s.to_string()))
get_stats().map_err(|e| convert_io_error(vm, e))
}
#[cfg(not(any(
@@ -850,17 +805,17 @@ fn os_stat(
windows
)))]
fn os_stat(
_path: PyStringRef,
_file: Either<PyStringRef, i64>,
_dir_fd: DirFd,
_follow_symlinks: FollowSymlinks,
_vm: &VirtualMachine,
) -> PyResult<StatResult> {
) -> PyResult {
unimplemented!();
}
fn os_lstat(path: PyStringRef, dir_fd: DirFd, vm: &VirtualMachine) -> PyResult<StatResult> {
fn os_lstat(file: Either<PyStringRef, i64>, dir_fd: DirFd, vm: &VirtualMachine) -> PyResult {
os_stat(
path,
file,
dir_fd,
FollowSymlinks {
follow_symlinks: false,
@@ -1175,7 +1130,7 @@ pub fn os_ttyname(fd: i32, vm: &VirtualMachine) -> PyResult {
use libc::ttyname;
let name = unsafe { ttyname(fd) };
if name.is_null() {
Err(vm.new_os_error(io::Error::last_os_error().to_string()))
Err(errno_err(vm))
} else {
let name = unsafe { ffi::CStr::from_ptr(name) }.to_str().unwrap();
Ok(vm.ctx.new_str(name.to_owned()))
@@ -1193,6 +1148,71 @@ fn os_urandom(size: usize, vm: &VirtualMachine) -> PyResult<Vec<u8>> {
}
}
// this is basically what CPython has for Py_off_t; windows uses long long
// for offsets, other platforms just use off_t
#[cfg(not(windows))]
pub type Offset = libc::off_t;
#[cfg(windows)]
pub type Offset = libc::c_longlong;
#[cfg(windows)]
type InvalidParamHandler = extern "C" fn(
*const libc::wchar_t,
*const libc::wchar_t,
*const libc::wchar_t,
libc::c_uint,
libc::uintptr_t,
);
#[cfg(windows)]
extern "C" {
fn _set_thread_local_invalid_parameter_handler(
pNew: InvalidParamHandler,
) -> InvalidParamHandler;
}
#[cfg(windows)]
extern "C" fn silent_iph_handler(
_: *const libc::wchar_t,
_: *const libc::wchar_t,
_: *const libc::wchar_t,
_: libc::c_uint,
_: libc::uintptr_t,
) {
}
macro_rules! suppress_iph {
($e:expr) => {{
#[cfg(windows)]
{
let old = _set_thread_local_invalid_parameter_handler(silent_iph_handler);
let ret = $e;
_set_thread_local_invalid_parameter_handler(old);
ret
}
#[cfg(not(windows))]
{
$e
}
}};
}
fn os_isatty(fd: i32, _vm: &VirtualMachine) -> bool {
unsafe { suppress_iph!(libc::isatty(fd)) != 0 }
}
fn os_lseek(fd: i32, position: Offset, how: i32, vm: &VirtualMachine) -> PyResult<Offset> {
#[cfg(not(windows))]
use libc::lseek;
#[cfg(windows)]
use libc::lseek64 as lseek;
let res = unsafe { suppress_iph!(lseek(fd, position, how)) };
if res < 0 {
Err(errno_err(vm))
} else {
Ok(res)
}
}
pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
let ctx = &vm.ctx;
@@ -1216,18 +1236,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
"stat" => ctx.new_rustfunc(DirEntryRef::stat),
});
let stat_result = py_class!(ctx, "stat_result", ctx.object(), {
"st_mode" => ctx.new_property(StatResultRef::st_mode),
"st_ino" => ctx.new_property(StatResultRef::st_ino),
"st_dev" => ctx.new_property(StatResultRef::st_dev),
"st_nlink" => ctx.new_property(StatResultRef::st_nlink),
"st_uid" => ctx.new_property(StatResultRef::st_uid),
"st_gid" => ctx.new_property(StatResultRef::st_gid),
"st_size" => ctx.new_property(StatResultRef::st_size),
"st_atime" => ctx.new_property(StatResultRef::st_atime),
"st_ctime" => ctx.new_property(StatResultRef::st_ctime),
"st_mtime" => ctx.new_property(StatResultRef::st_mtime),
});
let stat_result = StatResult::make_class(ctx);
struct SupportFunc<'a> {
name: &'a str,
@@ -1278,6 +1287,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
SupportFunc::new(vm, "rmdir", os_rmdir, Some(false), Some(false), None),
SupportFunc::new(vm, "scandir", os_scandir, Some(false), None, None),
SupportFunc::new(vm, "stat", os_stat, Some(false), Some(false), Some(false)),
SupportFunc::new(vm, "fstat", os_stat, Some(false), Some(false), Some(false)),
SupportFunc::new(vm, "symlink", os_symlink, None, Some(false), None),
// truncate Some None None
SupportFunc::new(vm, "unlink", os_remove, Some(false), Some(false), None),
@@ -1318,6 +1328,8 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
"cpu_count" => ctx.new_rustfunc(os_cpu_count),
"_exit" => ctx.new_rustfunc(os_exit),
"urandom" => ctx.new_rustfunc(os_urandom),
"isatty" => ctx.new_rustfunc(os_isatty),
"lseek" => ctx.new_rustfunc(os_lseek),
"O_RDONLY" => ctx.new_int(libc::O_RDONLY),
"O_WRONLY" => ctx.new_int(libc::O_WRONLY),
@@ -1325,10 +1337,14 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
"O_APPEND" => ctx.new_int(libc::O_APPEND),
"O_EXCL" => ctx.new_int(libc::O_EXCL),
"O_CREAT" => ctx.new_int(libc::O_CREAT),
"O_TRUNC" => ctx.new_int(libc::O_TRUNC),
"F_OK" => ctx.new_int(0),
"R_OK" => ctx.new_int(4),
"W_OK" => ctx.new_int(2),
"X_OK" => ctx.new_int(1),
"SEEK_SET" => ctx.new_int(libc::SEEK_SET),
"SEEK_CUR" => ctx.new_int(libc::SEEK_CUR),
"SEEK_END" => ctx.new_int(libc::SEEK_END),
});
for support in support_funcs {
@@ -1406,9 +1422,6 @@ fn extend_module_platform_specific(vm: &VirtualMachine, module: PyObjectRef) ->
"O_NDELAY" => ctx.new_int(libc::O_NDELAY),
"O_NOCTTY" => ctx.new_int(libc::O_NOCTTY),
"O_CLOEXEC" => ctx.new_int(libc::O_CLOEXEC),
"SEEK_SET" => ctx.new_int(Whence::SeekSet as i8),
"SEEK_CUR" => ctx.new_int(Whence::SeekCur as i8),
"SEEK_END" => ctx.new_int(Whence::SeekEnd as i8),
});
#[cfg(not(target_os = "redox"))]

View File

@@ -204,25 +204,23 @@ impl PySocket {
#[pymethod]
fn send(&self, bytes: PyBytesLike, vm: &VirtualMachine) -> PyResult<usize> {
// TODO: use PyBytesLike.with_ref() instead of to_cow()
self.sock()
.send(bytes.to_cow().as_ref())
bytes
.with_ref(|b| self.sock().send(b))
.map_err(|err| convert_sock_error(vm, err))
}
#[pymethod]
fn sendall(&self, bytes: PyBytesLike, vm: &VirtualMachine) -> PyResult<()> {
self.sock
.borrow_mut()
.write_all(bytes.to_cow().as_ref())
bytes
.with_ref(|b| self.sock.borrow_mut().write_all(b))
.map_err(|err| convert_sock_error(vm, err))
}
#[pymethod]
fn sendto(&self, bytes: PyBytesLike, address: Address, vm: &VirtualMachine) -> PyResult<()> {
let addr = get_addr(vm, address)?;
self.sock()
.send_to(bytes.to_cow().as_ref(), &addr)
bytes
.with_ref(|b| self.sock().send_to(b, &addr))
.map_err(|err| convert_sock_error(vm, err))?;
Ok(())
}

View File

@@ -1,18 +1,17 @@
#![allow(non_snake_case)]
use std::io;
use winapi::shared::winerror;
use winapi::um::winnt::HANDLE;
use winapi::um::{handleapi, winbase};
use super::os::convert_io_error;
use super::os;
use crate::pyobject::{PyObjectRef, PyResult};
use crate::VirtualMachine;
fn winapi_CloseHandle(handle: usize, vm: &VirtualMachine) -> PyResult<()> {
let res = unsafe { handleapi::CloseHandle(handle as HANDLE) };
if res == 0 {
Err(convert_io_error(vm, io::Error::last_os_error()))
Err(os::errno_err(vm))
} else {
Ok(())
}