Skip to main content

The python 'dict' object is ubiquitous when interacting with python modules, functions and classes.

The process to create a python DICT object using the U2 BASIC Python API is, well, interesting:

  1. Create a LIST containing just the 'name' and 'value' for the DICT entry
  2. Create a TUPLE from the list
  3. Append the TUPLE to another LIST that will be used to create the DICT
  4. When the LIST of TUPLE objects is completed, create a DICT using the LIST of TUPLES

This all works ok for strings and numbers, but I cannot get a boolean True or False value to use in the tuple.

I either get an integer value of 1, or 'None'.

This is the code I have tested so far, trying to get a python True object/value:

** Attempting to create a python True object using the PyBASIC API

pmo.BUILTINS = PyImport("builtins")
if len(@PYEXCEPTIONTYPE) then gosub PY.BADNESS

* Using CallMethod to run the "bool(x)" command
test1 = PyCallMethod( pmo.BUILTINS, "bool", (-1))
rslt = PyCallMethod( pmo.BUILTINS, "print", 'test1', test1)

* Using CallMethod to run the "True" value
test2 = PyCallMethod( pmo.BUILTINS, "True")
rslt = PyCallMethod( pmo.BUILTINS, "print", 'test2', test2)

* Create callable PyBobject for bool()
py_bool = PyGetAttr( pmo.BUILTINS, "bool")
if len(@PYEXCEPTIONTYPE) then gosub PY.BADNESS
* Create True using the __new__() method
test3 = PyCallMethod( py_bool, "__new__", (1))
rslt = PyCallMethod( pmo.BUILTINS, "print", 'test3', test3)

* Use the GetAttr method to get the True attribute
test4 = PyGetAttr( pmo.BUILTINS, "True")
rslt = PyCallMethod( pmo.BUILTINS, "print", 'test4', test4)

stop


PY.BADNESS:

crt " EXCEPTION TYPE     = " :@PYEXCEPTIONTYPE
crt " EXCEPTION MESSAGE  = " :squote(@PYEXCEPTIONMSG)
crt " EXCEPTIONTRACEBACK = " :@PYEXCEPTIONTRACEBACK

stop

When I run this all I get is this result:
>RUN GDS.BP TEST.PY.TRUE
test1 1
test2 None
test3 None
test4 1
>

Does anyone have any thoughts on how I can correctly create a True or False python value/object using the U2 BASIC Python API functions?

Whilst I could create python code to do this, I am trying to avoid the need to pre-deploy the python source as this logic is intended to be used as part of our python deployment processing (otherwise I have to deploy code so I can test the installation context to see if I need to deploy code ...).



------------------------------
Gregor Scott
Software Architect
Pentana Solutions Pty Ltd
Mount Waverley VIC AU
------------------------------

The python 'dict' object is ubiquitous when interacting with python modules, functions and classes.

The process to create a python DICT object using the U2 BASIC Python API is, well, interesting:

  1. Create a LIST containing just the 'name' and 'value' for the DICT entry
  2. Create a TUPLE from the list
  3. Append the TUPLE to another LIST that will be used to create the DICT
  4. When the LIST of TUPLE objects is completed, create a DICT using the LIST of TUPLES

This all works ok for strings and numbers, but I cannot get a boolean True or False value to use in the tuple.

I either get an integer value of 1, or 'None'.

This is the code I have tested so far, trying to get a python True object/value:

** Attempting to create a python True object using the PyBASIC API

pmo.BUILTINS = PyImport("builtins")
if len(@PYEXCEPTIONTYPE) then gosub PY.BADNESS

* Using CallMethod to run the "bool(x)" command
test1 = PyCallMethod( pmo.BUILTINS, "bool", (-1))
rslt = PyCallMethod( pmo.BUILTINS, "print", 'test1', test1)

* Using CallMethod to run the "True" value
test2 = PyCallMethod( pmo.BUILTINS, "True")
rslt = PyCallMethod( pmo.BUILTINS, "print", 'test2', test2)

* Create callable PyBobject for bool()
py_bool = PyGetAttr( pmo.BUILTINS, "bool")
if len(@PYEXCEPTIONTYPE) then gosub PY.BADNESS
* Create True using the __new__() method
test3 = PyCallMethod( py_bool, "__new__", (1))
rslt = PyCallMethod( pmo.BUILTINS, "print", 'test3', test3)

* Use the GetAttr method to get the True attribute
test4 = PyGetAttr( pmo.BUILTINS, "True")
rslt = PyCallMethod( pmo.BUILTINS, "print", 'test4', test4)

stop


PY.BADNESS:

crt " EXCEPTION TYPE     = " :@PYEXCEPTIONTYPE
crt " EXCEPTION MESSAGE  = " :squote(@PYEXCEPTIONMSG)
crt " EXCEPTIONTRACEBACK = " :@PYEXCEPTIONTRACEBACK

stop

When I run this all I get is this result:
>RUN GDS.BP TEST.PY.TRUE
test1 1
test2 None
test3 None
test4 1
>

Does anyone have any thoughts on how I can correctly create a True or False python value/object using the U2 BASIC Python API functions?

Whilst I could create python code to do this, I am trying to avoid the need to pre-deploy the python source as this logic is intended to be used as part of our python deployment processing (otherwise I have to deploy code so I can test the installation context to see if I need to deploy code ...).



------------------------------
Gregor Scott
Software Architect
Pentana Solutions Pty Ltd
Mount Waverley VIC AU
------------------------------

Hi Gregor

Not sure about the first half of your question, you can create and populate a dict object directly:

b = PyImport("builtins")

dict = PyCallMethod(b,"dict")

ok = PyCallMethod(dict,"__setitem__","hello","world")

ok = PyCallMethod(dict,"__repr__")

Crt ok

{'hello': 'world'}

However, I can't find a way to send a bool into the __setitem__ without it being coerced into a 1 or zero, either. I suspect it is the passing mechanism not the construction of the bool i.e. 

PyTrue = PyCallMethod(b,"bool",1)

Ok = PyCallMethod(dict,"__setitem__","atrue",PyTrue)

Ok = PyCallMethod(dict,"__repr__")

Crt Ok

{'hello': 'world', 'atrue': 1}



------------------------------
Brian Leach
Director
Brian Leach Consulting
Chipping Norton GB
------------------------------

Hi Gregor

Not sure about the first half of your question, you can create and populate a dict object directly:

b = PyImport("builtins")

dict = PyCallMethod(b,"dict")

ok = PyCallMethod(dict,"__setitem__","hello","world")

ok = PyCallMethod(dict,"__repr__")

Crt ok

{'hello': 'world'}

However, I can't find a way to send a bool into the __setitem__ without it being coerced into a 1 or zero, either. I suspect it is the passing mechanism not the construction of the bool i.e. 

PyTrue = PyCallMethod(b,"bool",1)

Ok = PyCallMethod(dict,"__setitem__","atrue",PyTrue)

Ok = PyCallMethod(dict,"__repr__")

Crt Ok

{'hello': 'world', 'atrue': 1}



------------------------------
Brian Leach
Director
Brian Leach Consulting
Chipping Norton GB
------------------------------

Hi Brian,

Thanks for the confirmation on the "True" object creation - always nice to know it is not just me!

My initial approach to the DICT creation was to use a "pythonic" approach as much as possible.
The dunder __setitem__ function is so much simpler than my approach (and more performant) I think I will consider using more of the "private" python functions wherever possible.



------------------------------
Gregor Scott
Software Architect
Pentana Solutions Pty Ltd
Mount Waverley VIC AU
------------------------------

Hi Gregor

Not sure about the first half of your question, you can create and populate a dict object directly:

b = PyImport("builtins")

dict = PyCallMethod(b,"dict")

ok = PyCallMethod(dict,"__setitem__","hello","world")

ok = PyCallMethod(dict,"__repr__")

Crt ok

{'hello': 'world'}

However, I can't find a way to send a bool into the __setitem__ without it being coerced into a 1 or zero, either. I suspect it is the passing mechanism not the construction of the bool i.e. 

PyTrue = PyCallMethod(b,"bool",1)

Ok = PyCallMethod(dict,"__setitem__","atrue",PyTrue)

Ok = PyCallMethod(dict,"__repr__")

Crt Ok

{'hello': 'world', 'atrue': 1}



------------------------------
Brian Leach
Director
Brian Leach Consulting
Chipping Norton GB
------------------------------

I revised my test code to check the type of variable being returned.

Whilst on UV 11.35 the descrinfo() function does not explicitly recognise a PYOBJECT it does return a "-1" when the type of variable cannot be determined.

The updated code looks like this

** Attempting to create a python True object using the PyBASIC API

pmo.BUILTINS = PyImport("builtins")
if len(@PYEXCEPTIONTYPE) then gosub PY.BADNESS

* Using CallMethod to run the "bool(x)" command
test1 = PyCallMethod( pmo.BUILTINS, "bool", (-1))
rslt = PyCallMethod( pmo.BUILTINS, "print", 'test1', test1)
crt "descrinfo(1,test1)=":descrinfo(1,test1)

* Using CallMethod to run the "True" value
test2 = PyCallMethod( pmo.BUILTINS, "True")
rslt = PyCallMethod( pmo.BUILTINS, "print", 'test2', test2)
crt "descrinfo(1,test2)=":descrinfo(1,test2)

* Create callable PyBobject for bool()
py_bool = PyGetAttr( pmo.BUILTINS, "bool")
if len(@PYEXCEPTIONTYPE) then gosub PY.BADNESS
crt "descrinfo(1,py_bool)=":descrinfo(1,py_bool)
* Create True using the __new__() method
test3 = PyCallMethod( py_bool, "__new__", (1))
rslt = PyCallMethod( pmo.BUILTINS, "print", 'test3', test3)
crt "descrinfo(1,test3)=":descrinfo(1,test3)

* Use the GetAttr method to get the True attribute
test4 = PyGetAttr( pmo.BUILTINS, "True")
rslt = PyCallMethod( pmo.BUILTINS, "print", 'test4', test4)
crt "descrinfo(1,test4)=":descrinfo(1,test4)

* Try the PyCall api
test5 = PyCall( py_bool, (-1))
rslt = PyCallMethod( pmo.BUILTINS, "print", 'test5', test5)
crt "descrinfo(1,test5)=":descrinfo(1,test5)

stop


PY.BADNESS:

crt " EXCEPTION TYPE     = " :@PYEXCEPTIONTYPE
crt " EXCEPTION MESSAGE  = " :squote(@PYEXCEPTIONMSG)
crt " EXCEPTIONTRACEBACK = " :@PYEXCEPTIONTRACEBACK

stop

This now produces this output:

>TEST.PY.TRUE
test1 1
descrinfo(1,test1)=1
test2 None
descrinfo(1,test2)=-1
descrinfo(1,py_bool)=-1
test3 None
descrinfo(1,test3)=-1
test4 1
descrinfo(1,test4)=1
test5 1
descrinfo(1,test5)=1
>

The variable type for both test2 and test3 is "-1" leading me to think they are the only PYOBJECT variables returned in the test code.

Their value when printed using the API call is "None" which is a pythonic value, but wrong.

So it seems that the U2 BASIC Python API has issues with the bool class being passed in/out of the API functions.



------------------------------
Gregor Scott
Software Architect
Pentana Solutions Pty Ltd
Mount Waverley VIC AU
------------------------------