|
15 | 15 |
|
16 | 16 | ## Modifications for ↓, ↑ |
17 | 17 | Sym(x::Nothing) = Sym(pybuiltins.None) |
| 18 | + |
18 | 19 | SymPyCore.:↓(x::PythonCall.Py) = x |
19 | 20 | SymPyCore.:↓(d::Dict) = pydict((↓(k) => ↓(v) for (k,v) ∈ pairs(d))) |
20 | 21 | SymPyCore.:↓(x::Set) = _sympy_.sympify(pyset(↓(sᵢ) for sᵢ ∈ x)) |
21 | 22 |
|
22 | | -SymPyCore.:↑(::Type{<:AbstractString}, x) = Py(x) |
| 23 | +SymPyCore.:↑(::Type{<:AbstractString}, x) = Sym(Py(x)) |
23 | 24 | function SymPyCore.:↑(::Type{PythonCall.Py}, x) |
24 | | - class_nm = SymPyCore.classname(x) |
25 | | - class_nm == "set" && return Set(Sym.(collect(x))) |
26 | | - class_nm == "tuple" && return Tuple(↑(xᵢ) for xᵢ ∈ x) |
27 | | - class_nm == "list" && return [↑(xᵢ) for xᵢ ∈ x] |
28 | | - class_nm == "dict" && return Dict(↑(k) => ↑(x[k]) for k ∈ x) |
29 | | - |
30 | | - class_nm == "FiniteSet" && return Set(Sym.(collect(x))) |
31 | | - class_nm == "MutableDenseMatrix" && return _up_matrix(x) #map(↑, x.tolist()) |
| 25 | + # this lower level approach shouldn't allocate |
| 26 | + pyisinstance(x, pybuiltins.set) && return Set(Sym.(x)) #Set(↑(xᵢ) for xᵢ ∈ x) |
| 27 | + pyisinstance(x, pybuiltins.tuple) && return Tuple(↑(xᵢ) for xᵢ ∈ x) |
| 28 | + pyisinstance(x, pybuiltins.list) && return [↑(xᵢ) for xᵢ ∈ x] |
| 29 | + pyisinstance(x, pybuiltins.dict) && return Dict(↑(k) => ↑(x[k]) for k ∈ x) |
32 | 30 |
|
33 | | - # others ... more hands on than pytype_mapping |
| 31 | + # add more sympy containers in sympy.jl and here |
| 32 | + pyisinstance(x, _FiniteSet_) && return Set(Sym.(x)) |
| 33 | + pyisinstance(x, _MutableDenseMatrix_) && return _up_matrix(x) #map(↑, x.tolist()) |
34 | 34 |
|
| 35 | + # fallback |
35 | 36 | Sym(x) |
36 | 37 | end |
37 | 38 |
|
|
52 | 53 |
|
53 | 54 | # should we also have different code path for a::String like PyCall? |
54 | 55 | function Base.getproperty(x::SymbolicObject{T}, a::Symbol) where {T <: PythonCall.Py} |
| 56 | + |
55 | 57 | a == :o && return getfield(x, a) |
| 58 | + |
56 | 59 | if a == :py |
57 | 60 | Base.depwarn("The field `.py` has been renamed `.o`", :getproperty) |
58 | 61 | return getfield(x,:o) |
59 | 62 | end |
60 | 63 |
|
61 | 64 | val = ↓(x) |
62 | | - !hasproperty(val, a) && return nothing # not a property |
| 65 | + 𝑎 = string(a) |
63 | 66 |
|
64 | | - meth = getproperty(val, a) |
| 67 | + hasproperty(val, 𝑎) || return nothing # not a property |
| 68 | + meth = getproperty(val, 𝑎) |
65 | 69 |
|
66 | | - pyconvert(Bool, meth == pybuiltins.None) && return nothing |
| 70 | + pyis(meth, pybuiltins.None) && return nothing |
67 | 71 |
|
68 | | - if hasproperty(meth, "is_Boolean") |
69 | | - if pyconvert(Bool, meth.is_Boolean == true) |
70 | | - return meth == _sympy_.logic.boolalg.BooleanFalse |
71 | | - end |
| 72 | + ## __call__ |
| 73 | + if pycallable(meth) # "__call__") #hasproperty(meth, "__call__") |
| 74 | + return SymPyCore.SymbolicCallable(meth) |
72 | 75 | end |
73 | 76 |
|
74 | 77 | # __class__ dispatch |
75 | | - if hasproperty(meth, :__class__) |
76 | | - cnm = string(meth.__class__.__name__) |
77 | | - if cnm == "bool" |
78 | | - return pyconvert(Bool, meth) |
79 | | - end |
80 | | - if cnm == "module" |
81 | | - # treat modules, callsm others differently |
82 | | - return Sym(meth) |
83 | | - end |
| 78 | + if pyisinstance(meth, _bool_) |
| 79 | + return pyconvert(Bool, meth) |
84 | 80 | end |
85 | 81 |
|
86 | | - ## __call__ |
87 | | - if hasproperty(meth, "__call__") |
88 | | - return SymPyCore.SymbolicCallable(meth) |
| 82 | + if pyisinstance(meth, _ModuleType_) |
| 83 | + return Sym(meth) |
89 | 84 | end |
90 | 85 |
|
| 86 | + |
| 87 | + # just convert |
91 | 88 | return ↑(convert(PythonCall.Py, meth)) |
92 | 89 |
|
93 | 90 | end |
|
0 commit comments