mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Merge pull request #2001 from RustPython/coolreader18/update-pwd
Update the pwd module
This commit is contained in:
7 files changed
+211
-154
No files matched your search
Generated
+10
-83
@@ -104,28 +104,6 @@ version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4ed64ae6d9ebfd9893193c4b2532b1292ec97bd8271c9d7d0fa90cd78a34cba"
|
||||
dependencies = [
|
||||
"backtrace-sys",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"rustc-demangle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace-sys"
|
||||
version = "0.1.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7de8aba10a69c8e8d7622c5710229485ec32e9d55fdad160ea559c086fdcd118"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.11.0"
|
||||
@@ -532,28 +510,6 @@ version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de853764b47027c2e862a995c34978ffa63c1501f2e15f987ba11bd4f9bba193"
|
||||
|
||||
[[package]]
|
||||
name = "failure"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8529c2421efa3066a5cbd8063d2244603824daccb6936b079010bb2aa89464b"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"failure_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "failure_derive"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "030a733c8287d6213886dd487564ff5c8f6aae10278b3588ed177f9d18f8d231"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.10",
|
||||
"quote 1.0.3",
|
||||
"syn 1.0.17",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fake-simd"
|
||||
version = "0.1.2"
|
||||
@@ -964,9 +920,9 @@ checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.2.6"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304"
|
||||
checksum = "b7f3fc75e3697059fb1bc465e3d8cca6cf92f56854f201158b3f9c77d5a3cfa0"
|
||||
dependencies = [
|
||||
"autocfg 1.0.0",
|
||||
"num-integer",
|
||||
@@ -987,9 +943,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.42"
|
||||
version = "0.1.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba"
|
||||
checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b"
|
||||
dependencies = [
|
||||
"autocfg 1.0.0",
|
||||
"num-traits",
|
||||
@@ -997,9 +953,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "num-iter"
|
||||
version = "0.1.40"
|
||||
version = "0.1.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dfb0800a0291891dd9f4fe7bd9c19384f98f7fbe0cd0f39a2c6b88b9868bbc00"
|
||||
checksum = "7a6e6b7c748f995c4c29c5f5ae0248536e04a5739927c74ec0fa564805094b9f"
|
||||
dependencies = [
|
||||
"autocfg 1.0.0",
|
||||
"num-integer",
|
||||
@@ -1008,9 +964,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "num-rational"
|
||||
version = "0.2.4"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef"
|
||||
checksum = "a5b4d7360f362cfb50dde8143501e6940b22f644be75a4cc90b2d81968908138"
|
||||
dependencies = [
|
||||
"autocfg 1.0.0",
|
||||
"num-bigint",
|
||||
@@ -1020,9 +976,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.11"
|
||||
version = "0.2.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096"
|
||||
checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611"
|
||||
dependencies = [
|
||||
"autocfg 1.0.0",
|
||||
]
|
||||
@@ -1259,16 +1215,6 @@ dependencies = [
|
||||
"unicode-xid 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pwd"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5dd32d8bece608e144ca20251e714ed107cdecdabb20c2d383cfc687825106a5"
|
||||
dependencies = [
|
||||
"failure",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "python3-sys"
|
||||
version = "0.2.1"
|
||||
@@ -1524,12 +1470,6 @@ dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.2.3"
|
||||
@@ -1685,7 +1625,6 @@ dependencies = [
|
||||
"openssl-sys",
|
||||
"parking_lot",
|
||||
"paste",
|
||||
"pwd",
|
||||
"rand 0.7.3",
|
||||
"rand_core 0.5.1",
|
||||
"regex",
|
||||
@@ -2001,18 +1940,6 @@ dependencies = [
|
||||
"unicode-xid 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "synstructure"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.10",
|
||||
"quote 1.0.3",
|
||||
"syn 1.0.17",
|
||||
"unicode-xid 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "term"
|
||||
version = "0.5.2"
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
import sys
|
||||
import unittest
|
||||
from test import support
|
||||
|
||||
pwd = support.import_module('pwd')
|
||||
|
||||
@unittest.skipUnless(hasattr(pwd, 'getpwall'), 'Does not have getpwall()')
|
||||
class PwdTest(unittest.TestCase):
|
||||
|
||||
def test_values(self):
|
||||
entries = pwd.getpwall()
|
||||
|
||||
for e in entries:
|
||||
self.assertEqual(len(e), 7)
|
||||
self.assertEqual(e[0], e.pw_name)
|
||||
self.assertIsInstance(e.pw_name, str)
|
||||
self.assertEqual(e[1], e.pw_passwd)
|
||||
self.assertIsInstance(e.pw_passwd, str)
|
||||
self.assertEqual(e[2], e.pw_uid)
|
||||
self.assertIsInstance(e.pw_uid, int)
|
||||
self.assertEqual(e[3], e.pw_gid)
|
||||
self.assertIsInstance(e.pw_gid, int)
|
||||
self.assertEqual(e[4], e.pw_gecos)
|
||||
self.assertIsInstance(e.pw_gecos, str)
|
||||
self.assertEqual(e[5], e.pw_dir)
|
||||
self.assertIsInstance(e.pw_dir, str)
|
||||
self.assertEqual(e[6], e.pw_shell)
|
||||
self.assertIsInstance(e.pw_shell, str)
|
||||
|
||||
# The following won't work, because of duplicate entries
|
||||
# for one uid
|
||||
# self.assertEqual(pwd.getpwuid(e.pw_uid), e)
|
||||
# instead of this collect all entries for one uid
|
||||
# and check afterwards (done in test_values_extended)
|
||||
|
||||
def test_values_extended(self):
|
||||
entries = pwd.getpwall()
|
||||
entriesbyname = {}
|
||||
entriesbyuid = {}
|
||||
|
||||
if len(entries) > 1000: # Huge passwd file (NIS?) -- skip this test
|
||||
self.skipTest('passwd file is huge; extended test skipped')
|
||||
|
||||
for e in entries:
|
||||
entriesbyname.setdefault(e.pw_name, []).append(e)
|
||||
entriesbyuid.setdefault(e.pw_uid, []).append(e)
|
||||
|
||||
# check whether the entry returned by getpwuid()
|
||||
# for each uid is among those from getpwall() for this uid
|
||||
for e in entries:
|
||||
if not e[0] or e[0] == '+':
|
||||
continue # skip NIS entries etc.
|
||||
self.assertIn(pwd.getpwnam(e.pw_name), entriesbyname[e.pw_name])
|
||||
self.assertIn(pwd.getpwuid(e.pw_uid), entriesbyuid[e.pw_uid])
|
||||
|
||||
def test_errors(self):
|
||||
self.assertRaises(TypeError, pwd.getpwuid)
|
||||
self.assertRaises(TypeError, pwd.getpwuid, 3.14)
|
||||
self.assertRaises(TypeError, pwd.getpwnam)
|
||||
self.assertRaises(TypeError, pwd.getpwnam, 42)
|
||||
self.assertRaises(TypeError, pwd.getpwall, 42)
|
||||
|
||||
# try to get some errors
|
||||
bynames = {}
|
||||
byuids = {}
|
||||
for (n, p, u, g, gecos, d, s) in pwd.getpwall():
|
||||
bynames[n] = u
|
||||
byuids[u] = n
|
||||
|
||||
allnames = list(bynames.keys())
|
||||
namei = 0
|
||||
fakename = allnames[namei]
|
||||
while fakename in bynames:
|
||||
chars = list(fakename)
|
||||
for i in range(len(chars)):
|
||||
if chars[i] == 'z':
|
||||
chars[i] = 'A'
|
||||
break
|
||||
elif chars[i] == 'Z':
|
||||
continue
|
||||
else:
|
||||
chars[i] = chr(ord(chars[i]) + 1)
|
||||
break
|
||||
else:
|
||||
namei = namei + 1
|
||||
try:
|
||||
fakename = allnames[namei]
|
||||
except IndexError:
|
||||
# should never happen... if so, just forget it
|
||||
break
|
||||
fakename = ''.join(chars)
|
||||
|
||||
self.assertRaises(KeyError, pwd.getpwnam, fakename)
|
||||
|
||||
# In some cases, byuids isn't a complete list of all users in the
|
||||
# system, so if we try to pick a value not in byuids (via a perturbing
|
||||
# loop, say), pwd.getpwuid() might still be able to find data for that
|
||||
# uid. Using sys.maxint may provoke the same problems, but hopefully
|
||||
# it will be a more repeatable failure.
|
||||
fakeuid = sys.maxsize
|
||||
self.assertNotIn(fakeuid, byuids)
|
||||
self.assertRaises(KeyError, pwd.getpwuid, fakeuid)
|
||||
|
||||
# -1 shouldn't be a valid uid because it has a special meaning in many
|
||||
# uid-related functions
|
||||
self.assertRaises(KeyError, pwd.getpwuid, -1)
|
||||
# should be out of uid_t range
|
||||
self.assertRaises(KeyError, pwd.getpwuid, 2**128)
|
||||
self.assertRaises(KeyError, pwd.getpwuid, -2**128)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
+1
-1
@@ -12,7 +12,7 @@ license = "MIT"
|
||||
bincode = "1.1"
|
||||
bitflags = "1.1"
|
||||
lz4-compress = "0.1.1"
|
||||
num-bigint = { version = "0.2", features = ["serde"] }
|
||||
num-bigint = { version = "0.3", features = ["serde"] }
|
||||
num-complex = { version = "0.2", features = ["serde"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
itertools = "0.8"
|
||||
+1
-1
@@ -14,7 +14,7 @@ lalrpop="0.17"
|
||||
[dependencies]
|
||||
lalrpop-util="0.17"
|
||||
log="0.4.1"
|
||||
num-bigint = "0.2"
|
||||
num-bigint = "0.3"
|
||||
num-traits = "0.2"
|
||||
unic-emoji-char = "0.9"
|
||||
unic-ucd-ident = "0.9"
|
||||
|
||||
+2
-5
@@ -27,10 +27,10 @@ blake2 = "0.8"
|
||||
volatile = "0.2"
|
||||
|
||||
num-complex = { version = "0.2.2", features = ["serde"] }
|
||||
num-bigint = { version = "0.2.4", features = ["serde"] }
|
||||
num-bigint = { version = "0.3", features = ["serde"] }
|
||||
num-traits = "0.2.8"
|
||||
num-integer = "0.1.41"
|
||||
num-rational = "0.2.2"
|
||||
num-rational = "0.3"
|
||||
num-iter = "0.1.39"
|
||||
rand = { version = "0.7", features = ["wasm-bindgen"] }
|
||||
rand_core = "0.5"
|
||||
@@ -92,9 +92,6 @@ unic-ucd-ident = "0.9"
|
||||
flame = { version = "0.2", optional = true }
|
||||
flamer = { version = "0.3", optional = true }
|
||||
|
||||
[target.'cfg(all(unix, not(any(target_os = "android", target_os = "redox"))))'.dependencies]
|
||||
pwd = "1"
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
exitcode = "1.1.2"
|
||||
uname = "0.1.1"
|
||||
|
||||
@@ -124,7 +124,7 @@ fn inner_pow(int1: &BigInt, int2: &BigInt, vm: &VirtualMachine) -> PyResult {
|
||||
objfloat::float_pow(v1, v2, vm).into_pyobject(vm)
|
||||
} else {
|
||||
Ok(if let Some(v2) = int2.to_u64() {
|
||||
vm.ctx.new_int(int1.pow(v2))
|
||||
vm.ctx.new_int(Pow::pow(int1, v2))
|
||||
} else if int1.is_one() {
|
||||
vm.ctx.new_int(1)
|
||||
} else if int1.is_zero() {
|
||||
@@ -519,7 +519,7 @@ impl PyInt {
|
||||
|
||||
#[pymethod(name = "__sizeof__")]
|
||||
fn sizeof(&self) -> usize {
|
||||
size_of::<Self>() + ((self.value.bits() + 7) & !7) / 8
|
||||
size_of::<Self>() + (((self.value.bits() + 7) & !7) / 8) as usize
|
||||
}
|
||||
|
||||
#[pymethod(name = "as_integer_ratio")]
|
||||
@@ -531,7 +531,7 @@ impl PyInt {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn bit_length(&self) -> usize {
|
||||
fn bit_length(&self) -> u64 {
|
||||
self.value.bits()
|
||||
}
|
||||
|
||||
|
||||
+82
-61
@@ -1,52 +1,54 @@
|
||||
use pwd::Passwd;
|
||||
|
||||
use super::os::convert_nix_error;
|
||||
use crate::obj::objint::PyIntRef;
|
||||
use crate::obj::objstr::PyStringRef;
|
||||
use crate::obj::objtype::PyClassRef;
|
||||
use crate::pyobject::{PyObjectRef, PyRef, PyResult, PyValue};
|
||||
use crate::pyobject::{PyClassImpl, PyObjectRef, PyResult};
|
||||
use crate::vm::VirtualMachine;
|
||||
use std::convert::TryFrom;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
impl PyValue for Passwd {
|
||||
fn class(vm: &VirtualMachine) -> PyClassRef {
|
||||
vm.class("pwd", "struct_passwd")
|
||||
use nix::unistd::{self, User};
|
||||
|
||||
#[pystruct_sequence(name = "pwd.struct_passwd")]
|
||||
struct Passwd {
|
||||
pw_name: String,
|
||||
pw_passwd: String,
|
||||
pw_uid: u32,
|
||||
pw_gid: u32,
|
||||
pw_gecos: String,
|
||||
pw_dir: String,
|
||||
pw_shell: String,
|
||||
}
|
||||
|
||||
impl From<User> for Passwd {
|
||||
fn from(user: User) -> Self {
|
||||
// this is just a pain...
|
||||
let cstr_lossy = |s: std::ffi::CString| {
|
||||
s.into_string()
|
||||
.unwrap_or_else(|e| e.into_cstring().to_string_lossy().into_owned())
|
||||
};
|
||||
let pathbuf_lossy = |p: std::path::PathBuf| {
|
||||
p.into_os_string()
|
||||
.into_string()
|
||||
.unwrap_or_else(|s| s.to_string_lossy().into_owned())
|
||||
};
|
||||
Passwd {
|
||||
pw_name: user.name,
|
||||
pw_passwd: cstr_lossy(user.passwd),
|
||||
pw_uid: user.uid.as_raw(),
|
||||
pw_gid: user.gid.as_raw(),
|
||||
pw_gecos: cstr_lossy(user.gecos),
|
||||
pw_dir: pathbuf_lossy(user.dir),
|
||||
pw_shell: pathbuf_lossy(user.shell),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type PasswdRef = PyRef<Passwd>;
|
||||
|
||||
impl PasswdRef {
|
||||
fn pw_name(self) -> String {
|
||||
self.name.clone()
|
||||
}
|
||||
|
||||
fn pw_passwd(self) -> Option<String> {
|
||||
self.passwd.clone()
|
||||
}
|
||||
|
||||
fn pw_uid(self) -> u32 {
|
||||
self.uid
|
||||
}
|
||||
|
||||
fn pw_gid(self) -> u32 {
|
||||
self.gid
|
||||
}
|
||||
|
||||
fn pw_gecos(self) -> Option<String> {
|
||||
self.gecos.clone()
|
||||
}
|
||||
|
||||
fn pw_dir(self) -> String {
|
||||
self.dir.clone()
|
||||
}
|
||||
|
||||
fn pw_shell(self) -> String {
|
||||
self.shell.clone()
|
||||
}
|
||||
}
|
||||
|
||||
fn pwd_getpwnam(name: PyStringRef, vm: &VirtualMachine) -> PyResult<Passwd> {
|
||||
match Passwd::from_name(name.as_str()) {
|
||||
Ok(Some(passwd)) => Ok(passwd),
|
||||
_ => {
|
||||
fn pwd_getpwnam(name: PyStringRef, vm: &VirtualMachine) -> PyResult {
|
||||
match User::from_name(name.as_str()).map_err(|e| convert_nix_error(vm, e))? {
|
||||
Some(user) => Ok(Passwd::from(user)
|
||||
.into_struct_sequence(vm, vm.try_class("pwd", "struct_passwd")?)?
|
||||
.into_object()),
|
||||
None => {
|
||||
let name_repr = vm.to_repr(name.as_object())?;
|
||||
let message = vm.new_str(format!("getpwnam(): name not found: {}", name_repr));
|
||||
Err(vm.new_key_error(message))
|
||||
@@ -54,32 +56,51 @@ fn pwd_getpwnam(name: PyStringRef, vm: &VirtualMachine) -> PyResult<Passwd> {
|
||||
}
|
||||
}
|
||||
|
||||
fn pwd_getpwuid(uid: u32, vm: &VirtualMachine) -> PyResult<Passwd> {
|
||||
match Passwd::from_uid(uid) {
|
||||
Some(passwd) => Ok(passwd),
|
||||
_ => {
|
||||
let message = vm.new_str(format!("getpwuid(): uid not found: {}", uid));
|
||||
fn pwd_getpwuid(uid: PyIntRef, vm: &VirtualMachine) -> PyResult {
|
||||
let uid_t = libc::uid_t::try_from(uid.as_bigint()).map(unistd::Uid::from_raw);
|
||||
let user = match uid_t {
|
||||
Ok(uid) => User::from_uid(uid).map_err(|e| convert_nix_error(vm, e))?,
|
||||
Err(_) => None,
|
||||
};
|
||||
match user {
|
||||
Some(user) => Ok(Passwd::from(user)
|
||||
.into_struct_sequence(vm, vm.try_class("pwd", "struct_passwd")?)?
|
||||
.into_object()),
|
||||
None => {
|
||||
let message = vm.new_str(format!("getpwuid(): uid not found: {}", uid.as_bigint()));
|
||||
Err(vm.new_key_error(message))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: maybe merge this functionality into nix?
|
||||
fn pwd_getpwall(vm: &VirtualMachine) -> PyResult {
|
||||
// setpwent, getpwent, etc are not thread safe. Could use fgetpwent_r, but this is easier
|
||||
static GETPWALL: parking_lot::Mutex<()> = parking_lot::const_mutex(());
|
||||
let _guard = GETPWALL.lock();
|
||||
let mut list = Vec::new();
|
||||
let cls = vm.try_class("pwd", "struct_passwd")?;
|
||||
|
||||
unsafe { libc::setpwent() };
|
||||
while let Some(ptr) = NonNull::new(unsafe { libc::getpwent() }) {
|
||||
let user = User::from(unsafe { ptr.as_ref() });
|
||||
let passwd = Passwd::from(user)
|
||||
.into_struct_sequence(vm, cls.clone())?
|
||||
.into_object();
|
||||
list.push(passwd);
|
||||
}
|
||||
unsafe { libc::endpwent() };
|
||||
|
||||
Ok(vm.ctx.new_list(list))
|
||||
}
|
||||
|
||||
pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
|
||||
let ctx = &vm.ctx;
|
||||
|
||||
let passwd_type = py_class!(ctx, "struct_passwd", ctx.object(), {
|
||||
"pw_name" => ctx.new_readonly_getset("pw_name", PasswdRef::pw_name),
|
||||
"pw_passwd" => ctx.new_readonly_getset("pw_passwd", PasswdRef::pw_passwd),
|
||||
"pw_uid" => ctx.new_readonly_getset("pw_uid", PasswdRef::pw_uid),
|
||||
"pw_gid" => ctx.new_readonly_getset("pw_gid", PasswdRef::pw_gid),
|
||||
"pw_gecos" => ctx.new_readonly_getset("pw_gecos", PasswdRef::pw_gecos),
|
||||
"pw_dir" => ctx.new_readonly_getset("pw_dir", PasswdRef::pw_dir),
|
||||
"pw_shell" => ctx.new_readonly_getset("pw_shell", PasswdRef::pw_shell),
|
||||
});
|
||||
|
||||
py_module!(vm, "pwd", {
|
||||
"struct_passwd" => passwd_type,
|
||||
"getpwnam" => ctx.new_function(pwd_getpwnam),
|
||||
"getpwuid" => ctx.new_function(pwd_getpwuid),
|
||||
"struct_passwd" => Passwd::make_class(ctx),
|
||||
"getpwnam" => named_function!(ctx, pwd, getpwnam),
|
||||
"getpwuid" => named_function!(ctx, pwd, getpwuid),
|
||||
"getpwall" => named_function!(ctx, pwd, getpwall),
|
||||
})
|
||||
}
|
||||
Reference in new issue
Block a user