X Tutup
using System; using System.Linq; using System.Collections.Generic; using System.Dynamic; using System.Runtime.Serialization; namespace Python.Runtime { [Serializable] public class PyModule : PyObject { internal BorrowedReference variables => VarsRef; internal BorrowedReference VarsRef { get { var vars = Runtime.PyModule_GetDict(Reference); PythonException.ThrowIfIsNull(vars); return vars; } } public PyModule(string name = "") : this(Create(name)) { InitializeBuiltins(); } static StolenReference Create(string name) { if (name is null) { throw new ArgumentNullException(nameof(name)); } return Runtime.PyModule_New(name).StealOrThrow(); } internal PyModule(in StolenReference reference) : base(reference) { if (!IsModule(Reference)) { throw new ArgumentException("object is not a module"); } } protected PyModule(SerializationInfo info, StreamingContext context) : base(info, context) { } private void InitializeBuiltins() { int res = Runtime.PyDict_SetItem( VarsRef, PyIdentifier.__builtins__, Runtime.PyEval_GetBuiltins() ); PythonException.ThrowIfIsNotZero(res); } internal PyModule(BorrowedReference reference) : this(new NewReference(reference).Steal()) { } /// /// Given a module or package name, import the module and return the resulting object. /// /// Fully-qualified module or package name public static PyObject Import(string name) { if (name is null) throw new ArgumentNullException(nameof(name)); NewReference op = Runtime.PyImport_ImportModule(name); return IsModule(op.BorrowOrThrow()) ? new PyModule(op.Steal()) : op.MoveToPyObject(); } /// /// Reloads the module, and returns the updated object /// public PyModule Reload() { NewReference op = Runtime.PyImport_ReloadModule(this.Reference); return new PyModule(op.StealOrThrow()); } public static PyModule FromString(string name, string code) { return FromString(name, code, ""); } public static PyModule FromString(string name, string code, string file) { // Force valid value if (string.IsNullOrWhiteSpace(file)) { file = "none"; } using NewReference c = Runtime.Py_CompileString(code, file, (int)RunFlagType.File); NewReference m = Runtime.PyImport_ExecCodeModule(name, c.BorrowOrThrow()); return new PyModule(m.StealOrThrow()); } public PyModule SetBuiltins(PyDict builtins) { if (builtins == null || builtins.IsNone()) { throw new ArgumentNullException(nameof(builtins)); } BorrowedReference globals = Runtime.PyModule_GetDict(this.Reference); PythonException.ThrowIfIsNull(globals); int rc = Runtime.PyDict_SetItemString(globals, "__builtins__", builtins.Reference); PythonException.ThrowIfIsNotZero(rc); return this; } public static PyDict SysModules { get { BorrowedReference sysModulesRef = Runtime.PyImport_GetModuleDict(); PythonException.ThrowIfIsNull(sysModulesRef); return new PyDict(sysModulesRef); } } internal static bool IsModule(BorrowedReference reference) { if (reference == null) return false; BorrowedReference type = Runtime.PyObject_TYPE(reference); return Runtime.PyType_IsSubtype(type, Runtime.PyModuleType); } /// /// Returns the variables dict of the module. /// public PyDict Variables() => new(VarsRef); /// /// Create a scope, and import all from this scope /// public PyModule NewScope() { var scope = new PyModule(); scope.ImportAll(this); return scope; } /// /// Import module by its name. /// public PyObject Import(string name, string? asname = null) { Check(); asname ??= name; var module = PyModule.Import(name); Import(module, asname); return module; } /// /// Import module as a variable of given name. /// public void Import(PyModule module, string asname) { if (module is null) throw new ArgumentNullException(nameof(module)); if (asname is null) throw new ArgumentNullException(nameof(asname)); this.SetPyValue(asname, module); } /// /// The 'import .. as ..' statement in Python. /// Import a module as a variable. /// public void Import(PyObject module, string? asname = null) { if (module is null) throw new ArgumentNullException(nameof(module)); asname ??= module.GetAttr("__name__").As(); if (asname is null) throw new ArgumentException("Module has no name"); Set(asname, module); } /// /// Import all variables of the module into this module. /// public void ImportAll(PyModule module) { if (module is null) throw new ArgumentNullException(nameof(module)); int result = Runtime.PyDict_Update(VarsRef, module.VarsRef); if (result < 0) { throw PythonException.ThrowLastAsClrException(); } } /// /// Import all variables of the module into this module. /// public void ImportAll(PyObject module) { if (module is null) throw new ArgumentNullException(nameof(module)); if (!IsModule(module.Reference)) { throw new ArgumentException("object is not a module", paramName: nameof(module)); } var module_dict = Runtime.PyModule_GetDict(module.Reference); int result = Runtime.PyDict_Update(VarsRef, module_dict); if (result < 0) { throw PythonException.ThrowLastAsClrException(); } } /// /// Import all variables in the dictionary into this module. /// public void ImportAll(PyDict dict) { if (dict is null) throw new ArgumentNullException(nameof(dict)); int result = Runtime.PyDict_Update(VarsRef, dict.Reference); if (result < 0) { throw PythonException.ThrowLastAsClrException(); } } /// /// Execute method /// /// /// Execute a Python ast and return the result as a PyObject. /// The ast can be either an expression or stmts. /// public PyObject Execute(PyObject script, PyDict? locals = null) { if (script is null) throw new ArgumentNullException(nameof(script)); Check(); BorrowedReference _locals = locals == null ? variables : locals.obj; using var ptr = Runtime.PyEval_EvalCode(script, variables, _locals); PythonException.ThrowIfIsNull(ptr); return ptr.MoveToPyObject(); } /// /// Execute a Python ast and return the result as a , /// and convert the result to a Managed Object of given type. /// The ast can be either an expression or stmts. /// public T? Execute(PyObject script, PyDict? locals = null) { Check(); PyObject pyObj = Execute(script, locals); var obj = pyObj.As(); return obj; } /// /// Evaluate a Python expression and return the result as a . /// public PyObject Eval(string code, PyDict? locals = null) { if (code is null) throw new ArgumentNullException(nameof(code)); Check(); BorrowedReference _locals = locals == null ? VarsRef : locals.Reference; NewReference reference = Runtime.PyRun_String( code, RunFlagType.Eval, VarsRef, _locals ); PythonException.ThrowIfIsNull(reference); return reference.MoveToPyObject(); } /// /// Evaluate a Python expression /// /// /// Evaluate a Python expression /// and convert the result to a Managed Object of given type. /// public T? Eval(string code, PyDict? locals = null) { Check(); PyObject pyObj = Eval(code, locals); var obj = pyObj.As(); return obj; } /// /// Exec Method /// /// /// Exec a Python script and save its local variables in the current local variable dict. /// public PyModule Exec(string code, PyDict? locals = null) { Check(); BorrowedReference _locals = locals == null ? VarsRef : locals.Reference; Exec(code, VarsRef, _locals); return this; } private void Exec(string code, BorrowedReference _globals, BorrowedReference _locals) { using NewReference reference = Runtime.PyRun_String( code, RunFlagType.File, _globals, _locals ); PythonException.ThrowIfIsNull(reference); } /// /// Set Variable Method /// /// /// Add a new variable to the variables dict if it not exist /// or update its value if the variable exists. /// public PyModule Set(string name, object? value) { if (name is null) throw new ArgumentNullException(nameof(name)); using var _value = Converter.ToPythonDetectType(value); SetPyValue(name, _value.Borrow()); return this; } private void SetPyValue(string name, BorrowedReference value) { Check(); using var pyKey = new PyString(name); int r = Runtime.PyObject_SetItem(variables, pyKey.obj, value); if (r < 0) { throw PythonException.ThrowLastAsClrException(); } } /// /// Remove Method /// /// /// Remove a variable from the variables dict. /// public PyModule Remove(string name) { if (name is null) throw new ArgumentNullException(nameof(name)); Check(); using (var pyKey = new PyString(name)) { int r = Runtime.PyObject_DelItem(variables, pyKey.obj); if (r < 0) { throw PythonException.ThrowLastAsClrException(); } } return this; } /// /// Returns true if the variable exists in the module. /// public bool Contains(string name) { if (name is null) throw new ArgumentNullException(nameof(name)); Check(); using var pyKey = new PyString(name); return Runtime.PyMapping_HasKey(variables, pyKey.obj) != 0; } /// /// Returns the value of the variable with the given name. /// /// /// Thrown when variable with the given name does not exist. /// public PyObject Get(string name) { if (name is null) throw new ArgumentNullException(nameof(name)); var state = TryGet(name, out var value); if (!state) { throw new KeyNotFoundException($"The module has no attribute '{name}'"); } return value!; } /// /// TryGet Method /// /// /// Returns the value of the variable, local variable first. /// If the variable does not exist, return null. /// public bool TryGet(string name, out PyObject? value) { if (name is null) throw new ArgumentNullException(nameof(name)); Check(); using var pyKey = new PyString(name); if (Runtime.PyMapping_HasKey(variables, pyKey.obj) != 0) { using var op = Runtime.PyObject_GetItem(variables, pyKey.obj); value = new PyObject(op.StealOrThrow()); return true; } else { value = null; return false; } } /// /// Get Method /// /// /// Obtain the value of the variable of given name, /// and convert the result to a Managed Object of given type. /// If the variable does not exist, throw an Exception. /// public T Get(string name) { if (name is null) throw new ArgumentNullException(nameof(name)); Check(); PyObject pyObj = Get(name); return pyObj.As()!; } /// /// TryGet Method /// /// /// Obtain the value of the variable of given name, /// and convert the result to a Managed Object of given type. /// If the variable does not exist, return false. /// public bool TryGet(string name, out T? value) { Check(); var result = TryGet(name, out var pyObj); if (!result) { value = default; return false; } value = pyObj!.As(); return true; } public override bool TryGetMember(GetMemberBinder binder, out object? result) { result = CheckNone(this.Get(binder.Name)); return true; } public override bool TrySetMember(SetMemberBinder binder, object? value) { this.Set(binder.Name, value); return true; } private void Check() { if (this.rawPtr == IntPtr.Zero) { throw new ObjectDisposedException(nameof(PyModule)); } } } }
X Tutup