Porting to python3

Here's the place for discussion related to coding in FreeCAD, C++ or Python. Design, interfaces and structures.
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
User avatar
looo
Veteran
Posts: 3941
Joined: Mon Nov 11, 2013 5:29 pm

Re: Porting to python3

Post by looo »

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
User avatar
looo
Veteran
Posts: 3941
Joined: Mon Nov 11, 2013 5:29 pm

Re: Porting to python3

Post by looo »

@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.
User avatar
looo
Veteran
Posts: 3941
Joined: Mon Nov 11, 2013 5:29 pm

Re: Porting to python3

Post by looo »

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
Veteran
Posts: 2511
Joined: Thu Mar 03, 2016 9:52 pm
Location: Illinois

Re: Porting to python3

Post by kkremitzki »

I just compiled master and that worked for me...
Like my FreeCAD work? I'd appreciate any level of support via Patreon, Liberapay, or PayPal! Read more about what I do at my blog.
User avatar
looo
Veteran
Posts: 3941
Joined: Mon Nov 11, 2013 5:29 pm

Re: Porting to python3

Post by looo »

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

Re: Porting to python3

Post by looo »

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
Founder
Posts: 20243
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: Porting to python3

Post by wmayer »

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.
User avatar
looo
Veteran
Posts: 3941
Joined: Mon Nov 11, 2013 5:29 pm

Re: Porting to python3

Post by looo »

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'>)

User avatar
looo
Veteran
Posts: 3941
Joined: Mon Nov 11, 2013 5:29 pm

Re: Porting to python3

Post by looo »

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);
User avatar
looo
Veteran
Posts: 3941
Joined: Mon Nov 11, 2013 5:29 pm

Re: Porting to python3

Post by looo »

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

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