Porting to python3

Here's the place for discussion related to coding in FreeCAD, C++ or Python. Design, interfaces and structures.
looo
Posts: 706
Joined: Mon Nov 11, 2013 5:29 pm

Re: Porting to python3

Postby looo » Thu Jan 26, 2017 5:11 pm

thanks for the testing. There are still many problems with the branch. But most of them shouldn't be that difficult. The only show-stopper at the moment is the problem with extensions. Hopefully this will be solved soon.
My plan is to slowly move all the commits into master. First all the modules and then the difficult things. it's a long way: https://github.com/looooo/FreeCAD/issues/8 :D
looo
Posts: 706
Joined: Mon Nov 11, 2013 5:29 pm

Re: Porting to python3

Postby looo » Thu Jan 26, 2017 6:15 pm

@wmayer should this function call the getCustomAttributes of ExtensionContainer.cpp?

Code: Select all

PyObject *ExtensionContainerPy::_getattro(PyObject *attro)            // __getattr__ function: note only need to handle new state
{
    char *attr;
#if PY_MAJOR_VERSION >= 3
    attr = PyUnicode_AsUTF8(attro);
#else
    attr = PyString_AsString(attro);
#endif
    try {
        // getter method for special Attributes (e.g. dynamic ones)
        printf("before getCustomAttributes");
        PyObject *r = getCustomAttributes(attr);

        printf("after getCustomAttributes");
        if(r) return r;


in the header file (ExtensionContainerPy.h) there is a definition of this function, but not in the cpp file (ExtensionContainerPy.cpp).
So what function is called.

ps.: Looking at the ExtensionContainerPyImp.cpp the getCustomAttributes function is implemented. So this means that the generators are failing here. :( So again a problem with generators.

ps.: the function is taken from the ExtensionContainerPyImp.cpp... But it is never called. This is strange.
looo
Posts: 706
Joined: Mon Nov 11, 2013 5:29 pm

Re: Porting to python3

Postby looo » Thu Jan 26, 2017 11:08 pm

this is too difficult.

Can anybody confirm this with master-branch:

Code: Select all

import sys
sys.path.append("/usr/lib/freecad/lib")
import FreeCAD as App
Doc = App.newDocument()
BodySource = Doc.addObject('PartDesign::Body','Body')
Sketch = Doc.addObject('Sketcher::SketchObject','Sketch')
BodySource.addObject(Sketch)

-->
AttributeError: 'Part.Feature' object has no attribute 'addObject'


It seems I am testing stuff not really working in master-branch
User avatar
kkremitzki
Posts: 326
Joined: Thu Mar 03, 2016 9:52 pm
Location: Texas

Re: Porting to python3

Postby kkremitzki » Fri Jan 27, 2017 2:19 am

I just compiled master and that worked for me...
looo
Posts: 706
Joined: Mon Nov 11, 2013 5:29 pm

Re: Porting to python3

Postby looo » Fri Jan 27, 2017 8:17 am

Also as a python script? It does work for me in the freecad gui. But not when running it as a exzternal script.
looo
Posts: 706
Joined: Mon Nov 11, 2013 5:29 pm

Re: Porting to python3

Postby looo » Fri Jan 27, 2017 10:28 am

found the problem:

1: PyObjectBase.cpp L135 __getattro is connected to tp_getattro
2: PyObjectBase.cpp L152 _getattro is called
3: (template) BodyPy.cpp here starts the implementation of _getattro
4: (template) BodyPy.cpp this line was changed for the python3 branch (PyFindMethod->PyObject_GenericGetAttr) and GenericGetAttr finds something so the father in line 785 is never called. Thats why the inheritance tree is not moved upwards and the _getattro of ExtensionContainerPy.cpp is never called.

So there is a difference between PyFindMethod and PyObject_GenericGetAttro.
wmayer
Site Admin
Posts: 11234
Joined: Thu Feb 19, 2009 10:32 am

Re: Porting to python3

Postby wmayer » Fri Jan 27, 2017 11:57 am

So there is a difference between PyFindMethod and PyObject_GenericGetAttro.

Yes, there is definitely a different behaviour. When using Py_FindMethod you pass an array of methods and the name and it returns a valid pointer if a method of this name is in the array.

However, PyObject_GenericGetAttro doesn't just look for method names but arbitrary attributes. But I wonder why does it find "addObject" and the system still raises an error that this attribute doesn't exist. Hmm, I think it's time to update my Python3 test environment.
looo
Posts: 706
Joined: Mon Nov 11, 2013 5:29 pm

Re: Porting to python3

Postby looo » Fri Jan 27, 2017 12:53 pm

https://docs.python.org/3.5/c-api/object.html
PyObject_GenericGetAttr...It looks for a descriptor in the dictionary of classes in the object’s MRO


maybe this allready looks in the father class for an object called addObject. when you look at the attributes in mro you will also find a parent class.

Code: Select all

Doc = App.newDocument()
BodySource = Doc.addObject('PartDesign::Body','Body')
type(BodySource).__mro__

>>> (<type 'PartDesign.Body'>, <type 'Part.BodyBase'>, <type 'Part.Feature'>, <type 'App.DocumentObject'>, <type 'App.ExtensionContainer'>, <type 'App.PropertyContainer'>, <type 'Base.Persistence'>, <type 'Base.BaseClass'>, <type 'PyObjectBase'>, <type 'object'>)

looo
Posts: 706
Joined: Mon Nov 11, 2013 5:29 pm

Re: Porting to python3

Postby looo » Fri Jan 27, 2017 11:29 pm

A solution could be to make the new implementation work the same as the PyFind method which only looked for function defined within the class. Only an idea:

Code: Select all

PyObject *rvalue = PyObject_GenericGetAttr(this, attro);

    if (rvalue != NULL)
    {
        for (PyMethodDef method: this->Methods)
        {
            if (method.ml_meth == reinterpret_cast<PyCFunctionObject*>(rvalue))
            {
                return rvalue;
            }
        }
    }

    PyErr_Clear();
    return @self.export.Father@::_getattro(attro);
looo
Posts: 706
Joined: Mon Nov 11, 2013 5:29 pm

Re: Porting to python3

Postby looo » Sat Jan 28, 2017 10:04 am

finally a working code. With this the part-design-gui tests are passing.

https://github.com/looooo/FreeCAD/commi ... 8bdcf7d4bc