View Issue Details

IDProjectCategoryView StatusLast Update
0015030ScribusScripterpublic2019-12-08 21:24
Reporteru ltd. Assigned Tojghali  
PrioritynormalSeverityfeatureReproducibilityalways
Status closedResolutionfixed 
Platformamd64OSalike debianOS Version9
Product Version1.5.3 
Fixed in Version1.5.6.svn 
Summary0015030: Port scripter to Python 3
DescriptionI thought of that it would be nice to port my scripts to Python 3 but Scribus doesn't support Python 3 so I wanted to see whether it can get supported. The patch contains following changes:
- cmdvar.h: simple-to-rewrite method names
- cmd*.cpp: simple-to-rewrite method names
- objimageexport.cpp, objpdffile.cpp, objprinter.cpp: struct change and initalization update, simple-to-rewrite method names
- scriptplugin.cpp: more-or-less complex changes: initalization order; initialize a so-called Python "module"
- scriptercore.cpp: the string problems get a bit visible here. + Updating the inline Python code to Python 3.
Additional InformationAdditional Information as was present on the mailing list thread "[scribus] Scribus 1.5.3 on Debian with Python 3" (e. g. Wed, 25 Oct 2017 08:54:06 +0200)

How to use: Enter some python code in the console and it get's executed. (This is the proof-of-concept for Python 3 running with Scribus). The function is illustrated on http://jbechtel.de/dist/scribus-py3 (or see the bugtracker attachments.)

* It doesn't work with the pdf export functions. I did not test / do not remember at which invokation stage the pdf export stucks
* There may be many errors in the string exchange between Python / User / Scribus Text Frames (because you have to differentiate between strings with code points and strings computed byte-by-byte -> the different parts of the program may count the chars differently, which makes text editing harder.)
* I did not test any window or so which is opened by the script as user interface.
* It doesn't work to load an external script invoked from GUI/Menu bar. (Displays an error but no error text)
* But you can load an external script from Scripter Console:
# https://stackoverflow.com/questions/1027714/ -> https://stackoverflow.com/a/31566843
vars = globals();
exec(open("test2.script").read(), vars)
print (vars)
# This doesn't forward the output of test2.script, but the script's execution leads to the desired effect on the document.

TagsNo tags attached.
PatchYes

Activities

u ltd.

2017-10-25 22:29

reporter  

python3.patch (79,191 bytes)   
diff -r -U 5 old/scribus-1.5.3/scribus/plugins/scriptplugin/cmdcell.cpp bug-submission/scribus/plugins/scriptplugin/cmdcell.cpp
--- old/scribus-1.5.3/scribus/plugins/scriptplugin/cmdcell.cpp	2017-05-28 11:10:24.000000000 +0200
+++ bug-submission/scribus/plugins/scriptplugin/cmdcell.cpp	2017-09-01 16:11:24.000000000 +0200
@@ -59,11 +59,11 @@
 	if (column < 0 || column >= table->columns() || row < 0 || row >= table->rows())
 	{
 		PyErr_SetString(PyExc_ValueError, QObject::tr("The cell %1,%2 does not exist in table", "python error").arg(row).arg(column).toLocal8Bit().constData());
 		return NULL;
 	}
-	return PyString_FromString(table->cellAt(row, column).styleName().toUtf8());
+	return Legacy_PyString_FromString(table->cellAt(row, column).styleName().toUtf8());
 }
 
 PyObject *scribus_setcellstyle(PyObject* /* self */, PyObject* args)
 {
 	char *Name = const_cast<char*>("");
@@ -151,11 +151,11 @@
 	if (column < 0 || column >= table->columns() || row < 0 || row >= table->rows())
 	{
 		PyErr_SetString(PyExc_ValueError, QObject::tr("The cell %1,%2 does not exist in table", "python error").arg(row).arg(column).toLocal8Bit().constData());
 		return NULL;
 	}
-	return PyString_FromString(table->cellAt(row, column).fillColor().toUtf8());
+	return Legacy_PyString_FromString(table->cellAt(row, column).fillColor().toUtf8());
 }
 
 PyObject *scribus_setcellfillcolor(PyObject* /* self */, PyObject* args)
 {
 	char *Name = const_cast<char*>("");
diff -r -U 5 old/scribus-1.5.3/scribus/plugins/scriptplugin/cmdcolor.cpp bug-submission/scribus/plugins/scriptplugin/cmdcolor.cpp
--- old/scribus-1.5.3/scribus/plugins/scriptplugin/cmdcolor.cpp	2017-05-28 11:10:24.000000000 +0200
+++ bug-submission/scribus/plugins/scriptplugin/cmdcolor.cpp	2017-09-01 16:15:55.000000000 +0200
@@ -20,11 +20,11 @@
 	edc = ScCore->primaryMainWindow()->HaveDoc ? ScCore->primaryMainWindow()->doc->PageColors : PrefsManager::instance()->colorSet();
 	ColorList::Iterator it;
 	l = PyList_New(edc.count());
 	for (it = edc.begin(); it != edc.end(); ++it)
 	{
-		PyList_SetItem(l, cc, PyString_FromString(it.key().toUtf8()));
+		PyList_SetItem(l, cc, Legacy_PyString_FromString(it.key().toUtf8()));
 		cc++;
 	}
 	return l;
 }
 
diff -r -U 5 old/scribus-1.5.3/scribus/plugins/scriptplugin/cmddialog.cpp bug-submission/scribus/plugins/scriptplugin/cmddialog.cpp
--- old/scribus-1.5.3/scribus/plugins/scriptplugin/cmddialog.cpp	2017-05-28 11:10:24.000000000 +0200
+++ bug-submission/scribus/plugins/scriptplugin/cmddialog.cpp	2017-09-01 16:13:00.000000000 +0200
@@ -66,11 +66,11 @@
 										 &nobool,
 										 &nobool
 										);
 //	QApplication::restoreOverrideCursor();
 	// FIXME: filename return unicode OK?
-	return PyString_FromString(fName.toUtf8());
+	return Legacy_PyString_FromString(fName.toUtf8());
 }
 
 PyObject *scribus_messdia(PyObject* /* self */, PyObject* args, PyObject* kw)
 {
 	char *caption = const_cast<char*>("");
@@ -118,11 +118,11 @@
 										QString::fromUtf8(caption),
 										QString::fromUtf8(message),
 										QLineEdit::Normal,
 										QString::fromUtf8(value));
 //	QApplication::restoreOverrideCursor();
-	return PyString_FromString(txt.toUtf8());
+	return Legacy_PyString_FromString(txt.toUtf8());
 }
 
 PyObject *scribus_newstyledialog(PyObject*, PyObject* args)
 {
 	if(!checkHaveDocument())
@@ -141,11 +141,11 @@
 		ParagraphStyle p;
 		p.setName(s);
 		st.create(p);
 		d->redefineStyles(st, false);
 		ScCore->primaryMainWindow()->styleMgr()->setDoc(d);
-		return PyString_FromString(s.toUtf8());
+		return Legacy_PyString_FromString(s.toUtf8());
 	}
 	else
 		Py_RETURN_NONE;
 }
 
diff -r -U 5 old/scribus-1.5.3/scribus/plugins/scriptplugin/cmddoc.cpp bug-submission/scribus/plugins/scriptplugin/cmddoc.cpp
--- old/scribus-1.5.3/scribus/plugins/scriptplugin/cmddoc.cpp	2017-05-28 11:10:24.000000000 +0200
+++ bug-submission/scribus/plugins/scriptplugin/cmddoc.cpp	2017-09-01 16:11:00.000000000 +0200
@@ -195,13 +195,13 @@
 {
 	if(!checkHaveDocument())
 		return NULL;
 	if (! ScCore->primaryMainWindow()->doc->hasName)
 	{
-		return PyString_FromString("");
+		return Legacy_PyString_FromString("");
 	}
-	return PyString_FromString(ScCore->primaryMainWindow()->doc->DocName.toUtf8());
+	return Legacy_PyString_FromString(ScCore->primaryMainWindow()->doc->DocName.toUtf8());
 }
 
 PyObject *scribus_savedocas(PyObject* /* self */, PyObject* args)
 {
 	char *Name;
@@ -316,11 +316,11 @@
 	QMap<QString,int>::const_iterator it(ScCore->primaryMainWindow()->doc->MasterNames.constBegin());
 	QMap<QString,int>::const_iterator itEnd(ScCore->primaryMainWindow()->doc->MasterNames.constEnd());
 	int n = 0;
 	for ( ; it != itEnd; ++it )
 	{
-		PyList_SET_ITEM(names, n++, PyString_FromString(it.key().toUtf8().data()) );
+		PyList_SET_ITEM(names, n++, Legacy_PyString_FromString(it.key().toUtf8().data()) );
 	}
 	return names;
 }
 
 PyObject *scribus_editmasterpage(PyObject* /* self */, PyObject* args)
@@ -401,11 +401,11 @@
 	if ((e < 0) || (e > static_cast<int>(ScCore->primaryMainWindow()->doc->Pages->count())-1))
 	{
 		PyErr_SetString(PyExc_IndexError, QObject::tr("Page number out of range: '%1'.","python error").arg(e+1).toLocal8Bit().constData());
 		return NULL;
 	}
-	return PyString_FromString(ScCore->primaryMainWindow()->doc->DocPages.at(e)->MPageNam.toUtf8());
+	return Legacy_PyString_FromString(ScCore->primaryMainWindow()->doc->DocPages.at(e)->MPageNam.toUtf8());
 }
 
 PyObject* scribus_applymasterpage(PyObject* /* self */, PyObject* args)
 {
 	char* name = 0;
diff -r -U 5 old/scribus-1.5.3/scribus/plugins/scriptplugin/cmdgetprop.cpp bug-submission/scribus/plugins/scriptplugin/cmdgetprop.cpp
--- old/scribus-1.5.3/scribus/plugins/scriptplugin/cmdgetprop.cpp	2017-05-28 11:10:24.000000000 +0200
+++ bug-submission/scribus/plugins/scriptplugin/cmdgetprop.cpp	2017-09-01 16:16:37.000000000 +0200
@@ -42,22 +42,22 @@
 		result = "LatexFrame";
 	} else if (item->itemType() == PageItem::Multiple) {
 		result = "Multiple";
 	}
 
-	return PyString_FromString(result.toUtf8());
+	return Legacy_PyString_FromString(result.toUtf8());
 }
 
 PyObject *scribus_getfillcolor(PyObject* /* self */, PyObject* args)
 {
 	char *Name = const_cast<char*>("");
 	if (!PyArg_ParseTuple(args, "|es", "utf-8", &Name))
 		return NULL;
 	if(!checkHaveDocument())
 		return NULL;
 	PageItem *i = GetUniqueItem(QString::fromUtf8(Name));
-	return i != NULL ? PyString_FromString(i->fillColor().toUtf8()) : NULL;
+	return i != NULL ? Legacy_PyString_FromString(i->fillColor().toUtf8()) : NULL;
 }
 
 PyObject *scribus_getfilltrans(PyObject* /* self */, PyObject* args)
 {
 	char *Name = const_cast<char*>("");
@@ -94,15 +94,15 @@
 	if ((it->HasSel) && ((it->itemType() == PageItem::TextFrame) || (it->itemType() == PageItem::PathText)))
 	{
 		for (int b = 0; b < it->itemText.length(); ++b)
 		{
 			if (it->itemText.selected(b))
-				return PyString_FromString(it->itemText.charStyle(b).fillColor().toUtf8());
+				return Legacy_PyString_FromString(it->itemText.charStyle(b).fillColor().toUtf8());
 		}
 	}
 	else
-		return PyString_FromString(it->lineColor().toUtf8());
+		return Legacy_PyString_FromString(it->lineColor().toUtf8());
 	PyErr_SetString(NotFoundError, QObject::tr("Color not found - python error", "python error").toLocal8Bit().constData());
 	return NULL;
 }
 
 PyObject *scribus_getlinetrans(PyObject* /* self */, PyObject* args)
@@ -234,11 +234,11 @@
 	if (!PyArg_ParseTuple(args, "|es", "utf-8", &Name))
 		return NULL;
 	if(!checkHaveDocument())
 		return NULL;
 	PageItem *i = GetUniqueItem(QString::fromUtf8(Name));
-	return i != NULL ? PyString_FromString(i->Pfile.toUtf8()) : NULL;
+	return i != NULL ? Legacy_PyString_FromString(i->Pfile.toUtf8()) : NULL;
 }
 
 PyObject *scribus_getposi(PyObject* /* self */, PyObject* args)
 {
 	char *Name = const_cast<char*>("");
@@ -311,17 +311,17 @@
 		{
 			if (typ != -1)
 			{
 				if (ScCore->primaryMainWindow()->doc->Items->at(lam)->itemType() == typ)
 				{
-					PyList_SetItem(l, counter2, PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(lam)->itemName().toUtf8()));
+					PyList_SetItem(l, counter2, Legacy_PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(lam)->itemName().toUtf8()));
 					counter2++;
 				}
 			}
 			else
 			{
-				PyList_SetItem(l, counter2, PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(lam)->itemName().toUtf8()));
+				PyList_SetItem(l, counter2, Legacy_PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(lam)->itemName().toUtf8()));
 				counter2++;
 			}
 		}
 	}
 	return l;
diff -r -U 5 old/scribus-1.5.3/scribus/plugins/scriptplugin/cmdgetsetprop.cpp bug-submission/scribus/plugins/scriptplugin/cmdgetsetprop.cpp
--- old/scribus-1.5.3/scribus/plugins/scriptplugin/cmdgetsetprop.cpp	2017-05-28 11:10:24.000000000 +0200
+++ bug-submission/scribus/plugins/scriptplugin/cmdgetsetprop.cpp	2017-09-01 16:12:26.000000000 +0200
@@ -86,21 +86,21 @@
 	if (type == NULL)
 	{
 		PyErr_SetString(PyExc_KeyError, QObject::tr("Property not found").toLocal8Bit().constData());
 		return NULL;
 	}
-	return PyString_FromString(type);
+	return Legacy_PyString_FromString(type);
 }
 
 PyObject* convert_QStringList_to_PyListObject(QStringList& origlist)
 {
 	PyObject* resultList = PyList_New(0);
 	if (!resultList)
 		return NULL;
 
 	for ( QStringList::Iterator it = origlist.begin(); it != origlist.end(); ++it )
-		if (PyList_Append(resultList, PyString_FromString((*it).toUtf8().data())) == -1)
+		if (PyList_Append(resultList, Legacy_PyString_FromString((*it).toUtf8().data())) == -1)
 			return NULL;
 
 	return resultList;
 }
 
@@ -287,13 +287,13 @@
 	// BOOLEAN
 	else if (prop.type() == QVariant::Bool)
 		resultobj = PyBool_FromLong(prop.toBool());
 	// STRING TYPES
 	else if (prop.type() == QVariant::ByteArray)
-		resultobj = PyString_FromString(prop.toByteArray().data());
+		resultobj = Legacy_PyString_FromString(prop.toByteArray().data());
 	else if (prop.type() == QVariant::String)
-		resultobj = PyString_FromString(prop.toString().toUtf8().data());
+		resultobj = Legacy_PyString_FromString(prop.toString().toUtf8().data());
 	// HIGHER ORDER TYPES
 	else if (prop.type() == QVariant::Point)
 	{
 		// Return a QPoint as an (x,y) tuple.
 		QPoint pt = prop.toPoint();
diff -r -U 5 old/scribus-1.5.3/scribus/plugins/scriptplugin/cmdmani.cpp bug-submission/scribus/plugins/scriptplugin/cmdmani.cpp
--- old/scribus-1.5.3/scribus/plugins/scriptplugin/cmdmani.cpp	2017-05-28 11:10:24.000000000 +0200
+++ bug-submission/scribus/plugins/scriptplugin/cmdmani.cpp	2017-09-01 16:14:21.000000000 +0200
@@ -404,11 +404,11 @@
 
 	const PageItem* group = ScCore->primaryMainWindow()->doc->itemSelection_GroupObjects(false, false, finalSelection);
 	finalSelection=0;
 	delete tempSelection;
 	
-	return (group ? PyString_FromString(group->itemName().toUtf8()) : NULL);
+	return (group ? Legacy_PyString_FromString(group->itemName().toUtf8()) : NULL);
 }
 
 PyObject *scribus_ungroupobj(PyObject* /* self */, PyObject* args)
 {
 	char *Name = const_cast<char*>("");
@@ -462,14 +462,14 @@
 	if (!PyArg_ParseTuple(args, "|i", &i))
 		return NULL;
 	if(!checkHaveDocument())
 		return NULL;
 	if ((i < static_cast<int>(ScCore->primaryMainWindow()->doc->m_Selection->count())) && (i > -1))
-		return PyString_FromString(ScCore->primaryMainWindow()->doc->m_Selection->itemAt(i)->itemName().toUtf8());
+		return Legacy_PyString_FromString(ScCore->primaryMainWindow()->doc->m_Selection->itemAt(i)->itemName().toUtf8());
 	else
 		// FIXME: Should probably return None if no selection?
-		return PyString_FromString("");
+		return Legacy_PyString_FromString("");
 }
 
 PyObject *scribus_selcount(PyObject* /* self */)
 {
 	if(!checkHaveDocument())
diff -r -U 5 old/scribus-1.5.3/scribus/plugins/scriptplugin/cmdmisc.cpp bug-submission/scribus/plugins/scriptplugin/cmdmisc.cpp
--- old/scribus-1.5.3/scribus/plugins/scriptplugin/cmdmisc.cpp	2017-05-28 11:10:24.000000000 +0200
+++ bug-submission/scribus/plugins/scriptplugin/cmdmisc.cpp	2017-09-01 16:16:17.000000000 +0200
@@ -47,11 +47,11 @@
 	int cc = 0;
 	for ( ; it.hasNext() ; it.next())
 	{
 		if (it.current().usable())
 		{
-			PyList_SetItem(l, cc, PyString_FromString(it.currentKey().toUtf8()));
+			PyList_SetItem(l, cc, Legacy_PyString_FromString(it.currentKey().toUtf8()));
 			cc++;
 		}
 	}
 	return l;
 }
@@ -126,11 +126,11 @@
 			return NULL;
 		}
 		int bufferSize = buffer.size();
 		buffer.close();
 		// Now make a Python string from the data we generated
-		PyObject* stringPython = PyString_FromStringAndSize(buffer_string,bufferSize);
+		PyObject* stringPython = Legacy_PyString_FromStringAndSize(buffer_string,bufferSize);
 		// Return even if the result is NULL (error) since an exception will have been
 		// set in that case.
 		return stringPython;
 	}
 	else
@@ -155,11 +155,11 @@
 	if(!checkHaveDocument())
 		return NULL;
 	PyObject *l;
 	l = PyList_New(ScCore->primaryMainWindow()->doc->Layers.count());
 	for (int lam=0; lam < ScCore->primaryMainWindow()->doc->Layers.count(); lam++)
-		PyList_SetItem(l, lam, PyString_FromString(ScCore->primaryMainWindow()->doc->Layers[lam].Name.toUtf8()));
+		PyList_SetItem(l, lam, Legacy_PyString_FromString(ScCore->primaryMainWindow()->doc->Layers[lam].Name.toUtf8()));
 	return l;
 }
 
 PyObject *scribus_setactlayer(PyObject* /* self */, PyObject* args)
 {
@@ -188,11 +188,11 @@
 
 PyObject *scribus_getactlayer(PyObject* /* self */)
 {
 	if(!checkHaveDocument())
 		return NULL;
-	return PyString_FromString(ScCore->primaryMainWindow()->doc->activeLayerName().toUtf8());
+	return Legacy_PyString_FromString(ScCore->primaryMainWindow()->doc->activeLayerName().toUtf8());
 }
 
 PyObject *scribus_senttolayer(PyObject* /* self */, PyObject* args)
 {
 	char *Name = const_cast<char*>("");
@@ -759,11 +759,11 @@
 	Py_RETURN_NONE;
 }
 
 PyObject *scribus_getlanguage(PyObject* /* self */)
 {
-	return PyString_FromString(ScCore->getGuiLanguage().toUtf8());
+	return Legacy_PyString_FromString(ScCore->getGuiLanguage().toUtf8());
 }
 
 /*! 04.01.2007 : Joachim Neu : Moves item selection to front. */
 PyObject *scribus_moveselectiontofront(PyObject*)
 {
diff -r -U 5 old/scribus-1.5.3/scribus/plugins/scriptplugin/cmdobj.cpp bug-submission/scribus/plugins/scriptplugin/cmdobj.cpp
--- old/scribus-1.5.3/scribus/plugins/scriptplugin/cmdobj.cpp	2017-05-28 11:10:24.000000000 +0200
+++ bug-submission/scribus/plugins/scriptplugin/cmdobj.cpp	2017-09-01 16:13:57.000000000 +0200
@@ -41,11 +41,11 @@
 	{
 		QString objName = QString::fromUtf8(Name);
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(i)->setItemName(objName);
 	}
-	return PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
+	return Legacy_PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
 }
 
 
 PyObject *scribus_newellipse(PyObject* /* self */, PyObject* args)
 {
@@ -67,11 +67,11 @@
 	{
 		QString objName = QString::fromUtf8(Name);
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(i)->setItemName(objName);
 	}
-	return PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
+	return Legacy_PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
 }
 
 
 PyObject *scribus_newimage(PyObject* /* self */, PyObject* args)
 {
@@ -92,11 +92,11 @@
 	{
 		QString objName = QString::fromUtf8(Name);
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(i)->setItemName(objName);
 	}
-	return PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
+	return Legacy_PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
 }
 
 
 PyObject *scribus_newtext(PyObject* /* self */, PyObject* args)
 {
@@ -117,11 +117,11 @@
 	{
 		QString objName = QString::fromUtf8(Name);
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(i)->setItemName(objName);
 	}
-	return PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
+	return Legacy_PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
 }
 
 PyObject *scribus_newtable(PyObject* /* self */, PyObject* args)
 {
 	double x, y, w, h;
@@ -153,11 +153,11 @@
 	{
 		QString objName = QString::fromUtf8(Name);
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(i)->setItemName(objName);
 	}
-	return PyString_FromString(table->itemName().toUtf8());
+	return Legacy_PyString_FromString(table->itemName().toUtf8());
 }
 
 PyObject *scribus_newline(PyObject* /* self */, PyObject* args)
 {
 	double x, y, w, h;
@@ -213,11 +213,11 @@
 	{
 		QString objName = QString::fromUtf8(Name);
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(i)->setItemName(objName);
 	}
-	return PyString_FromString(it->itemName().toUtf8());
+	return Legacy_PyString_FromString(it->itemName().toUtf8());
 }
 
 
 PyObject *scribus_polyline(PyObject* /* self */, PyObject* args)
 {
@@ -290,11 +290,11 @@
 	{
 		QString objName = QString::fromUtf8(Name);
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(ic)->setItemName(objName);
 	}
-	return PyString_FromString(it->itemName().toUtf8());
+	return Legacy_PyString_FromString(it->itemName().toUtf8());
 }
 
 
 PyObject *scribus_polygon(PyObject* /* self */, PyObject* args)
 {
@@ -372,11 +372,11 @@
 	{
 		QString objName = QString::fromUtf8(Name);
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(ic)->setItemName(objName);
 	}
-	return PyString_FromString(it->itemName().toUtf8());
+	return Legacy_PyString_FromString(it->itemName().toUtf8());
 }
 
 PyObject *scribus_bezierline(PyObject* /* self */, PyObject* args)
 {
 	char *Name = const_cast<char*>("");
@@ -463,11 +463,11 @@
 	{
 		QString objName = QString::fromUtf8(Name);
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(ic)->setItemName(objName);
 	}
-	return PyString_FromString(it->itemName().toUtf8());
+	return Legacy_PyString_FromString(it->itemName().toUtf8());
 }
 
 
 /* 03/31/2004 - xception handling
  */
@@ -504,11 +504,11 @@
 	{
 		QString objName = QString::fromUtf8(Name);
 		if (!ItemExists(objName))
 			i->setItemName(objName);
 	}
-	return PyString_FromString(i->itemName().toUtf8());
+	return Legacy_PyString_FromString(i->itemName().toUtf8());
 }
 
 
 /* 03/21/2004 - exception raised when Name doesn't exists. Doesn't crash then. (subik)
  */
@@ -660,11 +660,11 @@
 	if(!checkHaveDocument())
 		return NULL;
 	styleList = PyList_New(0);
 	for (int i=0; i < ScCore->primaryMainWindow()->doc->paragraphStyles().count(); ++i)
 	{
-		if (PyList_Append(styleList, PyString_FromString(ScCore->primaryMainWindow()->doc->paragraphStyles()[i].name().toUtf8())))
+		if (PyList_Append(styleList, Legacy_PyString_FromString(ScCore->primaryMainWindow()->doc->paragraphStyles()[i].name().toUtf8())))
 		{
 			// An exception will have already been set by PyList_Append apparently.
 			return NULL;
 		}
 	}
@@ -677,11 +677,11 @@
 	if(!checkHaveDocument())
 		return NULL;
 	charStyleList = PyList_New(0);
 	for (int i=0; i < ScCore->primaryMainWindow()->doc->charStyles().count(); ++i)
 	{
-		if (PyList_Append(charStyleList, PyString_FromString(ScCore->primaryMainWindow()->doc->charStyles()[i].name().toUtf8())))
+		if (PyList_Append(charStyleList, Legacy_PyString_FromString(ScCore->primaryMainWindow()->doc->charStyles()[i].name().toUtf8())))
 		{
 			// An exception will have already been set by PyList_Append apparently.
 			return NULL;
 		}
 	}
diff -r -U 5 old/scribus-1.5.3/scribus/plugins/scriptplugin/cmdtable.cpp bug-submission/scribus/plugins/scriptplugin/cmdtable.cpp
--- old/scribus-1.5.3/scribus/plugins/scriptplugin/cmdtable.cpp	2017-05-28 11:10:24.000000000 +0200
+++ bug-submission/scribus/plugins/scriptplugin/cmdtable.cpp	2017-09-01 16:15:25.000000000 +0200
@@ -336,11 +336,11 @@
 	if (!table)
 	{
 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get table style on a non-table item.","python error").toLocal8Bit().constData());
 		return NULL;
 	}
-	return PyString_FromString(table->styleName().toUtf8());
+	return Legacy_PyString_FromString(table->styleName().toUtf8());
 }
 
 PyObject *scribus_settablestyle(PyObject* /* self */, PyObject* args)
 {
 	char *Name = const_cast<char*>("");
@@ -376,11 +376,11 @@
 	if (!table)
 	{
 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get table fill color on a non-table item.","python error").toLocal8Bit().constData());
 		return NULL;
 	}
-	return PyString_FromString(table->fillColor().toUtf8());
+	return Legacy_PyString_FromString(table->fillColor().toUtf8());
 }
 
 PyObject *scribus_settablefillcolor(PyObject* /* self */, PyObject* args)
 {
 	char *Name = const_cast<char*>("");
diff -r -U 5 old/scribus-1.5.3/scribus/plugins/scriptplugin/cmdtext.cpp bug-submission/scribus/plugins/scriptplugin/cmdtext.cpp
--- old/scribus-1.5.3/scribus/plugins/scriptplugin/cmdtext.cpp	2017-05-28 11:10:24.000000000 +0200
+++ bug-submission/scribus/plugins/scriptplugin/cmdtext.cpp	2017-09-01 16:14:43.000000000 +0200
@@ -89,15 +89,15 @@
 	}
 	if (it->HasSel)
 	{
 		for (int b = 0; b < it->itemText.length(); b++)
 			if (it->itemText.selected(b))
-				return PyString_FromString(it->itemText.charStyle(b).font().scName().toUtf8());
+				return Legacy_PyString_FromString(it->itemText.charStyle(b).font().scName().toUtf8());
 		return NULL;
 	}
 	else
-		return PyString_FromString(it->currentCharStyle().font().scName().toUtf8());
+		return Legacy_PyString_FromString(it->currentCharStyle().font().scName().toUtf8());
 }
 
 PyObject *scribus_gettextsize(PyObject* /* self */, PyObject* args)
 {
 	char *Name = const_cast<char*>("");
@@ -169,15 +169,15 @@
 	}
 	if (it->HasSel)
 	{
 		for (int b = 0; b < it->itemText.length(); b++)
 			if (it->itemText.selected(b))
-				return PyString_FromString(it->itemText.charStyle(b).fontFeatures().toUtf8());
+				return Legacy_PyString_FromString(it->itemText.charStyle(b).fontFeatures().toUtf8());
 		return NULL;
 	}
 	else
-		return PyString_FromString(it->currentCharStyle().fontFeatures().toUtf8());
+		return Legacy_PyString_FromString(it->currentCharStyle().fontFeatures().toUtf8());
 }
 
 PyObject *scribus_getlinespace(PyObject* /* self */, PyObject* args)
 {
 	char *Name = const_cast<char*>("");
@@ -262,11 +262,11 @@
 		else
 		{
 			text += it->itemText.text(a);
 		}
 	}
-	return PyString_FromString(text.toUtf8());
+	return Legacy_PyString_FromString(text.toUtf8());
 }
 
 PyObject *scribus_gettext(PyObject* /* self */, PyObject* args)
 {
 	char *Name = const_cast<char*>("");
@@ -295,11 +295,11 @@
 		else
 		{
 			text += it->itemText.text(a);
 		}
 	} // for
-	return PyString_FromString(text.toUtf8());
+	return Legacy_PyString_FromString(text.toUtf8());
 }
 
 PyObject *scribus_setboxtext(PyObject* /* self */, PyObject* args)
 {
 	char *Name = const_cast<char*>("");
diff -r -U 5 old/scribus-1.5.3/scribus/plugins/scriptplugin/cmdvar.h bug-submission/scribus/plugins/scriptplugin/cmdvar.h
--- old/scribus-1.5.3/scribus/plugins/scriptplugin/cmdvar.h	2017-05-28 11:10:24.000000000 +0200
+++ bug-submission/scribus/plugins/scriptplugin/cmdvar.h	2017-10-25 23:55:59.000000000 +0200
@@ -30,10 +30,34 @@
 
 #ifndef Py_RETURN_TRUE
 	#define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True
 #endif
 
+
+// Python 2 -> Python 3 transition:
+#define Legacy_PyString_FromString PyBytes_FromString
+//#define PyString_FromStringAndSize PyBytes_FromStringAndSize
+#define Legacy_PyString_FromStringAndSize PyBytes_FromStringAndSize
+#define PyString_Check PyBytes_Check
+// rather CheckExact?
+#define PyString_Size PyBytes_Size
+#define PyString_AsString PyBytes_AsString
+#define PyInt_FromLong PyLong_FromLong
+#define PyInt_Check PyLong_Check
+#define PyInt_AsLong PyLong_AsLong
+#define PyCObject_Check PyCapsule_CheckExact
+#define PyCObject_AsVoidPtr(capsule) \
+		(PyCapsule_GetPointer(capsule, NULL))
+#define PyCObject_FromVoidPtr(pointer, destructor) \
+		(PyCapsule_New(pointer, NULL, destructor))
+// Helpful is:
+// https://docs.python.org/3/howto/cporting.html#cobject-replaced-with-capsule
+// as well as:
+// https://docs.python.org/3/c-api/bytes.html 
+// etc.
+
+
 #include <QString>
 
 #include "scribus.h"
 
 
@@ -49,10 +73,11 @@
 /** @brief A pointer to the ScripterCore instance */
 extern ScripterCore* scripterCore;
 
 /** @brief Initialize the 'scribus' Python module in the currently active interpreter */
 extern "C" void initscribus(ScribusMainWindow *pl);
+/*static*/ PyObject* PyInit_scribus(void);
 
 /* Exceptions */
 /*! Common scribus Exception */
 extern PyObject* ScribusException;
 /*! Exception raised when no document opened - see checkHaveDocument() in cmdutil.cpp */
diff -r -U 5 old/scribus-1.5.3/scribus/plugins/scriptplugin/objimageexport.cpp bug-submission/scribus/plugins/scriptplugin/objimageexport.cpp
--- old/scribus-1.5.3/scribus/plugins/scriptplugin/objimageexport.cpp	2017-05-28 11:10:24.000000000 +0200
+++ bug-submission/scribus/plugins/scriptplugin/objimageexport.cpp	2017-10-25 23:54:47.000000000 +0200
@@ -31,23 +31,23 @@
 static void ImageExport_dealloc(ImageExport* self)
 {
 	Py_XDECREF(self->name);
 	Py_XDECREF(self->type);
 	Py_XDECREF(self->allTypes);
-	self->ob_type->tp_free((PyObject *)self);
+	Py_TYPE(self)->tp_free((PyObject *)self);
 }
 
 static PyObject * ImageExport_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
 {
 	if(!checkHaveDocument())
 		return NULL;
 
 	ImageExport *self;
 	self = (ImageExport *)type->tp_alloc(type, 0);
 	if (self != NULL) {
-		self->name = PyString_FromString("ImageExport.png");
-		self->type = PyString_FromString("PNG");
+		self->name = Legacy_PyString_FromString("ImageExport.png");
+		self->type = Legacy_PyString_FromString("PNG");
 		self->allTypes = PyList_New(0);
 		self->dpi = 72;
 		self->scale = 100;
 		self->quality = 100;
 	}
@@ -117,11 +117,11 @@
 	int pos = 0;
 	QList<QByteArray> list = QImageWriter::supportedImageFormats();
 	l = PyList_New(list.count());
 	for (QList<QByteArray>::Iterator it = list.begin(); it != list.end(); ++it)
 	{
-		PyList_SetItem(l, pos, PyString_FromString(QString((*it)).toLatin1().constData()));
+		PyList_SetItem(l, pos, Legacy_PyString_FromString(QString((*it)).toLatin1().constData()));
 		++pos;
 	}
 	return l;
 }
 
@@ -203,11 +203,10 @@
 	{NULL, (PyCFunction)(0), 0, NULL} // sentinel
 };
 
 PyTypeObject ImageExport_Type = {
 	PyObject_HEAD_INIT(NULL)   // PyObject_VAR_HEAD
-	0,
 	const_cast<char*>("scribus.ImageExport"), // char *tp_name; /* For printing, in format "<module>.<name>" */
 	sizeof(ImageExport),   // int tp_basicsize, /* For allocation */
 	0,  // int tp_itemsize; /* For allocation */
 	(destructor) ImageExport_dealloc, //	 destructor tp_dealloc;
 	0, //	 printfunc tp_print;
@@ -249,11 +248,14 @@
 	0, //	 PyObject *tp_mro; /* method resolution order */
 	0, //	 PyObject *tp_cache;
 	0, //	 PyObject *tp_subclasses;
 	0, //	 PyObject *tp_weaklist;
 	0, //	 destructor tp_del;
-
+	// Added in version 2.6:
+	0, //	 unsigned int tp_version_tag;
+	0, //	 destructor tp_finalize;
+	
 #ifdef COUNT_ALLOCS
 	/* these must be last and never explicitly initialized */
 	//	int tp_allocs;
 	//	int tp_frees;
 	//	int tp_maxalloc;
diff -r -U 5 old/scribus-1.5.3/scribus/plugins/scriptplugin/objpdffile.cpp bug-submission/scribus/plugins/scriptplugin/objpdffile.cpp
--- old/scribus-1.5.3/scribus/plugins/scriptplugin/objpdffile.cpp	2017-05-28 11:10:24.000000000 +0200
+++ bug-submission/scribus/plugins/scriptplugin/objpdffile.cpp	2017-10-25 23:53:29.000000000 +0200
@@ -133,11 +133,11 @@
 	Py_XDECREF(self->imagepr);
 	Py_XDECREF(self->printprofc);
 	Py_XDECREF(self->info);
 	Py_XDECREF(self->rotateDeg);
 	Py_XDECREF(self->openAction);
-	self->ob_type->tp_free((PyObject *)self);
+	Py_TYPE(self)->tp_free((PyObject *)self);
 }
 
 static PyObject * PDFfile_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
 {
 // do not create new object if there is no opened document
@@ -148,11 +148,11 @@
 	PDFfile *self;
 
 	self = (PDFfile *)type->tp_alloc(type, 0);
 	if (self) {
 // set file attribute
-		self->file = PyString_FromString("");
+		self->file = Legacy_PyString_FromString("");
 		if (!self->file) {
 			Py_DECREF(self);
 			return NULL;
 		}
 // set font embedding mode attribute
@@ -237,17 +237,17 @@
 		if (!self->lpival){
 			Py_DECREF(self);
 			return NULL;
 		}
 // set owner attribute
-		self->owner = PyString_FromString("");
+		self->owner = Legacy_PyString_FromString("");
 		if (!self->owner){
 			Py_DECREF(self);
 			return NULL;
 		}
 // set user attribute
-		self->user = PyString_FromString("");
+		self->user = Legacy_PyString_FromString("");
 		if (!self->user){
 			Py_DECREF(self);
 			return NULL;
 		}
 // set allowPrinting attribute
@@ -267,26 +267,26 @@
 		self->profiles = 0; // bool
 		self->profilei = 0; // bool
 		self->intents = 0; // int - 0 - ?
 		self->intenti = 0; // int - 0 - ?
 		self->noembicc = 0; // bool
-		self->solidpr = PyString_FromString("");
+		self->solidpr = Legacy_PyString_FromString("");
 		if (!self->solidpr){
 			Py_DECREF(self);
 			return NULL;
 		}
-		self->imagepr = PyString_FromString("");
+		self->imagepr = Legacy_PyString_FromString("");
 		if (!self->imagepr){
 			Py_DECREF(self);
 			return NULL;
 		}
-		self->printprofc = PyString_FromString("");
+		self->printprofc = Legacy_PyString_FromString("");
 		if (!self->printprofc){
 			Py_DECREF(self);
 			return NULL;
 		}
-		self->info = PyString_FromString("");
+		self->info = Legacy_PyString_FromString("");
 		if (!self->info){
 			Py_DECREF(self);
 			return NULL;
 		}
 		self->bleedt = 0; // double -
@@ -311,11 +311,11 @@
 		self->displayLayers = 0;
 		self->displayFullscreen = 0;
 		self->hideToolBar = 0;
 		self->hideMenuBar = 0;
 		self->fitWindow = 0;
-		self->openAction = PyString_FromString("");
+		self->openAction = Legacy_PyString_FromString("");
 		if (!self->openAction){
 			Py_DECREF(self);
 			return NULL;
 		}
 	}
@@ -337,11 +337,11 @@
 	if (tf.isEmpty()) {
 		QFileInfo fi = QFileInfo(currentDoc->DocName);
 		tf = fi.path()+"/"+fi.baseName()+".pdf";
 	}
 	PyObject *file = NULL;
-	file = PyString_FromString(tf.toLatin1());
+	file = Legacy_PyString_FromString(tf.toLatin1());
 	if (file){
 		Py_DECREF(self->file);
 		self->file = file;
 	} else {
 		PyErr_SetString(PyExc_SystemError, "Can not initialize 'file' attribute");
@@ -373,11 +373,11 @@
 	QList<QString> tmpEm = ReallyUsed.keys();
 	for (int i = 0; i < tmpEm.count(); ++i) 
 	{
 		QString fontName = tmpEm.at(i);
 		PyObject *tmp= NULL;
-		tmp = PyString_FromString(fontName.toLatin1());
+		tmp = Legacy_PyString_FromString(fontName.toLatin1());
 		if (tmp) {
 			PyList_Append(self->fonts, tmp);
 // do i need Py_DECREF(tmp) here?
 // Does PyList_Append increase reference or 'steal' one from provided argument
 // If it 'steal' reference comment next line
@@ -399,11 +399,11 @@
 	}
 // copied from TabPDFOptions::restoreDefaults()
 	for (int fe = 0; fe < pdfOptions.SubsetList.count(); ++fe)
 	{
 		PyObject *tmp= NULL;
-		tmp = PyString_FromString(pdfOptions.SubsetList[fe].toLatin1().data());
+		tmp = Legacy_PyString_FromString(pdfOptions.SubsetList[fe].toLatin1().data());
 		if (tmp) {
 			PyList_Append(self->subsetList, tmp);
 			Py_DECREF(tmp);
 		}
 		else {
@@ -547,21 +547,21 @@
 	PyList_Reverse(lpival);
 	Py_DECREF(self->lpival);
 	self->lpival = lpival;
 // set owner's password
 	PyObject *owner = NULL;
-	owner = PyString_FromString(pdfOptions.PassOwner.toLatin1());
+	owner = Legacy_PyString_FromString(pdfOptions.PassOwner.toLatin1());
 	if (owner){
 		Py_DECREF(self->owner);
 		self->owner = owner;
 	} else {
 		PyErr_SetString(PyExc_SystemError, "Can not initialize 'owner' attribute");
 		return -1;
 	}
 // set user'a password
 	PyObject *user = NULL;
-	user = PyString_FromString(pdfOptions.PassUser.toLatin1());
+	user = Legacy_PyString_FromString(pdfOptions.PassUser.toLatin1());
 	if (user){
 		Py_DECREF(self->user);
 		self->user = user;
 	} else {
 		PyErr_SetString(PyExc_SystemError, "Can not initialize 'user' attribute");
@@ -587,11 +587,11 @@
 	self->intenti = pdfOptions.Intent2; // int - 0 - 3
 	QString tp = pdfOptions.SolidProf;
 	if (!ScCore->InputProfiles.contains(tp))
 		tp = currentDoc->cmsSettings().DefaultSolidColorRGBProfile;
 	PyObject *solidpr = NULL;
-	solidpr = PyString_FromString(tp.toLatin1());
+	solidpr = Legacy_PyString_FromString(tp.toLatin1());
 	if (solidpr){
 		Py_DECREF(self->solidpr);
 		self->solidpr = solidpr;
 	} else {
 		PyErr_SetString(PyExc_SystemError, "Can not initialize 'solidpr' attribute");
@@ -599,11 +599,11 @@
 	}
 	QString tp2 = pdfOptions.ImageProf;
 	if (!ScCore->InputProfiles.contains(tp2))
 		tp2 = currentDoc->cmsSettings().DefaultSolidColorRGBProfile;
 	PyObject *imagepr = NULL;
-	imagepr = PyString_FromString(tp2.toLatin1());
+	imagepr = Legacy_PyString_FromString(tp2.toLatin1());
 	if (imagepr){
 		Py_DECREF(self->imagepr);
 		self->imagepr = imagepr;
 	} else {
 		PyErr_SetString(PyExc_SystemError, "Can not initialize 'imagepr' attribute");
@@ -611,21 +611,21 @@
 	}
 	QString tp3 = pdfOptions.PrintProf;
 	if (!ScCore->PDFXProfiles.contains(tp3))
 		tp3 = currentDoc->cmsSettings().DefaultPrinterProfile;
 	PyObject *printprofc = NULL;
-	printprofc = PyString_FromString(tp3.toLatin1());
+	printprofc = Legacy_PyString_FromString(tp3.toLatin1());
 	if (printprofc){
 		Py_DECREF(self->printprofc);
 		self->printprofc = printprofc;
 	} else {
 		PyErr_SetString(PyExc_SystemError, "Can not initialize 'printprofc' attribute");
 		return -1;
 	}
 	QString tinfo = pdfOptions.Info;
 	PyObject *info = NULL;
-	info = PyString_FromString(tinfo.toLatin1());
+	info = Legacy_PyString_FromString(tinfo.toLatin1());
 	if (info){
 		Py_DECREF(self->info);
 		self->info = info;
 	} else {
 		PyErr_SetString(PyExc_SystemError, "Can not initialize 'info' attribute");
@@ -659,11 +659,11 @@
 	self->hideToolBar = pdfOptions.hideToolBar; // bool
 	self->hideMenuBar = pdfOptions.hideMenuBar; // bool
 	self->fitWindow = pdfOptions.fitWindow; // bool
 
 	PyObject *openAction = NULL;
-	openAction = PyString_FromString(pdfOptions.openAction.toLatin1().data());
+	openAction = Legacy_PyString_FromString(pdfOptions.openAction.toLatin1().data());
 	if (openAction){
 		Py_DECREF(self->openAction);
 		self->openAction = openAction;
 	} else {
 		PyErr_SetString(PyExc_SystemError, "Can not initialize 'openAction' attribute");
@@ -1544,11 +1544,10 @@
 	{NULL, (PyCFunction)(0), 0, NULL} // sentinel
 };
 
 PyTypeObject PDFfile_Type = {
 	PyObject_HEAD_INIT(NULL) // PyObject_VAR_HEAD
-	0,		      //
 	const_cast<char*>("scribus.PDFfile"), // char *tp_name; /* For printing, in format "<module>.<name>" */
 	sizeof(PDFfile),     // int tp_basicsize, /* For allocation */
 	0,		    // int tp_itemsize; /* For allocation */
 
 	/* Methods to implement standard operations */
diff -r -U 5 old/scribus-1.5.3/scribus/plugins/scriptplugin/objprinter.cpp bug-submission/scribus/plugins/scriptplugin/objprinter.cpp
--- old/scribus-1.5.3/scribus/plugins/scriptplugin/objprinter.cpp	2017-05-28 11:10:24.000000000 +0200
+++ bug-submission/scribus/plugins/scriptplugin/objprinter.cpp	2017-10-25 23:52:35.000000000 +0200
@@ -57,11 +57,11 @@
 	Py_XDECREF(self->printer);
 	Py_XDECREF(self->file);
 	Py_XDECREF(self->cmd);
 	Py_XDECREF(self->pages);
 	Py_XDECREF(self->separation);
-	self->ob_type->tp_free((PyObject *)self);
+	Py_TYPE(self)->tp_free((PyObject *)self);
 }
 
 static PyObject * Printer_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
 {
 // do not create new object if there is no opened document
@@ -77,23 +77,23 @@
 		if (self->allPrinters == NULL){
 			Py_DECREF(self);
 			return NULL;
 		}
 // set printer attribute
-		self->printer = PyString_FromString("");
+		self->printer = Legacy_PyString_FromString("");
 		if (self->printer == NULL){
 			Py_DECREF(self);
 			return NULL;
 		}
 // set file attribute
-		self->file = PyString_FromString("");
+		self->file = Legacy_PyString_FromString("");
 		if (self->file == NULL){
 			Py_DECREF(self);
 			return NULL;
 		}
 // set cmd attribute
-		self->cmd = PyString_FromString("");
+		self->cmd = Legacy_PyString_FromString("");
 		if (self->cmd == NULL){
 			Py_DECREF(self);
 			return NULL;
 		}
 // set pages attribute
@@ -101,11 +101,11 @@
 		if (self->pages == NULL){
 			Py_DECREF(self);
 			return NULL;
 		}
 // set separation attribute
-		self->separation = PyString_FromString("No");
+		self->separation = Legacy_PyString_FromString("No");
 		if (self->separation == NULL){
 			Py_DECREF(self);
 			return NULL;
 		}
 // set color attribute
@@ -142,22 +142,22 @@
 	for (int i = 0; i < printers.count(); ++i)
 	{
 		QString prn = printers[i];
 		if (prn.isEmpty())
 			continue;
-		PyObject *tmppr = PyString_FromString(prn.toLocal8Bit().constData());
+		PyObject *tmppr = Legacy_PyString_FromString(prn.toLocal8Bit().constData());
 		if (tmppr){
 			PyList_Append(self->allPrinters, tmppr);
 			Py_DECREF(tmppr);
 		}
 	}
-	PyObject *tmp2 = PyString_FromString("File");
+	PyObject *tmp2 = Legacy_PyString_FromString("File");
 	PyList_Append(self->allPrinters, tmp2);
 	Py_DECREF(tmp2);
 // as defaut set to print into file
 	PyObject *printer = NULL;
-	printer = PyString_FromString("File");
+	printer = Legacy_PyString_FromString("File");
 	if (printer){
 		Py_DECREF(self->printer);
 		self->printer = printer;
 	}
 // set defaul name of file to print into
@@ -165,21 +165,21 @@
 	if (tf.isEmpty()) {
 		QFileInfo fi = QFileInfo(ScCore->primaryMainWindow()->doc->DocName);
 		tf = fi.path()+"/"+fi.baseName()+".pdf";
 	}
 	PyObject *file = NULL;
-	file = PyString_FromString(tf.toLatin1());
+	file = Legacy_PyString_FromString(tf.toLatin1());
 	if (file){
 		Py_DECREF(self->file);
 		self->file = file;
 	} else {
 		PyErr_SetString(PyExc_SystemError, "Can not initialize 'file' attribute");
 		return -1;
 	}
 // alternative printer commands default to ""
 	PyObject *cmd = NULL;
-	cmd = PyString_FromString("");
+	cmd = Legacy_PyString_FromString("");
 	if (cmd){
 		Py_DECREF(self->cmd);
 		self->cmd = cmd;
 	}
 // if document exist when created Printer instance
@@ -197,11 +197,11 @@
 		if (tmp)
 			PyList_SetItem(self->pages, i, tmp);
 	}
 // do not print separation
 	PyObject *separation = NULL;
-	separation = PyString_FromString("No");
+	separation = Legacy_PyString_FromString("No");
 	if (separation){
 		Py_DECREF(self->separation);
 		self->separation = separation;
 	}
 // print in color
@@ -512,11 +512,10 @@
 	{NULL, (PyCFunction)(0), 0, NULL} // sentinel
 };
 
 PyTypeObject Printer_Type = {
 	PyObject_HEAD_INIT(NULL)   // PyObject_VAR_HEAD
-	0,			 //
 	const_cast<char*>("scribus.Printer"), // char *tp_name; /* For printing, in format "<module>.<name>" */
 	sizeof(Printer),   // int tp_basicsize, /* For allocation */
 	0,		       // int tp_itemsize; /* For allocation */
 
 	/* Methods to implement standard operations */
diff -r -U 5 old/scribus-1.5.3/scribus/plugins/scriptplugin/scriptercore.cpp bug-submission/scribus/plugins/scriptplugin/scriptercore.cpp
--- old/scribus-1.5.3/scribus/plugins/scriptplugin/scriptercore.cpp	2017-05-28 11:10:24.000000000 +0200
+++ bug-submission/scribus/plugins/scriptplugin/scriptercore.cpp	2017-10-26 00:03:20.000000000 +0200
@@ -264,22 +264,24 @@
 
 	// Make sure sys.argv[0] is the path to the script
 	arguments.prepend(na.data());
 	//convert arguments (QListString) to char** for Python bridge
 	/* typically arguments == ['path/to/script.py','--argument1','valueforarg1','--flag']*/
-	char **comm = new char*[arguments.size()];
+	wchar_t **comm = new wchar_t*[arguments.size()];
 	for (int i = 0; i < arguments.size(); i++)
 	{
 		QByteArray localStr = arguments.at(i).toLocal8Bit();
-		comm[i] = new char[localStr.size() + 1]; //+1 to allow adding '\0'. may be useless, don't know how to check.
-		comm[i][localStr.size()] = 0;
-		strncpy(comm[i], localStr.data(), localStr.size());
+		char * tmp = new char[localStr.size() + 1];
+		tmp[localStr.size()] = 0;
+		strncpy(tmp, localStr.data(), localStr.size());
+		comm[i] = Py_DecodeLocale(tmp, NULL);
+		delete[] tmp;
 	}
 	PySys_SetArgv(arguments.size(), comm);
 
 	for (int i = 0; i < arguments.size(); i++)
-		delete[] comm[i];
+		PyMem_RawFree(comm[i]);
 	delete[] comm;
 	
 	// call python script
 	PyObject* m = PyImport_AddModule((char*)"__main__");
 	if (m == NULL)
@@ -292,19 +294,19 @@
 		// FIXME: If filename contains chars outside 7bit ascii, might be problems
 		PyObject* globals = PyModule_GetDict(m);
 		// Build the Python code to run the script
 		//QString cm = QString("from __future__ import division\n"); removed due #5252 PV
 		QString cm = QString("import sys\n");
-		cm        += QString("import cStringIO\n");
+		cm        += QString("import io\n");
 		/* Implementation of the help() in pydoc.py reads some OS variables
 		 * for output settings. I use ugly hack to stop freezing calling help()
 		 * in script. pv. */
 		cm        += QString("import os\nos.environ['PAGER'] = '/bin/false'\n"); // HACK
 		cm        += QString("sys.path[0] = \"%1\"\n").arg(escapedAbsPath);
 		// Replace sys.stdin with a dummy StringIO that always returns
 		// "" for read
-		cm        += QString("sys.stdin = cStringIO.StringIO()\n");
+		cm        += QString("sys.stdin = io.StringIO()\n");
 		// tell the script if it's running in the main intepreter or a subinterpreter
 		cm        += QString("import scribus\n");
 		if (inMainInterpreter)
 			cm+= QString("scribus.mainInterpreter = True\n");
 		else
@@ -409,25 +411,26 @@
 		Calling all code in one command:
 		ia = code.InteractiveInterpreter() ia.runsource(getval())
 		works fine in plain Python. Not here. WTF? */
 		cm += (
 				"try:\n"
-				"    import cStringIO\n"
-				"    scribus._bu = cStringIO.StringIO()\n"
+				"    print('Started script console.') # Outputs to stdout of scribus\n"
+				"    import io\n"
+				"    scribus._bu = io.StringIO()\n"
 				"    sys.stdout = scribus._bu\n"
 				"    sys.stderr = scribus._bu\n"
 				"    sys.argv = ['scribus']\n" // this is the PySys_SetArgv replacement
 				"    scribus.mainInterpreter = True\n" // the scripter console runs everything in the main interpreter
 				"    for i in scribus.getval().splitlines():\n"
 				"        scribus._ia.push(i)\n"
 				"    scribus.retval(scribus._bu.getvalue())\n"
 				"    sys.stdout = sys.__stdout__\n"
 				"    sys.stderr = sys.__stderr__\n"
 				"except SystemExit:\n"
-				"    print 'Catched SystemExit - it is not good for Scribus'\n"
+				"    print ('Catched SystemExit - it is not good for Scribus')\n"
 				"except KeyboardInterrupt:\n"
-				"    print 'Catched KeyboardInterrupt - it is not good for Scribus'\n"
+				"    print ('Catched KeyboardInterrupt - it is not good for Scribus')\n"
 			  );
 	}
 	// Set up sys.argv
 	/* PV - WARNING: THIS IS EVIL! This code summons a crash - see
 	bug #3510. I don't know why as the Python C API is a little
@@ -594,18 +597,20 @@
 	menuMgr->setText("RecentScripts", QObject::tr("&Recent Scripts"));
 }
 
 bool ScripterCore::setupMainInterpreter()
 {
+	// Code duplication - StringIO several times assigned to sys.stdin?
 	QString cm = QString(
 		"# -*- coding: utf-8 -*-\n"
 		"import scribus\n"
 		"import sys\n"
 		"import code\n"
 		"sys.path.insert(0, \"%1\")\n"
-		"import cStringIO\n"
-		"sys.stdin = cStringIO.StringIO()\n"
+		"import io\n"
+		"sys.stdin = io.StringIO()\n"
+		"#print('    scriptercore.cpp: This is the .so plugin loading code.')\n"
 		"scribus._ia = code.InteractiveConsole(globals())\n"
 		).arg(ScPaths::instance().scriptDir());
 	if (m_importAllNames)
 		cm += "from scribus import *\n";
 	QByteArray cmd = cm.toUtf8();
diff -r -U 5 old/scribus-1.5.3/scribus/plugins/scriptplugin/scriptplugin.cpp bug-submission/scribus/plugins/scriptplugin/scriptplugin.cpp
--- old/scribus-1.5.3/scribus/plugins/scriptplugin/scriptplugin.cpp	2017-05-28 11:10:24.000000000 +0200
+++ bug-submission/scribus/plugins/scriptplugin/scriptplugin.cpp	2017-09-01 17:26:00.000000000 +0200
@@ -168,20 +168,22 @@
 		QString ph = QDir::toNativeSeparators(pyHome);
 		pythonHome = ph.toLocal8Bit();
 		Py_SetPythonHome(pythonHome.data());
 	}
 #endif
+	scripterCore = new ScripterCore(ScCore->primaryMainWindow());
+	Q_CHECK_PTR(scripterCore);
+	
+	PyImport_AppendInittab("scribus", &PyInit_scribus);
 	Py_Initialize();
-	if (PyUnicode_SetDefaultEncoding("utf-8"))
+	/*if (PyUnicode_SetDefaultEncoding("utf-8"))
 	{
 		qDebug("Failed to set default encoding to utf-8.\n");
 		PyErr_Clear();
-	}
+	}*/
 
-	scripterCore = new ScripterCore(ScCore->primaryMainWindow());
-	Q_CHECK_PTR(scripterCore);
-	initscribus(ScCore->primaryMainWindow());
+	//initscribus(ScCore->primaryMainWindow());
 #ifdef HAVE_SCRIPTER2
 	scripter2_init();
 #endif
 	scripterCore->setupMainInterpreter();
 	scripterCore->initExtensionScripts();
@@ -252,11 +254,11 @@
 	return PyInt_FromLong(0L);
 }
 
 /*static */PyObject *scribus_getval(PyObject* /*self*/)
 {
-	return PyString_FromString(scripterCore->inValue.toUtf8().data());
+	return PyUnicode_FromString(scripterCore->inValue.toUtf8().data());
 }
 
 /*! \brief Translate a docstring. Small helper function for use with the
  * PyMethodDef struct.
  */
@@ -573,32 +575,70 @@
 	{const_cast<char*>("retval"), (PyCFunction)scribus_retval, METH_VARARGS, const_cast<char*>("Scribus internal.")},
 	{const_cast<char*>("getval"), (PyCFunction)scribus_getval, METH_NOARGS, const_cast<char*>("Scribus internal.")},
 	{NULL, (PyCFunction)(0), 0, NULL} /* sentinel */
 };
 
+
+struct module_state {
+    PyObject *error;
+};
+#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
+
+static int myextension_traverse(PyObject *m, visitproc visit, void *arg) {
+    Py_VISIT(GETSTATE(m)->error);
+    return 0;
+}
+
+static int myextension_clear(PyObject *m) {
+    Py_CLEAR(GETSTATE(m)->error);
+    return 0;
+}
+
+static struct PyModuleDef moduledef = {
+        PyModuleDef_HEAD_INIT,
+        "scribus",
+        NULL,
+        sizeof(struct module_state),
+        scribus_methods,
+        NULL,
+        myextension_traverse,
+        myextension_clear,
+        NULL
+};
+
+
 void initscribus_failed(const char* fileName, int lineNo)
 {
 	qDebug("Scripter setup failed (%s:%i)", fileName, lineNo);
 	if (PyErr_Occurred())
 		PyErr_Print();
 	return;
 }
 
+// explanation on how it's to be done: https://docs.python.org/3/howto/cporting.html
+// Additional hint: has to be called by PyImport_AppendInittab before Py_Initialize
+/*static*/ PyObject* PyInit_scribus(void) {
+	PyObject *m;
+	m = PyModule_Create(&moduledef);
+	return m;
+}
 void initscribus(ScribusMainWindow *pl)
 {
+	
 	if (!scripterCore)
 	{
 		qWarning("scriptplugin: Tried to init scribus module, but no scripter core. Aborting.");
 		return;
 	}
 	PyObject *m, *d;
-	PyImport_AddModule((char*)"scribus");
+	m = PyImport_AddModule((char*)"scribus");
 
 	PyType_Ready(&Printer_Type);
 	PyType_Ready(&PDFfile_Type);
 	PyType_Ready(&ImageExport_Type);
-	m = Py_InitModule((char*)"scribus", scribus_methods);
+	//m = Py_InitModule((char*)"scribus", scribus_methods);
+	
 	Py_INCREF(&Printer_Type);
 	PyModule_AddObject(m, (char*)"Printer", (PyObject *) &Printer_Type);
 	Py_INCREF(&PDFfile_Type);
 	PyModule_AddObject(m, (char*)"PDFfile", (PyObject *) &PDFfile_Type);
 	Py_INCREF(&ImageExport_Type);
@@ -631,116 +671,116 @@
 	Py_INCREF(NameExistsError);
 	PyModule_AddObject(m, (char*)"NameExistsError", NameExistsError);
 	// Done with exception setup
 
 	// CONSTANTS
-	PyDict_SetItemString(d, const_cast<char*>("UNIT_POINTS"), PyInt_FromLong(unitIndexFromString("pt")));
-	PyDict_SetItemString(d, const_cast<char*>("UNIT_MILLIMETERS"), PyInt_FromLong(unitIndexFromString("mm")));
-	PyDict_SetItemString(d, const_cast<char*>("UNIT_INCHES"), PyInt_FromLong(unitIndexFromString("in")));
-	PyDict_SetItemString(d, const_cast<char*>("UNIT_PICAS"), PyInt_FromLong(unitIndexFromString("p")));
-	PyDict_SetItemString(d, const_cast<char*>("UNIT_CENTIMETRES"), PyInt_FromLong(unitIndexFromString("cm")));
-	PyDict_SetItemString(d, const_cast<char*>("UNIT_CICERO"), PyInt_FromLong(unitIndexFromString("c")));
-        PyDict_SetItemString(d, const_cast<char*>("UNIT_PT"), PyInt_FromLong(unitIndexFromString("pt")));
-        PyDict_SetItemString(d, const_cast<char*>("UNIT_MM"), PyInt_FromLong(unitIndexFromString("mm")));
-        PyDict_SetItemString(d, const_cast<char*>("UNIT_IN"), PyInt_FromLong(unitIndexFromString("in")));
-        PyDict_SetItemString(d, const_cast<char*>("UNIT_P"), PyInt_FromLong(unitIndexFromString("p")));
-        PyDict_SetItemString(d, const_cast<char*>("UNIT_CM"), PyInt_FromLong(unitIndexFromString("cm")));
-        PyDict_SetItemString(d, const_cast<char*>("UNIT_C"), PyInt_FromLong(unitIndexFromString("c")));
-	PyDict_SetItemString(d, const_cast<char*>("PORTRAIT"), Py_BuildValue(const_cast<char*>("i"), portraitPage));
-	PyDict_SetItemString(d, const_cast<char*>("LANDSCAPE"), Py_BuildValue(const_cast<char*>("i"), landscapePage));
-	PyDict_SetItemString(d, const_cast<char*>("NOFACINGPAGES"), Py_BuildValue(const_cast<char*>("i"), 0));
-	PyDict_SetItemString(d, const_cast<char*>("FACINGPAGES"),  Py_BuildValue(const_cast<char*>("i"), 1));
-	PyDict_SetItemString(d, const_cast<char*>("FIRSTPAGERIGHT"), Py_BuildValue(const_cast<char*>("i"), 1));
-	PyDict_SetItemString(d, const_cast<char*>("FIRSTPAGELEFT"), Py_BuildValue(const_cast<char*>("i"), 0));
-	PyDict_SetItemString(d, const_cast<char*>("ALIGN_LEFT"), Py_BuildValue(const_cast<char*>("i"), 0));
-	PyDict_SetItemString(d, const_cast<char*>("ALIGN_RIGHT"), Py_BuildValue(const_cast<char*>("i"), 2));
-	PyDict_SetItemString(d, const_cast<char*>("ALIGN_CENTERED"), Py_BuildValue(const_cast<char*>("i"), 1));
-	PyDict_SetItemString(d, const_cast<char*>("ALIGN_BLOCK"), Py_BuildValue(const_cast<char*>("i"), 3));
-	PyDict_SetItemString(d, const_cast<char*>("ALIGN_FORCED"), Py_BuildValue(const_cast<char*>("i"), 4));
-	PyDict_SetItemString(d, const_cast<char*>("DIRECTION_LTR"), Py_BuildValue(const_cast<char*>("i"), 0));
-	PyDict_SetItemString(d, const_cast<char*>("DIRECTION_RTL"), Py_BuildValue(const_cast<char*>("i"), 1));
-	PyDict_SetItemString(d, const_cast<char*>("FILL_NOG"), Py_BuildValue(const_cast<char*>("i"), 0));
-	PyDict_SetItemString(d, const_cast<char*>("FILL_HORIZONTALG"), Py_BuildValue(const_cast<char*>("i"), 1));
-	PyDict_SetItemString(d, const_cast<char*>("FILL_VERTICALG"), Py_BuildValue(const_cast<char*>("i"), 2));
-	PyDict_SetItemString(d, const_cast<char*>("FILL_DIAGONALG"), Py_BuildValue(const_cast<char*>("i"), 3));
-	PyDict_SetItemString(d, const_cast<char*>("FILL_CROSSDIAGONALG"), Py_BuildValue(const_cast<char*>("i"), 4));
-	PyDict_SetItemString(d, const_cast<char*>("FILL_RADIALG"), Py_BuildValue(const_cast<char*>("i"), 5));
-	PyDict_SetItemString(d, const_cast<char*>("LINE_SOLID"), Py_BuildValue(const_cast<char*>("i"), Qt::SolidLine));
-	PyDict_SetItemString(d, const_cast<char*>("LINE_DASH"), Py_BuildValue(const_cast<char*>("i"), Qt::DashLine));
-	PyDict_SetItemString(d, const_cast<char*>("LINE_DOT"), Py_BuildValue(const_cast<char*>("i"), Qt::DotLine));
-	PyDict_SetItemString(d, const_cast<char*>("LINE_DASHDOT"), Py_BuildValue(const_cast<char*>("i"), Qt::DashDotLine));
-	PyDict_SetItemString(d, const_cast<char*>("LINE_DASHDOTDOT"), Py_BuildValue(const_cast<char*>("i"), Qt::DashDotDotLine));
-	PyDict_SetItemString(d, const_cast<char*>("JOIN_MITTER"), Py_BuildValue(const_cast<char*>("i"), Qt::MiterJoin));
-	PyDict_SetItemString(d, const_cast<char*>("JOIN_BEVEL"), Py_BuildValue(const_cast<char*>("i"), Qt::BevelJoin));
-	PyDict_SetItemString(d, const_cast<char*>("JOIN_ROUND"), Py_BuildValue(const_cast<char*>("i"), Qt::RoundJoin));
-	PyDict_SetItemString(d, const_cast<char*>("CAP_FLAT"), Py_BuildValue(const_cast<char*>("i"), Qt::FlatCap));
-	PyDict_SetItemString(d, const_cast<char*>("CAP_SQUARE"), Py_BuildValue(const_cast<char*>("i"), Qt::SquareCap));
-	PyDict_SetItemString(d, const_cast<char*>("CAP_ROUND"), Py_BuildValue(const_cast<char*>("i"), Qt::RoundCap));
-	PyDict_SetItemString(d, const_cast<char*>("BUTTON_NONE"), Py_BuildValue(const_cast<char*>("i"), QMessageBox::NoButton));
-	PyDict_SetItemString(d, const_cast<char*>("BUTTON_OK"), Py_BuildValue(const_cast<char*>("i"), QMessageBox::Ok));
-	PyDict_SetItemString(d, const_cast<char*>("BUTTON_CANCEL"), Py_BuildValue(const_cast<char*>("i"), QMessageBox::Cancel));
-	PyDict_SetItemString(d, const_cast<char*>("BUTTON_YES"), Py_BuildValue(const_cast<char*>("i"), QMessageBox::Yes));
-	PyDict_SetItemString(d, const_cast<char*>("BUTTON_NO"), Py_BuildValue(const_cast<char*>("i"), QMessageBox::No));
-	PyDict_SetItemString(d, const_cast<char*>("BUTTON_ABORT"), Py_BuildValue(const_cast<char*>("i"), QMessageBox::Abort));
-	PyDict_SetItemString(d, const_cast<char*>("BUTTON_RETRY"), Py_BuildValue(const_cast<char*>("i"), QMessageBox::Retry));
-	PyDict_SetItemString(d, const_cast<char*>("BUTTON_IGNORE"), Py_BuildValue(const_cast<char*>("i"), QMessageBox::Ignore));
-	PyDict_SetItemString(d, const_cast<char*>("BUTTON_DEFAULT"), Py_BuildValue(const_cast<char*>("i"), QMessageBox::Default));
-	PyDict_SetItemString(d, const_cast<char*>("ICON_NONE"), Py_BuildValue(const_cast<char*>("i"), QMessageBox::NoIcon));
-	PyDict_SetItemString(d, const_cast<char*>("ICON_INFORMATION"), Py_BuildValue(const_cast<char*>("i"), QMessageBox::Information));
-	PyDict_SetItemString(d, const_cast<char*>("ICON_WARNING"), Py_BuildValue(const_cast<char*>("i"), QMessageBox::Warning));
-	PyDict_SetItemString(d, const_cast<char*>("ICON_CRITICAL"), Py_BuildValue(const_cast<char*>("i"), QMessageBox::Critical));
-	PyDict_SetItemString(d, const_cast<char*>("PAPER_A0"), Py_BuildValue(const_cast<char*>("(ff)"), 2380.0, 3368.0));
-	PyDict_SetItemString(d, const_cast<char*>("PAPER_A1"), Py_BuildValue(const_cast<char*>("(ff)"), 1684.0, 2380.0));
-	PyDict_SetItemString(d, const_cast<char*>("PAPER_A2"), Py_BuildValue(const_cast<char*>("(ff)"), 1190.0, 1684.0));
-	PyDict_SetItemString(d, const_cast<char*>("PAPER_A3"), Py_BuildValue(const_cast<char*>("(ff)"), 842.0, 1190.0));
-	PyDict_SetItemString(d, const_cast<char*>("PAPER_A4"), Py_BuildValue(const_cast<char*>("(ff)"), 595.0, 842.0));
-	PyDict_SetItemString(d, const_cast<char*>("PAPER_A5"), Py_BuildValue(const_cast<char*>("(ff)"), 421.0, 595.0));
-	PyDict_SetItemString(d, const_cast<char*>("PAPER_A6"), Py_BuildValue(const_cast<char*>("(ff)"), 297.0, 421.0));
-	PyDict_SetItemString(d, const_cast<char*>("PAPER_A7"), Py_BuildValue(const_cast<char*>("(ff)"), 210.0, 297.0));
-	PyDict_SetItemString(d, const_cast<char*>("PAPER_A8"), Py_BuildValue(const_cast<char*>("(ff)"), 148.0, 210.0));
-	PyDict_SetItemString(d, const_cast<char*>("PAPER_A9"), Py_BuildValue(const_cast<char*>("(ff)"), 105.0, 148.0));
-	PyDict_SetItemString(d, const_cast<char*>("PAPER_B0"), Py_BuildValue(const_cast<char*>("(ff)"), 2836.0, 4008.0));
-	PyDict_SetItemString(d, const_cast<char*>("PAPER_B1"), Py_BuildValue(const_cast<char*>("(ff)"), 2004.0, 2836.0));
-	PyDict_SetItemString(d, const_cast<char*>("PAPER_B2"), Py_BuildValue(const_cast<char*>("(ff)"), 1418.0, 2004.0));
-	PyDict_SetItemString(d, const_cast<char*>("PAPER_B3"), Py_BuildValue(const_cast<char*>("(ff)"), 1002.0, 1418.0));
-	PyDict_SetItemString(d, const_cast<char*>("PAPER_B4"), Py_BuildValue(const_cast<char*>("(ff)"), 709.0, 1002.0));
-	PyDict_SetItemString(d, const_cast<char*>("PAPER_B5"), Py_BuildValue(const_cast<char*>("(ff)"), 501.0, 709.0));
-	PyDict_SetItemString(d, const_cast<char*>("PAPER_B6"), Py_BuildValue(const_cast<char*>("(ff)"), 355.0, 501.0));
-	PyDict_SetItemString(d, const_cast<char*>("PAPER_B7"), Py_BuildValue(const_cast<char*>("(ff)"), 250.0, 355.0));
-	PyDict_SetItemString(d, const_cast<char*>("PAPER_B8"), Py_BuildValue(const_cast<char*>("(ff)"), 178.0, 250.0));
-	PyDict_SetItemString(d, const_cast<char*>("PAPER_B9"), Py_BuildValue(const_cast<char*>("(ff)"), 125.0, 178.0));
-	PyDict_SetItemString(d, const_cast<char*>("PAPER_B10"), Py_BuildValue(const_cast<char*>("(ff)"), 89.0, 125.0));
-	PyDict_SetItemString(d, const_cast<char*>("PAPER_C5E"), Py_BuildValue(const_cast<char*>("(ff)"), 462.0, 649.0));
-	PyDict_SetItemString(d, const_cast<char*>("PAPER_COMM10E"), Py_BuildValue(const_cast<char*>("(ff)"), 298.0, 683.0));
-	PyDict_SetItemString(d, const_cast<char*>("PAPER_DLE"),  Py_BuildValue(const_cast<char*>("(ff)"), 312.0, 624.0));
-	PyDict_SetItemString(d, const_cast<char*>("PAPER_EXECUTIVE"), Py_BuildValue(const_cast<char*>("(ff)"), 542.0, 720.0));
-	PyDict_SetItemString(d, const_cast<char*>("PAPER_FOLIO"), Py_BuildValue(const_cast<char*>("(ff)"), 595.0, 935.0));
-	PyDict_SetItemString(d, const_cast<char*>("PAPER_LEDGER"), Py_BuildValue(const_cast<char*>("(ff)"), 1224.0, 792.0));
-	PyDict_SetItemString(d, const_cast<char*>("PAPER_LEGAL"), Py_BuildValue(const_cast<char*>("(ff)"), 612.0, 1008.0));
-	PyDict_SetItemString(d, const_cast<char*>("PAPER_LETTER"), Py_BuildValue(const_cast<char*>("(ff)"), 612.0, 792.0));
-	PyDict_SetItemString(d, const_cast<char*>("PAPER_TABLOID"), Py_BuildValue(const_cast<char*>("(ff)"), 792.0, 1224.0));
-	PyDict_SetItemString(d, const_cast<char*>("NORMAL"), Py_BuildValue(const_cast<char*>("i"), 0));
-	PyDict_SetItemString(d, const_cast<char*>("DARKEN"), Py_BuildValue(const_cast<char*>("i"), 1));
-	PyDict_SetItemString(d, const_cast<char*>("LIGHTEN"), Py_BuildValue(const_cast<char*>("i"), 2));
-	PyDict_SetItemString(d, const_cast<char*>("MULTIPLY"), Py_BuildValue(const_cast<char*>("i"), 3));
-	PyDict_SetItemString(d, const_cast<char*>("SCREEN"), Py_BuildValue(const_cast<char*>("i"), 4));
-	PyDict_SetItemString(d, const_cast<char*>("OVERLAY"), Py_BuildValue(const_cast<char*>("i"), 5));
-	PyDict_SetItemString(d, const_cast<char*>("HARD_LIGHT"), Py_BuildValue(const_cast<char*>("i"), 6));
-	PyDict_SetItemString(d, const_cast<char*>("SOFT_LIGHT"), Py_BuildValue(const_cast<char*>("i"), 7));
-	PyDict_SetItemString(d, const_cast<char*>("DIFFERENCE"), Py_BuildValue(const_cast<char*>("i"), 8));
-	PyDict_SetItemString(d, const_cast<char*>("EXCLUSION"), Py_BuildValue(const_cast<char*>("i"), 9));
-	PyDict_SetItemString(d, const_cast<char*>("COLOR_DODGE"), Py_BuildValue(const_cast<char*>("i"), 10));
-	PyDict_SetItemString(d, const_cast<char*>("COLOR_BURN"), Py_BuildValue(const_cast<char*>("i"), 11));
-	PyDict_SetItemString(d, const_cast<char*>("HUE"), Py_BuildValue(const_cast<char*>("i"), 12));
-	PyDict_SetItemString(d, const_cast<char*>("SATURATION"), Py_BuildValue(const_cast<char*>("i"), 13));
-	PyDict_SetItemString(d, const_cast<char*>("COLOR"), Py_BuildValue(const_cast<char*>("i"), 14));
-	PyDict_SetItemString(d, const_cast<char*>("LUMINOSITY"), Py_BuildValue(const_cast<char*>("i"), 15));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("UNIT_POINTS")), PyInt_FromLong(unitIndexFromString("pt")));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("UNIT_MILLIMETERS")), PyInt_FromLong(unitIndexFromString("mm")));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("UNIT_INCHES")), PyInt_FromLong(unitIndexFromString("in")));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("UNIT_PICAS")), PyInt_FromLong(unitIndexFromString("p")));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("UNIT_CENTIMETRES")), PyInt_FromLong(unitIndexFromString("cm")));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("UNIT_CICERO")), PyInt_FromLong(unitIndexFromString("c")));
+        PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("UNIT_PT")), PyInt_FromLong(unitIndexFromString("pt")));
+        PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("UNIT_MM")), PyInt_FromLong(unitIndexFromString("mm")));
+        PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("UNIT_IN")), PyInt_FromLong(unitIndexFromString("in")));
+        PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("UNIT_P")), PyInt_FromLong(unitIndexFromString("p")));
+        PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("UNIT_CM")), PyInt_FromLong(unitIndexFromString("cm")));
+        PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("UNIT_C")), PyInt_FromLong(unitIndexFromString("c")));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PORTRAIT")), Py_BuildValue(const_cast<char*>("i"), portraitPage));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("LANDSCAPE")), Py_BuildValue(const_cast<char*>("i"), landscapePage));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("NOFACINGPAGES")), Py_BuildValue(const_cast<char*>("i"), 0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("FACINGPAGES")),  Py_BuildValue(const_cast<char*>("i"), 1));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("FIRSTPAGERIGHT")), Py_BuildValue(const_cast<char*>("i"), 1));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("FIRSTPAGELEFT")), Py_BuildValue(const_cast<char*>("i"), 0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("ALIGN_LEFT")), Py_BuildValue(const_cast<char*>("i"), 0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("ALIGN_RIGHT")), Py_BuildValue(const_cast<char*>("i"), 2));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("ALIGN_CENTERED")), Py_BuildValue(const_cast<char*>("i"), 1));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("ALIGN_BLOCK")), Py_BuildValue(const_cast<char*>("i"), 3));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("ALIGN_FORCED")), Py_BuildValue(const_cast<char*>("i"), 4));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("DIRECTION_LTR")), Py_BuildValue(const_cast<char*>("i"), 0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("DIRECTION_RTL")), Py_BuildValue(const_cast<char*>("i"), 1));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("FILL_NOG")), Py_BuildValue(const_cast<char*>("i"), 0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("FILL_HORIZONTALG")), Py_BuildValue(const_cast<char*>("i"), 1));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("FILL_VERTICALG")), Py_BuildValue(const_cast<char*>("i"), 2));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("FILL_DIAGONALG")), Py_BuildValue(const_cast<char*>("i"), 3));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("FILL_CROSSDIAGONALG")), Py_BuildValue(const_cast<char*>("i"), 4));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("FILL_RADIALG")), Py_BuildValue(const_cast<char*>("i"), 5));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("LINE_SOLID")), Py_BuildValue(const_cast<char*>("i"), Qt::SolidLine));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("LINE_DASH")), Py_BuildValue(const_cast<char*>("i"), Qt::DashLine));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("LINE_DOT")), Py_BuildValue(const_cast<char*>("i"), Qt::DotLine));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("LINE_DASHDOT")), Py_BuildValue(const_cast<char*>("i"), Qt::DashDotLine));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("LINE_DASHDOTDOT")), Py_BuildValue(const_cast<char*>("i"), Qt::DashDotDotLine));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("JOIN_MITTER")), Py_BuildValue(const_cast<char*>("i"), Qt::MiterJoin));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("JOIN_BEVEL")), Py_BuildValue(const_cast<char*>("i"), Qt::BevelJoin));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("JOIN_ROUND")), Py_BuildValue(const_cast<char*>("i"), Qt::RoundJoin));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("CAP_FLAT")), Py_BuildValue(const_cast<char*>("i"), Qt::FlatCap));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("CAP_SQUARE")), Py_BuildValue(const_cast<char*>("i"), Qt::SquareCap));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("CAP_ROUND")), Py_BuildValue(const_cast<char*>("i"), Qt::RoundCap));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("BUTTON_NONE")), Py_BuildValue(const_cast<char*>("i"), QMessageBox::NoButton));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("BUTTON_OK")), Py_BuildValue(const_cast<char*>("i"), QMessageBox::Ok));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("BUTTON_CANCEL")), Py_BuildValue(const_cast<char*>("i"), QMessageBox::Cancel));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("BUTTON_YES")), Py_BuildValue(const_cast<char*>("i"), QMessageBox::Yes));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("BUTTON_NO")), Py_BuildValue(const_cast<char*>("i"), QMessageBox::No));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("BUTTON_ABORT")), Py_BuildValue(const_cast<char*>("i"), QMessageBox::Abort));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("BUTTON_RETRY")), Py_BuildValue(const_cast<char*>("i"), QMessageBox::Retry));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("BUTTON_IGNORE")), Py_BuildValue(const_cast<char*>("i"), QMessageBox::Ignore));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("BUTTON_DEFAULT")), Py_BuildValue(const_cast<char*>("i"), QMessageBox::Default));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("ICON_NONE")), Py_BuildValue(const_cast<char*>("i"), QMessageBox::NoIcon));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("ICON_INFORMATION")), Py_BuildValue(const_cast<char*>("i"), QMessageBox::Information));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("ICON_WARNING")), Py_BuildValue(const_cast<char*>("i"), QMessageBox::Warning));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("ICON_CRITICAL")), Py_BuildValue(const_cast<char*>("i"), QMessageBox::Critical));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_A0")), Py_BuildValue(const_cast<char*>("(ff)"), 2380.0, 3368.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_A1")), Py_BuildValue(const_cast<char*>("(ff)"), 1684.0, 2380.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_A2")), Py_BuildValue(const_cast<char*>("(ff)"), 1190.0, 1684.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_A3")), Py_BuildValue(const_cast<char*>("(ff)"), 842.0, 1190.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_A4")), Py_BuildValue(const_cast<char*>("(ff)"), 595.0, 842.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_A5")), Py_BuildValue(const_cast<char*>("(ff)"), 421.0, 595.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_A6")), Py_BuildValue(const_cast<char*>("(ff)"), 297.0, 421.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_A7")), Py_BuildValue(const_cast<char*>("(ff)"), 210.0, 297.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_A8")), Py_BuildValue(const_cast<char*>("(ff)"), 148.0, 210.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_A9")), Py_BuildValue(const_cast<char*>("(ff)"), 105.0, 148.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_B0")), Py_BuildValue(const_cast<char*>("(ff)"), 2836.0, 4008.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_B1")), Py_BuildValue(const_cast<char*>("(ff)"), 2004.0, 2836.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_B2")), Py_BuildValue(const_cast<char*>("(ff)"), 1418.0, 2004.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_B3")), Py_BuildValue(const_cast<char*>("(ff)"), 1002.0, 1418.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_B4")), Py_BuildValue(const_cast<char*>("(ff)"), 709.0, 1002.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_B5")), Py_BuildValue(const_cast<char*>("(ff)"), 501.0, 709.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_B6")), Py_BuildValue(const_cast<char*>("(ff)"), 355.0, 501.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_B7")), Py_BuildValue(const_cast<char*>("(ff)"), 250.0, 355.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_B8")), Py_BuildValue(const_cast<char*>("(ff)"), 178.0, 250.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_B9")), Py_BuildValue(const_cast<char*>("(ff)"), 125.0, 178.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_B10")), Py_BuildValue(const_cast<char*>("(ff)"), 89.0, 125.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_C5E")), Py_BuildValue(const_cast<char*>("(ff)"), 462.0, 649.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_COMM10E")), Py_BuildValue(const_cast<char*>("(ff)"), 298.0, 683.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_DLE")),  Py_BuildValue(const_cast<char*>("(ff)"), 312.0, 624.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_EXECUTIVE")), Py_BuildValue(const_cast<char*>("(ff)"), 542.0, 720.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_FOLIO")), Py_BuildValue(const_cast<char*>("(ff)"), 595.0, 935.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_LEDGER")), Py_BuildValue(const_cast<char*>("(ff)"), 1224.0, 792.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_LEGAL")), Py_BuildValue(const_cast<char*>("(ff)"), 612.0, 1008.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_LETTER")), Py_BuildValue(const_cast<char*>("(ff)"), 612.0, 792.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_TABLOID")), Py_BuildValue(const_cast<char*>("(ff)"), 792.0, 1224.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("NORMAL")), Py_BuildValue(const_cast<char*>("i"), 0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("DARKEN")), Py_BuildValue(const_cast<char*>("i"), 1));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("LIGHTEN")), Py_BuildValue(const_cast<char*>("i"), 2));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("MULTIPLY")), Py_BuildValue(const_cast<char*>("i"), 3));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("SCREEN")), Py_BuildValue(const_cast<char*>("i"), 4));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("OVERLAY")), Py_BuildValue(const_cast<char*>("i"), 5));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("HARD_LIGHT")), Py_BuildValue(const_cast<char*>("i"), 6));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("SOFT_LIGHT")), Py_BuildValue(const_cast<char*>("i"), 7));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("DIFFERENCE")), Py_BuildValue(const_cast<char*>("i"), 8));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("EXCLUSION")), Py_BuildValue(const_cast<char*>("i"), 9));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("COLOR_DODGE")), Py_BuildValue(const_cast<char*>("i"), 10));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("COLOR_BURN")), Py_BuildValue(const_cast<char*>("i"), 11));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("HUE")), Py_BuildValue(const_cast<char*>("i"), 12));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("SATURATION")), Py_BuildValue(const_cast<char*>("i"), 13));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("COLOR")), Py_BuildValue(const_cast<char*>("i"), 14));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("LUMINOSITY")), Py_BuildValue(const_cast<char*>("i"), 15));
 	// preset page layouts
-	PyDict_SetItemString(d, const_cast<char*>("PAGE_1"), Py_BuildValue(const_cast<char*>("i"), 0));
-	PyDict_SetItemString(d, const_cast<char*>("PAGE_2"), Py_BuildValue(const_cast<char*>("i"), 1));
-	PyDict_SetItemString(d, const_cast<char*>("PAGE_3"), Py_BuildValue(const_cast<char*>("i"), 2));
-	PyDict_SetItemString(d, const_cast<char*>("PAGE_4"), Py_BuildValue(const_cast<char*>("i"), 3));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAGE_1")), Py_BuildValue(const_cast<char*>("i"), 0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAGE_2")), Py_BuildValue(const_cast<char*>("i"), 1));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAGE_3")), Py_BuildValue(const_cast<char*>("i"), 2));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAGE_4")), Py_BuildValue(const_cast<char*>("i"), 3));
 
 	// Measurement units understood by Scribus's units.cpp functions are exported as constant conversion
 	// factors to be used from Python.
 	for (int i = 0; i <= unitGetMaxIndex()-2; ++i)
 	{
@@ -751,13 +791,13 @@
 			return;
 		}
 		// `in' is a reserved word in Python so we must replace it
 		PyObject* name;
 		if (unitGetUntranslatedStrFromIndex(i) == "in")
-			name = PyString_FromString("inch");
+			name = PyUnicode_FromString("inch");
 		else
-			name = PyString_FromString(unitGetUntranslatedStrFromIndex(i).toLatin1().constData());
+			name = PyUnicode_FromString(unitGetUntranslatedStrFromIndex(i).toLatin1().constData());
 		if (!name)
 		{
 			initscribus_failed(__FILE__, __LINE__);
 			return;
 		}
@@ -767,11 +807,11 @@
 			return;
 		}
 	}
 
 	// Export the Scribus version into the module namespace so scripts know what they're running in
-	PyDict_SetItemString(d, const_cast<char*>("scribus_version"), PyString_FromString(const_cast<char*>(VERSION)));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("scribus_version")), PyUnicode_FromString(const_cast<char*>(VERSION)));
 	// Now build a version tuple like that provided by Python in sys.version_info
 	// The tuple is of the form (major, minor, patchlevel, extraversion, reserved)
 	QRegExp version_re("(\\d+)\\.(\\d+)\\.(\\d+)(.*)");
 	int pos = version_re.indexIn(QString(VERSION));
 	// We ignore errors, causing the scribus_version_info attribute to simply not be created.
@@ -783,47 +823,52 @@
 		int patchVersion = version_re.cap(3).toInt();
 		QString extraVersion = version_re.cap(4);
 		PyObject* versionTuple = Py_BuildValue(const_cast<char*>("(iiisi)"),\
 				majorVersion, minorVersion, patchVersion, (const char*)extraVersion.toUtf8(), 0);
 		if (versionTuple != NULL)
-			PyDict_SetItemString(d, const_cast<char*>("scribus_version_info"), versionTuple);
+			PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("scribus_version_info")), versionTuple);
 		else
 			qDebug("Failed to build version tuple for version string '%s' in scripter", VERSION);
 	}
 	else
 		qDebug("Couldn't parse version string '%s' in scripter", VERSION);
 
 // 	ScMW = pl;
 	// Function aliases for compatibility
-	// We need to import the __builtins__, warnings and exceptions modules to be able to run
+	// We need to import the builtins, warnings and exceptions modules to be able to run
 	// the generated Python functions from inside the `scribus' module's context.
 	// This code makes it possible to extend the `scribus' module by running Python code
 	// from C in other ways too.
-	PyObject* builtinModule = PyImport_ImportModuleEx(const_cast<char*>("__builtin__"),
+	// JONAS: __builtin__ -> builtins (Python3)
+	PyObject* builtinModule = PyImport_ImportModuleEx(const_cast<char*>("builtins"),
 			d, d, Py_BuildValue(const_cast<char*>("[]")));
 	if (builtinModule == NULL)
 	{
-		qDebug("Failed to import __builtin__ module. Something is probably broken with your Python.");
+		qDebug("Failed to import builtins module. Something is probably broken with your Python.");
 		return;
 	}
-	PyDict_SetItemString(d, const_cast<char*>("__builtin__"), builtinModule);
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("builtins")), builtinModule);
+	
+	/* JONAS: "exceptions" has been merged into "builtins" in Python 3
 	PyObject* exceptionsModule = PyImport_ImportModuleEx(const_cast<char*>("exceptions"),
 			d, d, Py_BuildValue(const_cast<char*>("[]")));
 	if (exceptionsModule == NULL)
 	{
 		qDebug("Failed to import exceptions module. Something is probably broken with your Python.");
 		return;
 	}
-	PyDict_SetItemString(d, const_cast<char*>("exceptions"), exceptionsModule);
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("exceptions")), exceptionsModule);
+	*/
+	
 	PyObject* warningsModule = PyImport_ImportModuleEx(const_cast<char*>("warnings"),
 			d, d, Py_BuildValue(const_cast<char*>("[]")));
 	if (warningsModule == NULL)
 	{
 		qDebug("Failed to import warnings module. Something is probably broken with your Python.");
 		return;
 	}
-	PyDict_SetItemString(d, const_cast<char*>("warnings"), warningsModule);
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("warnings")), warningsModule);
 	// Create the module-level docstring. This can be a proper unicode string, unlike
 	// the others, because we can just create a Unicode object and insert it in our
 	// module dictionary.
 	QString docstring = QObject::tr("Scribus Python interface module\n\
 \n\
@@ -855,24 +900,26 @@
 Details of what exceptions each function may throw are provided on the\n\
 function's documentation, though as with most Python code this list\n\
 is not exhaustive due to exceptions from called functions.\n\
 ");
 
-	PyObject* docStr = PyString_FromString(docstring.toUtf8().data());
+	PyObject* docStr = PyUnicode_FromString(docstring.toUtf8().data());
 	if (!docStr)
 		qDebug("Failed to create module-level docstring (couldn't make str)");
 	else
 	{
-		PyObject* uniDocStr = PyUnicode_FromEncodedObject(docStr, "utf-8", NULL);
+		PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("__doc__")), docStr);
+		/*PyObject* uniDocStr = PyUnicode_FromEncodedObject(docStr, "utf-8", NULL);
 		Py_DECREF(docStr);
 		docStr = NULL;
 		if (!uniDocStr)
 			qDebug("Failed to create module-level docstring object (couldn't make unicode)");
 		else
-			PyDict_SetItemString(d, const_cast<char*>("__doc__"), uniDocStr);
+			PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("__doc__")), uniDocStr);
 		Py_DECREF(uniDocStr);
 		uniDocStr = NULL;
+		*/
 	}
 
 	// Wrap up pointers to the the QApp and main window and push them out
 	// to Python.
 	wrappedQApp = wrapQObject(qApp);
@@ -880,24 +927,26 @@
 	{
 		qDebug("Failed to wrap up QApp");
 		PyErr_Print();
 	}
 	// Push it into the module dict, stealing a ref in the process
-	PyDict_SetItemString(d, const_cast<char*>("qApp"), wrappedQApp);
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("qApp")), wrappedQApp);
 	Py_DECREF(wrappedQApp);
 	wrappedQApp = NULL;
 
 	wrappedMainWindow = wrapQObject(pl);
 	if (!wrappedMainWindow)
 	{
 		qDebug("Failed to wrap up ScMW");
 		PyErr_Print();
 	}
 	// Push it into the module dict, stealing a ref in the process
-	PyDict_SetItemString(d, const_cast<char*>("mainWindow"), wrappedMainWindow);
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("mainWindow")), wrappedMainWindow);
 	Py_DECREF(wrappedMainWindow);
 	wrappedMainWindow = NULL;
+	
+	return;
 }
 
 /*! HACK: this removes "warning: 'blah' defined but not used" compiler warnings
 with header files structure untouched (docstrings are kept near declarations)
 PV */
python3.patch (79,191 bytes)   
Sample_script_result.png (35,269 bytes)   
Sample_script_result.png (35,269 bytes)   

ale

2017-10-26 07:04

manager   ~0044589

i did not check thoroughly (nor run) the patch but:

- the "right" way to run scripts is by loading them from the menues... so that part should also work before moving to python3
- of course the standard script should also be tested, if they work with python3
- please do not comment out code, just delete it
- i'm not sure that creating a "legacy" macro is the way to go... can't you just modify the old one?
- moving to python3 will probably break many of the amateurish script the users have written for their own use
  (that's one of the reasons why i don't really care about keeping a compatibility layer between the old and new scripter... scripts will break anyway... but we will need a document explaining how to migrate from one scripter to the other...)

python3 is still not the default on most systems... but it's true that if people want to interface with python3 libraries, we will need to also make the upgrade.
and i'd like to support any action towards making python3 *the* version to use...

not an easy move, but why not?

u ltd.

2017-10-26 07:40

reporter   ~0044591

I must admit that the patch is not very clean. I simply wanted to test how difficult it may be to update the scripter.

I did only modify as few code places as possible and used as many macros as possible because I have no idea which is the right string representation (PyBytes or PyUnicode) in order to fit the character count of the text frames. (I came across this problem of different counting when implementing the first WiScri version - It took lots of my time, of Python code and of final performance to circumvent the problem)

Once this decision is taken, one can replace the actual code directly and clear the legacy macros.

u ltd.

2017-10-26 07:45

reporter   ~0044592

[I neither compiled or tested the actual patch but the patch on my website. Mainly I changed the comments, but functionally it should be the same]
Here I upload the test script and its result. (Which you already now from the screenshot)
test.script (482 bytes)
test.script.result (19,081 bytes)

u ltd.

2017-11-19 22:37

reporter   ~0044633

As I already wrote on 26th of October, I needed to have some decision on the Scribus internal encoding.

Now I've looked into the source and made some trials so I can write some more about the coding:
- The internal representation of the text is a QList of structs containing one QChar each. (sctext_shared.h)
- QChars usually have a width of 16 bit.
- When coping with larger chars (e. g. U+1D434 = "�" = 0xf09d90b4 = MATHEMATICAL ITALIC CAPITAL A) two subsequent QChars are occupied and automagically appear as one letter in the text frame.
- The counting is strict in QChars; bigger chars count as two chars for the API -> You can insert (with Python) other letters inbetween of the 2x16 bit chars which will make the piece of text look strange.


Python 3 support so far makes this:
* When fetching the text with python you get a byte string which seems to be UTF-8 compatible. As such the counting is incompatible for most special chars.
* When a Python-3-Unicode-String would be used, counting would be more compatible, but is not in case of these 2x16 bit chars because Python correctly counts them as 1 char.
* If the very last char is a 2x16 bit char it gets translated to a question mark (so something with the length of the strings is wrong in the patch proposed by me).
* A QChar which has an illegal value (that happens if you insert another letter inbetween a 2x16 bit char) are represented by an question mark as well. (I would have expected that the actual bytes from the QChar would be returned.)


-> Conclusion: It seems hardly to be possible to synchronize the Python <-> Scribus text counting. Maybe a QChar-oriented API could be added to the normal python functions?

u ltd.

2017-11-19 22:53

reporter   ~0044634

For illustration: how it looks by now.
Remark: The middle � in �i�i� is in a different font which cann't display this codepoint.
Scribus--Kursives_A.png (23,639 bytes)   
Scribus--Kursives_A.png (23,639 bytes)   

u ltd.

2017-12-07 10:32

reporter   ~0044719

Since I did not hear anything from you, I suggest following proceeding:

For fast access (e. g. if a script simply wants to search for a phrase or move text phrases) a new number-array-API is propagated (so every number in this array is on QChar in the scribus structures). As long as scribus works with QChars internally, there's no way around a new/additional API.


For the old API there are several variants:

Variant 1: Remove all indexed parts of the old API and only allow to insert at the beginning or at the end. [Not good because you take some functionality of scripts that don't depend on the user typed text frame content.]

Variant 2a: Keep API and translate everything to true Unicode, working best with Python 3 strings, but do not translate counts. This will make many users happy, but discriminates other users (writing languages with four-byte codepoints, e. g. Chinese).

Variant 2b: Keep API and translate everything to true Unicode, working best with Python 3 strings, but do not translate counts and insert an extra character phrase RLI + PDI in all returned strings at the positions 5, 15, 50, 150, 500, 1500, 5000, 15000, ... to achieve that people with max-two-byte-codepoint languages don't get used to a correct character count and therefore produce scripts not feasible for worldwide (so-to-speak for exact scripts they would use the new/additional array API).

Variant 3: Keep API and translate everything to true Unicode, working best with Python 3 strings. In order not to discriminate any user there will be an exact beginning-to-end character count translation, so when you say "I want to insert 'HELLO' at the 46th char in the text frame" then Scribus does not only count the QChars but also respects the double QChars in counting. That will be some programming work and will please the CPU vendors but is the most user-friendly variant.

Variant 4: Return Python Byte Strings. [Not good because counts are wrong anyway, the computational complexity in Scribus is not better than any of the alternative variants and the byte string is not directly usable for text in Python]

... Variant 5 ... Of course there is another variant: change the codepoint representation in Scribus. As the Python scripter API is facing similar problems now which must have had the text frame GUI + exporting routine + ... before this would be a fully integrated and most clean approach, but I'm in doubt that this will happen soon? At least it would take much efford because many components have to be reviewed then.





Forget about variants 1 and 4. I don't like variant 2a.

I personally would find it funny to proceed with variant 2b though I know this is the way to get unpopular very fast ;-) But maybe this unpopularity would be a trigger for variant 5 (= clean solution) which is better than variant 3 (= yet another workaround for a fundamental problem)

ale

2017-12-07 14:27

manager   ~0044720

personally, i prefer finishing my tries with a new scripter before thinking about porting the old scripter to python3...

if it works, the new scripter will be python3 only.

u ltd.

2017-12-07 15:14

reporter   ~0044723

Hm, but you have to consider these variants anyway in the new scripter.

How will the text be represented when you query a text frame with the new scripter? What Python data type will be returned?

william

2018-01-05 04:08

updater   ~0044810

Last edited: 2018-02-05 11:56

I am interested in getting Scribus to support python3.
I attached a new set of patches.
I started with u ltd.'s patches from the first comment.
I made a few changes so that it compiles with the current scribus svn (as of a few days ago) on Fedora 27 x86_64.
I updated it so that it can run external scripts and show the traceback if a script gets a python error.
It can now run the attached script that creates buttons using PyQt5 (when you check 'Run as Extension Script').

u ltd. did a great job working out the python3 initialization so that Scribus runs and that python scripts can use PyQt5.
I changed the patches so that they work for both python2 and 3.

To enable python3, run cmake with -DWANT_PYTHON3=1. I have attached a build script that can build with python2 and 3 from the same source tree.

I am hoping that this will help get the patches accepted because they can be applied without breaking Scribus for python2 and they will be more accessible for others who want to finish the python3 support.
As u ltd. said, the issues with unicode remain. I think that they are tractable once a decision is made, and the legacy macro is not a problem.
Also modules like PDFFile don't get loaded properly.
The link below has notes by the gnu coreutils maintainers on decisions that they took when adding unicode support. https://crashcourse.housegordon.org/coreutils-multibyte-support.html
Regards,
William

pyqt_tutl2.py (1,401 bytes)   
#!/usr/bin/env python

import sys

try:
    import scribus
except ImportError:
    print('This script can only be run as an extension script from Scribus')
    sys.exit(1)

from PyQt5 import Qt
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import pyqtSlot

class MyPushButton(QPushButton):
  def __init__(self, parent, number):
    super(QPushButton, self).__init__('button' + str(number), parent)
    self.setToolTip('This is example button ' + str(number))
    self.move(10 + 100 * (number-1), 10)
    self.clicked.connect(self.on_click)
    self.number = number

  @pyqtSlot()
  def on_click(self):
    print('PyQt5 click on button ' + str(self.number))

class App(QWidget):

  def __init__(self):
    super(App, self).__init__()
    self.title = 'PyQt5 button - pythonspot.com'
    self.left = 10
    self.top = 10
    self.width = 1000
    self.height = 200
    self.initUI()

  def initUI(self):
    self.setWindowTitle(self.title)

    button1 = MyPushButton(self, 1)
    button2 = MyPushButton(self, 2)
    button3 = MyPushButton(self, 3)
    self.width = 20 + 200 + button2.sizeHint().width()
    self.height = 20 + button1.sizeHint().height()
    self.setGeometry(self.left, self.top, self.width, self.height)
    self.show()

if __name__ == '__main__':
  # app = QApplication(sys.argv)
  ex = App()
  # sys.exit(app.exec_())
pyqt_tutl2.py (1,401 bytes)   

william

2018-01-05 19:20

updater   ~0044812

In objpdffile.cpp, PDFfile_init() sets scribus.file with PyObject *file = Legacy_PyString_FromString(tf.toLatin1());
This creates bytes in python3, and I think that we should create a unicode string with PyUnicode_FromString(tf.toUtf8());
https://docs.python.org/3/c-api/unicode.html has PyObject *PyUnicode_FromString(const char *u) "Create a Unicode object from a UTF-8 encoded null-terminated char buffer u."
Isn't that what we need?
Searching for Legacy_PyString_FromString shows that some calls use .toLatin1() and others use .toUtf8().
Even for python2 shouldn't it always use .toUtf8()? It looks like most of the uses of .toLatin1() are in objpdffile.cpp so could those be an oversight of the original author of that file?
Regards, William Bader, Director of Research and Development at SCS, http://www.newspapersystems.com

william

2018-01-05 22:12

updater   ~0044814

An updated patch that works better with strings.

jghali

2018-01-07 01:32

administrator   ~0044818

Last edited: 2018-01-07 02:04

>> Even for python2 shouldn't it always use .toUtf8()?

With Python 2, Legacy_PyString_FromString translates to PyString_FromString. Depending on where the string come from (QString, script), the encoding of the input C string is implementation or script defined. The encoding of a python script can be specified by user and does not need to be UTF-8 at all. With today Unices, C strings are usually UTF-8 encoded, however on Windows, C strings will usually use the local codepage encoding... which is not UTF-8 at all. So in general, with python 2, always using .toUtf8() would be incorrect.

In the case of PDFfile "file" member, the string can be specified by user. The problem with current implementation of PDFfile_setfile() is that we do not perform any check or enforce encoding of the input string. If we look at scribus_opendoc() in cmddoc.cpp, this function call PyArg_ParseTuple() with "es" and "utf-8" arguments to specifically retrieve an UTF-8 encoded string. That's what we should do in PDFfile_setfile() too. From that point we would have full control on PDFfile "file" encoding and could use Legacy_PyString_FromString(tf.toUtf8()) in PDFfile_init().

With python 3, it looks like PyUnicode_FromString(tf.toUtf8()) would be indeed a better choice.

One thing is also coming to my mind and makes me wonder if we should not make a more brutal switch to python 3. Given the diversity of distros, I fear indeed that giving python 2 and python 3 choice would create a situation where, given python 2 and 3 language differences, a same script would work on one distro and not on another. If we provide both choices, we have at least ensure that our sample scripts work in both cases.

william

2018-01-07 03:25

updater   ~0044819

>So in general, with python 2, always using .toUtf8() would be incorrect.

So for python2, the places that used .toLatin1() should continue that way, and python3 can use .toUtf8()?
I was thinking about making a Legacy_PyString_FromQString macro that would take care of the conversion.

I don't mind the compatibility macros, but if anyone does, maybe the prefix could be changed from Legacy_ to Scribus_ .

>same script would work on one distro and not on another

I haven't looked at the sample scripts yet because I am still trying to get scripts to work (the 'scribus' module is visible in the console window but not from external scripts).
I suspect that it should be possible to update the sample scripts so that they work with both 2.7 and 3. Last summer, I wrote a 2000 line python script that reads directories of xml files, parses them, and updates records in a postgresql database using psycopg2, parallelizing the work using a multiprocessing process queue. It works in both python2 and 3, without using future, and only one line (encoding a string) needed to test the python version. I think if that can work, it should be possible to make the sample scripts work.

u ltd.

2018-01-28 02:17

reporter  

don_t_call_initscribus.png (189,872 bytes)   
don_t_call_initscribus.png (189,872 bytes)   

u ltd.

2018-01-28 02:17

reporter   ~0044878

The solution is so simple! To get the initialized module, do not initialize it...

[OK, there's also another half of the truth. It's not that simple]

u ltd.

2018-01-28 02:44

reporter   ~0044879

Hm, I must admit that I still work on the 1.5.3 base (recompilation takes 1-2 hours and when I switch to 1.5.4 there may be several tries to successful build) so I don't know how to make proper diff for you.
Following has to be changed:
cmdvar.h: declare an additional bool argument "subinit" for initscribus();

scriptplugin.cpp: Replace m = PyImport_AddModule((char*)"scribus"); by following code:
    
#if !IS_PY3K
    subinit = false;
#endif
    if (!subinit)
        m = PyImport_AddModule((char*)"scribus");
    else
        m = PyImport_ImportModule((char*)"scribus");

scriptplugin.cpp:initPlugin(): call initscribus(ScCore->primaryMainWindow(), false);
scriptercore.cpp:slotRunScriptFile(): call initscribus(ScCore->primaryMainWindow(), true);
scriptercore.cpp:slotRunScript(): call initscribus(ScCore->primaryMainWindow(), false);


That's it. I changed several other things for debugging but I guess they aren't too interesting for you.


Overall reason for the non-availability of 'scribus' module methods (which william called scribus module visibility, but the module was there, it simply had no content) is that when you call PyImport_AddModule in a sub-instance of Python, the module seems to be reinitialized but the PyImport_AppendInittab hooks don't get called. (A behaviour which is not intuitive)

OK, so now for my personal needs following questions have to be answered:
- Does pdf export work? - YES!
- Can text frames be accessed and are counted like the actual codepoints? YES! (at least for the two-byte chars)
- How do autostart scripts work and are they affected by the module load - to be determined.
- Other questions which I will figure out when next day has begun (or the day after tomorrow).

u ltd.

2018-01-28 02:46

reporter   ~0044880

(Credits for pdf export go to william, I think as it must have been some string encoding issue.

william

2018-01-28 05:31

updater   ~0044881

>Following has to be changed:

Thank you for figuring that out.

>I don't know how to make proper diff for you.

I haven't had a chance to get back to it since the last patch I sent called scribus-python3-20180105-220717.pat
I think that the easiest is to work inside svn and make patches against a recent svn snapshot. It is probably not recommended use of svn, but I save my work by running
  svn diff > "$HOME/scribus-`date +%Y""%m""%d-%H%M%S`".pat
instead of committing it, and when necessary, I can delete the source tree, make a fresh svn snapshot, and reapply the patches.

For the compile times, I use ccache, and until about a year ago, Scribus was small enough that I could build it on a ram disk. My laptop has 4 cores, so I run 'make -j4'. I tried ninja instead of make, but it seemed to rebuild more files than necessary after small changes.

william

2018-02-06 04:19

updater   ~0044922

I saw the patches that you posted to the scribus list on Feb 5. They got line-wrapped in the email. Can you post them here?
To make something that works with the current SVN, can I compare them against my patches and then merge your new parts, which seem to involve the scriptercore disable_updates(), test_checkpoint(), enable_updates(), starting_script(), checkpoint(), finishing_script(), renameObject, and duplicateObject?

u ltd.

2018-02-06 07:37

reporter   ~0044924

You also need patch [0015131 Add fast & precise duplicate to core+scripter] scribus-20180205-095552-jonas-duplicate.patch

The naming of duplicateObject/duplicateObject_legacy maybe has to be revised.

I have the impression that for every small text change a complete redraw happens, which results in a four-line QPixmap error per redraw event. I would like to hinder this, but so far couldn't find a way. But the beginning to address this is the enable_/disable_update and checkpoint system. checkpoints get incremented by an arbitrary number for every action, and if the total number reaches 1000, a redraw is explicitely called.


If you have problems using this patch I'll post the combined version of all of my patches.
scribus-20180205-095552-jonas-scripterpart.patch (83,565 bytes)   
Index: CMakeLists.txt
===================================================================
--- CMakeLists.txt	(Revision 22369)
+++ CMakeLists.txt	(Arbeitskopie)
@@ -749,8 +749,14 @@
 #<< JPEG, TIFF
 
 #<< PYTHON
-#set(PythonLibs_FIND_VERSION 2)
-find_package(PythonLibs 2 REQUIRED)
+if (WANT_PYTHON3)
+	#set(PythonLibs_FIND_VERSION 3)
+	#find_package(PythonInterp 3)
+	find_package(PythonLibs 3 REQUIRED)
+else()
+	#set(PythonLibs_FIND_VERSION 2)
+	find_package(PythonLibs 2 REQUIRED)
+endif()
 if (PYTHON_LIBRARY)
 	message("Python Library Found OK")
 	set(HAVE_PYTHON 1)
Index: scribus/fonts/ftface.cpp
===================================================================
--- scribus/fonts/ftface.cpp	(Revision 22369)
+++ scribus/fonts/ftface.cpp	(Arbeitskopie)
@@ -346,7 +346,7 @@
 			glEncoding.glyphName = adobeGlyphName(charcode);
 		else
 			glEncoding.glyphName = QString(reinterpret_cast<char*>(buf));
-		glEncoding.toUnicode = QString().sprintf("%04X", charcode);
+		glEncoding.toUnicode = QString().sprintf("%04lX", charcode);
 		GList.insert(gindex, glEncoding);
 
 		charcode = FT_Get_Next_Char(face, charcode, &gindex );
@@ -379,7 +379,7 @@
 		ScFace::GlyphEncoding glEncoding;
 		glEncoding.charcode  = static_cast<ScFace::ucs4_type>(charcode);
 		glEncoding.glyphName = glyphname;
-		glEncoding.toUnicode = QString().sprintf("%04X", charcode);
+		glEncoding.toUnicode = QString().sprintf("%04lX", charcode);
 		if ((charcode == 0) && glyphname.startsWith("uni"))
 		{
 			QString uniHexStr = uniGlyphNameToUnicode(glyphname);
Index: scribus/fonts/scface_ttf.cpp
===================================================================
--- scribus/fonts/scface_ttf.cpp	(Revision 22369)
+++ scribus/fonts/scface_ttf.cpp	(Arbeitskopie)
@@ -94,7 +94,7 @@
 		ScFace::GlyphEncoding glEncoding;
 		glEncoding.charcode  = charcode;
 		glEncoding.glyphName = adobeGlyphName(charcode);
-		glEncoding.toUnicode = QString().sprintf("%04X", charcode);
+		glEncoding.toUnicode = QString().sprintf("%04lX", charcode);
 		GList.insert(gindex, glEncoding);
 		charcode = FT_Get_Next_Char(face, charcode, &gindex );
 	}
Index: scribus/plugins/scriptplugin/cmdannotations.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdannotations.cpp	(Revision 22369)
+++ scribus/plugins/scriptplugin/cmdannotations.cpp	(Arbeitskopie)
@@ -54,8 +54,8 @@
 
 			getLinkData(drv, a.Ziel(), a.Action());
 			const char path[] = "path";
-			PyObject *pathkey = PyString_FromString(path);
-			PyObject *pathvalue = PyString_FromString(a.Extern().toUtf8());
+			PyObject *pathkey = Legacy_PyString_FromString(path);
+			PyObject *pathvalue = Legacy_PyString_FromString(a.Extern().toUtf8());
 			PyDict_SetItem(drv, pathkey, pathvalue);
 			add_text_to_dict(drv, i);
 			PyObject *rv = Py_BuildValue("(sO)", name3, drv);
@@ -64,8 +64,8 @@
 		else if (atype == Annotation::Link && actype == Annotation::Action_URI)
 		{
 			const char uri[] = "uri";
-			PyObject *ukey = PyString_FromString(uri);
-			PyObject *uval = PyString_FromString(a.Extern().toUtf8());
+			PyObject *ukey = Legacy_PyString_FromString(uri);
+			PyObject *uval = Legacy_PyString_FromString(a.Extern().toUtf8());
 			PyDict_SetItem(drv, ukey, uval);
 			add_text_to_dict(drv, i);
 			char *name4= const_cast<char*>("Link URI");
@@ -138,12 +138,12 @@
 			};
 			if (icon >= 0 && icon < 9)
 			{
-				PyObject *iconkey = PyString_FromString("icon");
-				PyObject *iconvalue = PyString_FromString(icons[icon]);
+				PyObject *iconkey = Legacy_PyString_FromString("icon");
+				PyObject *iconvalue = Legacy_PyString_FromString(icons[icon]);
 				PyDict_SetItem(drv, iconkey, iconvalue);
 			}
 
-			PyObject *openkey = PyString_FromString("open");
+			PyObject *openkey = Legacy_PyString_FromString("open");
 			PyObject *open = Py_False;
 			if (a.IsAnOpen())
 				open = Py_True;
@@ -437,7 +437,7 @@
 			break;
 	}
 	
-	return PyString_FromString(m_doc->Items->at(i)->itemName().toUtf8());
+	return Legacy_PyString_FromString(m_doc->Items->at(i)->itemName().toUtf8());
 }
 
 
@@ -463,7 +463,7 @@
 	int x, y;
 
 	const char pagenum[] = "page";
-	PyObject *pagekey = PyString_FromString(pagenum);
+	PyObject *pagekey = Legacy_PyString_FromString(pagenum);
 	PyObject *pagevalue = PyInt_FromLong((long)page);
 	PyDict_SetItem(rv, pagekey, pagevalue);
 	
@@ -471,7 +471,7 @@
 
 	x = qsl[0].toInt();
 	const char x2[] = "x";
-	PyObject *xkey = PyString_FromString(x2);
+	PyObject *xkey = Legacy_PyString_FromString(x2);
 	PyObject *xvalue = PyInt_FromLong((long)x);
 	PyDict_SetItem(rv, xkey, xvalue);
 
@@ -478,7 +478,7 @@
 	int height =ScCore->primaryMainWindow()->doc->pageHeight();
 	y = height - qsl[1].toInt();
 	const char y2[] = "y";
-	PyObject *ykey = PyString_FromString(y2);
+	PyObject *ykey = Legacy_PyString_FromString(y2);
 	PyObject *yvalue = PyInt_FromLong((long)y);
 	PyDict_SetItem(rv, ykey, yvalue);
 
@@ -519,9 +519,9 @@
 static void add_text_to_dict(PyObject *drv, PageItem * i)
 {
 	const char text[] = "text";
-	PyObject *textkey = PyString_FromString(text);
+	PyObject *textkey = Legacy_PyString_FromString(text);
 	QString txt = i->itemText.text(0, i->itemText.length());
-	PyObject *textvalue = PyString_FromString(txt.toUtf8());
+	PyObject *textvalue = Legacy_PyString_FromString(txt.toUtf8());
 	PyDict_SetItem(drv, textkey, textvalue);
 
 	Annotation &a = i->annotation();
@@ -530,8 +530,8 @@
 	if (actype == Annotation::Action_JavaScript)
 	{
 		const char text[] = "javascript";
-		PyObject *jskey = PyString_FromString(text);
-		PyObject *jsvalue = PyString_FromString(i->annotation().Action().toUtf8());
+		PyObject *jskey = Legacy_PyString_FromString(text);
+		PyObject *jsvalue = Legacy_PyString_FromString(i->annotation().Action().toUtf8());
 		PyDict_SetItem(drv, jskey, jsvalue);
 	}
 
@@ -543,10 +543,10 @@
 			            "Named", NULL };
 
 	const char action[] = "action";
-	PyObject *akey = PyString_FromString(action);
+	PyObject *akey = Legacy_PyString_FromString(action);
 	if (actype > 10)
 		actype = 6;
-	PyObject *avalue = PyString_FromString(aactions[actype]);
+	PyObject *avalue = Legacy_PyString_FromString(aactions[actype]);
 	PyDict_SetItem(drv, akey, avalue);
 
 	int atype = a.Type();
@@ -553,7 +553,7 @@
 	if (atype == Annotation::Checkbox || atype == Annotation::RadioButton)
 	{
 		const char checked[] = "checked";
-		PyObject *checkkey = PyString_FromString(checked);
+		PyObject *checkkey = Legacy_PyString_FromString(checked);
 		PyObject *checkvalue = Py_False;
 		if (a.IsChk())
 			checkvalue = Py_True;
@@ -563,7 +563,7 @@
 	if (atype == Annotation::Combobox || atype == Annotation::Listbox)
 	{
 		const char editable[] = "editable";
-		PyObject *ekey = PyString_FromString(editable);
+		PyObject *ekey = Legacy_PyString_FromString(editable);
 
 		PyObject *edit = Py_False;
 		int result = Annotation::Flag_Edit & a.Flag();
Index: scribus/plugins/scriptplugin/cmdcell.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdcell.cpp	(Revision 22369)
+++ scribus/plugins/scriptplugin/cmdcell.cpp	(Arbeitskopie)
@@ -61,7 +61,7 @@
 		PyErr_SetString(PyExc_ValueError, QObject::tr("The cell %1,%2 does not exist in table", "python error").arg(row).arg(column).toLocal8Bit().constData());
 		return NULL;
 	}
-	return PyString_FromString(table->cellAt(row, column).styleName().toUtf8());
+	return Legacy_PyString_FromString(table->cellAt(row, column).styleName().toUtf8());
 }
 
 PyObject *scribus_setcellstyle(PyObject* /* self */, PyObject* args)
@@ -153,7 +153,7 @@
 		PyErr_SetString(PyExc_ValueError, QObject::tr("The cell %1,%2 does not exist in table", "python error").arg(row).arg(column).toLocal8Bit().constData());
 		return NULL;
 	}
-	return PyString_FromString(table->cellAt(row, column).fillColor().toUtf8());
+	return Legacy_PyString_FromString(table->cellAt(row, column).fillColor().toUtf8());
 }
 
 PyObject *scribus_setcellfillcolor(PyObject* /* self */, PyObject* args)
Index: scribus/plugins/scriptplugin/cmdcolor.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdcolor.cpp	(Revision 22369)
+++ scribus/plugins/scriptplugin/cmdcolor.cpp	(Arbeitskopie)
@@ -22,7 +22,7 @@
 	l = PyList_New(edc.count());
 	for (it = edc.begin(); it != edc.end(); ++it)
 	{
-		PyList_SetItem(l, cc, PyString_FromString(it.key().toUtf8()));
+		PyList_SetItem(l, cc, Legacy_PyString_FromString(it.key().toUtf8()));
 		cc++;
 	}
 	return l;
Index: scribus/plugins/scriptplugin/cmddialog.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmddialog.cpp	(Revision 22369)
+++ scribus/plugins/scriptplugin/cmddialog.cpp	(Arbeitskopie)
@@ -68,7 +68,7 @@
 										);
 //	QApplication::restoreOverrideCursor();
 	// FIXME: filename return unicode OK?
-	return PyString_FromString(fName.toUtf8());
+	return Legacy_PyString_FromString(fName.toUtf8());
 }
 
 PyObject *scribus_messdia(PyObject* /* self */, PyObject* args, PyObject* kw)
@@ -120,7 +120,7 @@
 										QLineEdit::Normal,
 										QString::fromUtf8(value));
 //	QApplication::restoreOverrideCursor();
-	return PyString_FromString(txt.toUtf8());
+	return Legacy_PyString_FromString(txt.toUtf8());
 }
 
 PyObject *scribus_newstyledialog(PyObject*, PyObject* args)
@@ -143,7 +143,7 @@
 		st.create(p);
 		d->redefineStyles(st, false);
 		ScCore->primaryMainWindow()->styleMgr()->setDoc(d);
-		return PyString_FromString(s.toUtf8());
+		return Legacy_PyString_FromString(s.toUtf8());
 	}
 	else
 		Py_RETURN_NONE;
Index: scribus/plugins/scriptplugin/cmddoc.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmddoc.cpp	(Revision 22369)
+++ scribus/plugins/scriptplugin/cmddoc.cpp	(Arbeitskopie)
@@ -197,9 +197,9 @@
 		return NULL;
 	if (! ScCore->primaryMainWindow()->doc->hasName)
 	{
-		return PyString_FromString("");
+		return Legacy_PyString_FromString("");
 	}
-	return PyString_FromString(ScCore->primaryMainWindow()->doc->DocName.toUtf8());
+	return Legacy_PyString_FromString(ScCore->primaryMainWindow()->doc->DocName.toUtf8());
 }
 
 PyObject *scribus_savedocas(PyObject* /* self */, PyObject* args)
@@ -318,7 +318,7 @@
 	int n = 0;
 	for ( ; it != itEnd; ++it )
 	{
-		PyList_SET_ITEM(names, n++, PyString_FromString(it.key().toUtf8().data()) );
+		PyList_SET_ITEM(names, n++, Legacy_PyString_FromString(it.key().toUtf8().data()) );
 	}
 	return names;
 }
@@ -403,7 +403,7 @@
 		PyErr_SetString(PyExc_IndexError, QObject::tr("Page number out of range: '%1'.","python error").arg(e+1).toLocal8Bit().constData());
 		return NULL;
 	}
-	return PyString_FromString(ScCore->primaryMainWindow()->doc->DocPages.at(e)->MPageNam.toUtf8());
+	return Legacy_PyString_FromString(ScCore->primaryMainWindow()->doc->DocPages.at(e)->MPageNam.toUtf8());
 }
 
 PyObject* scribus_applymasterpage(PyObject* /* self */, PyObject* args)
Index: scribus/plugins/scriptplugin/cmdgetprop.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdgetprop.cpp	(Revision 22369)
+++ scribus/plugins/scriptplugin/cmdgetprop.cpp	(Arbeitskopie)
@@ -44,7 +44,7 @@
 		result = "Multiple";
 	}
 
-	return PyString_FromString(result.toUtf8());
+	return Legacy_PyString_FromString(result.toUtf8());
 }
 
 PyObject *scribus_getfillcolor(PyObject* /* self */, PyObject* args)
@@ -55,7 +55,7 @@
 	if(!checkHaveDocument())
 		return NULL;
 	PageItem *i = GetUniqueItem(QString::fromUtf8(Name));
-	return i != NULL ? PyString_FromString(i->fillColor().toUtf8()) : NULL;
+	return i != NULL ? Legacy_PyString_FromString(i->fillColor().toUtf8()) : NULL;
 }
 
 PyObject *scribus_getfilltrans(PyObject* /* self */, PyObject* args)
@@ -91,7 +91,7 @@
 	it = GetUniqueItem(QString::fromUtf8(Name));
 	if (it == NULL)
 		return NULL;
-	return PyString_FromString(it->customLineStyle().toUtf8());
+	return Legacy_PyString_FromString(it->customLineStyle().toUtf8());
 }
 
 PyObject *scribus_getlinecolor(PyObject* /* self */, PyObject* args)
@@ -110,11 +110,11 @@
 		for (int b = 0; b < it->itemText.length(); ++b)
 		{
 			if (it->itemText.selected(b))
-				return PyString_FromString(it->itemText.charStyle(b).fillColor().toUtf8());
+				return Legacy_PyString_FromString(it->itemText.charStyle(b).fillColor().toUtf8());
 		}
 	}
 	else
-		return PyString_FromString(it->lineColor().toUtf8());
+		return Legacy_PyString_FromString(it->lineColor().toUtf8());
 	PyErr_SetString(NotFoundError, QObject::tr("Color not found - python error", "python error").toLocal8Bit().constData());
 	return NULL;
 }
@@ -250,7 +250,7 @@
 	if(!checkHaveDocument())
 		return NULL;
 	PageItem *i = GetUniqueItem(QString::fromUtf8(Name));
-	return i != NULL ? PyString_FromString(i->Pfile.toUtf8()) : NULL;
+	return i != NULL ? Legacy_PyString_FromString(i->Pfile.toUtf8()) : NULL;
 }
 
 PyObject *scribus_getposi(PyObject* /* self */, PyObject* args)
@@ -338,13 +338,13 @@
 			{
 				if (ScCore->primaryMainWindow()->doc->Items->at(lam)->itemType() == typ)
 				{
-					PyList_SetItem(l, counter2, PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(lam)->itemName().toUtf8()));
+					PyList_SetItem(l, counter2, Legacy_PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(lam)->itemName().toUtf8()));
 					counter2++;
 				}
 			}
 			else
 			{
-				PyList_SetItem(l, counter2, PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(lam)->itemName().toUtf8()));
+				PyList_SetItem(l, counter2, Legacy_PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(lam)->itemName().toUtf8()));
 				counter2++;
 			}
 		}
Index: scribus/plugins/scriptplugin/cmdgetsetprop.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdgetsetprop.cpp	(Revision 22369)
+++ scribus/plugins/scriptplugin/cmdgetsetprop.cpp	(Arbeitskopie)
@@ -88,7 +88,7 @@
 		PyErr_SetString(PyExc_KeyError, QObject::tr("Property not found").toLocal8Bit().constData());
 		return NULL;
 	}
-	return PyString_FromString(type);
+	return Legacy_PyString_FromString(type);
 }
 
 PyObject* convert_QStringList_to_PyListObject(QStringList& origlist)
@@ -98,7 +98,7 @@
 		return NULL;
 
 	for ( QStringList::Iterator it = origlist.begin(); it != origlist.end(); ++it )
-		if (PyList_Append(resultList, PyString_FromString((*it).toUtf8().data())) == -1)
+		if (PyList_Append(resultList, Legacy_PyString_FromString((*it).toUtf8().data())) == -1)
 			return NULL;
 
 	return resultList;
@@ -289,9 +289,9 @@
 		resultobj = PyBool_FromLong(prop.toBool());
 	// STRING TYPES
 	else if (prop.type() == QVariant::ByteArray)
-		resultobj = PyString_FromString(prop.toByteArray().data());
+		resultobj = Legacy_PyString_FromString(prop.toByteArray().data());
 	else if (prop.type() == QVariant::String)
-		resultobj = PyString_FromString(prop.toString().toUtf8().data());
+		resultobj = Legacy_PyString_FromString(prop.toString().toUtf8().data());
 	// HIGHER ORDER TYPES
 	else if (prop.type() == QVariant::Point)
 	{
Index: scribus/plugins/scriptplugin/cmdmani.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdmani.cpp	(Revision 22369)
+++ scribus/plugins/scriptplugin/cmdmani.cpp	(Arbeitskopie)
@@ -406,7 +406,7 @@
 	finalSelection=0;
 	delete tempSelection;
 	
-	return (group ? PyString_FromString(group->itemName().toUtf8()) : NULL);
+	return (group ? Legacy_PyString_FromString(group->itemName().toUtf8()) : NULL);
 }
 
 PyObject *scribus_ungroupobj(PyObject* /* self */, PyObject* args)
@@ -464,10 +464,10 @@
 	if(!checkHaveDocument())
 		return NULL;
 	if ((i < static_cast<int>(ScCore->primaryMainWindow()->doc->m_Selection->count())) && (i > -1))
-		return PyString_FromString(ScCore->primaryMainWindow()->doc->m_Selection->itemAt(i)->itemName().toUtf8());
+		return Legacy_PyString_FromString(ScCore->primaryMainWindow()->doc->m_Selection->itemAt(i)->itemName().toUtf8());
 	else
 		// FIXME: Should probably return None if no selection?
-		return PyString_FromString("");
+		return Legacy_PyString_FromString("");
 }
 
 PyObject *scribus_selcount(PyObject* /* self */)
Index: scribus/plugins/scriptplugin/cmdmisc.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdmisc.cpp	(Revision 22369)
+++ scribus/plugins/scriptplugin/cmdmisc.cpp	(Arbeitskopie)
@@ -49,7 +49,7 @@
 	{
 		if (it.current().usable())
 		{
-			PyList_SetItem(l, cc, PyString_FromString(it.currentKey().toUtf8()));
+			PyList_SetItem(l, cc, Legacy_PyString_FromString(it.currentKey().toUtf8()));
 			cc++;
 		}
 	}
@@ -128,7 +128,7 @@
 		int bufferSize = buffer.size();
 		buffer.close();
 		// Now make a Python string from the data we generated
-		PyObject* stringPython = PyString_FromStringAndSize(buffer_string,bufferSize);
+		PyObject* stringPython = Legacy_PyBytes_FromStringAndSize(buffer_string,bufferSize);
 		// Return even if the result is NULL (error) since an exception will have been
 		// set in that case.
 		return stringPython;
@@ -157,7 +157,7 @@
 	PyObject *l;
 	l = PyList_New(ScCore->primaryMainWindow()->doc->Layers.count());
 	for (int lam=0; lam < ScCore->primaryMainWindow()->doc->Layers.count(); lam++)
-		PyList_SetItem(l, lam, PyString_FromString(ScCore->primaryMainWindow()->doc->Layers[lam].Name.toUtf8()));
+		PyList_SetItem(l, lam, Legacy_PyString_FromString(ScCore->primaryMainWindow()->doc->Layers[lam].Name.toUtf8()));
 	return l;
 }
 
@@ -190,7 +190,7 @@
 {
 	if(!checkHaveDocument())
 		return NULL;
-	return PyString_FromString(ScCore->primaryMainWindow()->doc->activeLayerName().toUtf8());
+	return Legacy_PyString_FromString(ScCore->primaryMainWindow()->doc->activeLayerName().toUtf8());
 }
 
 PyObject *scribus_senttolayer(PyObject* /* self */, PyObject* args)
@@ -761,7 +761,7 @@
 
 PyObject *scribus_getlanguage(PyObject* /* self */)
 {
-	return PyString_FromString(ScCore->getGuiLanguage().toUtf8());
+	return Legacy_PyString_FromString(ScCore->getGuiLanguage().toUtf8());
 }
 
 /*! 04.01.2007 : Joachim Neu : Moves item selection to front. */
Index: scribus/third_party/fparser/fparser.cc
===================================================================
--- scribus/third_party/fparser/fparser.cc	(Revision 22369)
+++ scribus/third_party/fparser/fparser.cc	(Arbeitskopie)
@@ -1625,9 +1625,11 @@
               {
                 default:
                 case '+':
-                    if(!is_unary) data->ByteCode.push_back(cAdd); break;
+                    if(!is_unary) data->ByteCode.push_back(cAdd);
+                    break;
                 case '-':
-                    data->ByteCode.push_back(is_unary ? cNeg : cSub); break;
+                    data->ByteCode.push_back(is_unary ? cNeg : cSub);
+                    break;
               }
         }
         --StackPtr;
Index: scribus/plugins/scriptplugin/objimageexport.cpp
===================================================================
--- scribus/plugins/scriptplugin/objimageexport.cpp	(Revision 22369)
+++ scribus/plugins/scriptplugin/objimageexport.cpp	(Arbeitskopie)
@@ -33,7 +33,7 @@
 	Py_XDECREF(self->name);
 	Py_XDECREF(self->type);
 	Py_XDECREF(self->allTypes);
-	self->ob_type->tp_free((PyObject *)self);
+	Py_TYPE(self)->tp_free((PyObject *)self);
 }
 
 static PyObject * ImageExport_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
@@ -44,8 +44,8 @@
 	ImageExport *self;
 	self = (ImageExport *)type->tp_alloc(type, 0);
 	if (self != NULL) {
-		self->name = PyString_FromString("ImageExport.png");
-		self->type = PyString_FromString("PNG");
+		self->name = Legacy_PyString_FromString("ImageExport.png");
+		self->type = Legacy_PyString_FromString("PNG");
 		self->allTypes = PyList_New(0);
 		self->dpi = 72;
 		self->scale = 100;
@@ -119,7 +119,7 @@
 	l = PyList_New(list.count());
 	for (QList<QByteArray>::Iterator it = list.begin(); it != list.end(); ++it)
 	{
-		PyList_SetItem(l, pos, PyString_FromString(QString((*it)).toLatin1().constData()));
+		PyList_SetItem(l, pos, Legacy_PyString_FromString(QString((*it)).toLatin1().constData()));
 		++pos;
 	}
 	return l;
@@ -204,10 +204,15 @@
 
 PyTypeObject ImageExport_Type = {
 	PyObject_HEAD_INIT(NULL)   // PyObject_VAR_HEAD
+#if !IS_PY3K
 	0,
+#endif
 	const_cast<char*>("scribus.ImageExport"), // char *tp_name; /* For printing, in format "<module>.<name>" */
 	sizeof(ImageExport),   // int tp_basicsize, /* For allocation */
 	0,  // int tp_itemsize; /* For allocation */
+
+	/* Methods to implement standard operations */
+
 	(destructor) ImageExport_dealloc, //	 destructor tp_dealloc;
 	0, //	 printfunc tp_print;
 	0, //	 getattrfunc tp_getattr;
@@ -214,23 +219,54 @@
 	0, //	 setattrfunc tp_setattr;
 	0, //	 cmpfunc tp_compare;
 	0, //	 reprfunc tp_repr;
+
+	/* Method suites for standard classes */
+
 	0, //	 PyNumberMethods *tp_as_number;
 	0, //	 PySequenceMethods *tp_as_sequence;
 	0, //	 PyMappingMethods *tp_as_mapping;
+
+	/* More standard operations (here for binary compatibility) */
+
 	0, //	 hashfunc tp_hash;
 	0, //	 ternaryfunc tp_call;
 	0, //	 reprfunc tp_str;
 	0, //	 getattrofunc tp_getattro;
 	0, //	 setattrofunc tp_setattro;
+
+	/* Functions to access object as input/output buffer */
+
 	0, //	 PyBufferProcs *tp_as_buffer;
+
+	/* Flags to define presence of optional/expanded features */
+
 	Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,	// long tp_flags;
+
 	imgexp__doc__, // char *tp_doc; /* Documentation string */
+
+	/* traverse all accessible objects, assigned in 2.0 */
+
 	0, //	 traverseproc tp_traverse;
+
+	/* delete references to contained objects */
+
 	0, //	 inquiry tp_clear;
+
+	/* rich comparisons, assigned in 2.1 */
+
 	0, //	 richcmpfunc tp_richcompare;
+
+	/* weak reference enabler */
+
 	0, //	 long tp_weaklistoffset;
+
+	/* Iterators, added in 2.2 */
+
 	0, //	 getiterfunc tp_iter;
 	0, //	 iternextfunc tp_iternext;
+
+	/* Attribute descriptor and subclassing stuff */
+
 	ImageExport_methods, //	 struct PyMethodDef *tp_methods;
 	ImageExport_members, //	 struct PyMemberDef *tp_members;
 	ImageExport_getseters, //	 struct PyGetSetDef *tp_getset;
@@ -251,6 +287,15 @@
 	0, //	 PyObject *tp_weaklist;
 	0, //	 destructor tp_del;
 
+#if IS_PY3K || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION >= 6)
+	/* Type attribute cache version tag. Added in version 2.6 */
+	0, //	 unsigned int tp_version_tag;
+#endif
+
+#if IS_PY3K
+	0, //	 destructor tp_finalize;
+#endif
+	
 #ifdef COUNT_ALLOCS
 	/* these must be last and never explicitly initialized */
 	//	int tp_allocs;
Index: scribus/plugins/scriptplugin/objpdffile.cpp
===================================================================
--- scribus/plugins/scriptplugin/objpdffile.cpp	(Revision 22369)
+++ scribus/plugins/scriptplugin/objpdffile.cpp	(Arbeitskopie)
@@ -135,7 +135,7 @@
 	Py_XDECREF(self->info);
 	Py_XDECREF(self->rotateDeg);
 	Py_XDECREF(self->openAction);
-	self->ob_type->tp_free((PyObject *)self);
+	Py_TYPE(self)->tp_free((PyObject *)self);
 }
 
 static PyObject * PDFfile_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
@@ -150,7 +150,7 @@
 	self = (PDFfile *)type->tp_alloc(type, 0);
 	if (self) {
 // set file attribute
-		self->file = PyString_FromString("");
+		self->file = Legacy_PyString_FromString("");
 		if (!self->file) {
 			Py_DECREF(self);
 			return NULL;
@@ -239,13 +239,13 @@
 			return NULL;
 		}
 // set owner attribute
-		self->owner = PyString_FromString("");
+		self->owner = Legacy_PyString_FromString("");
 		if (!self->owner){
 			Py_DECREF(self);
 			return NULL;
 		}
 // set user attribute
-		self->user = PyString_FromString("");
+		self->user = Legacy_PyString_FromString("");
 		if (!self->user){
 			Py_DECREF(self);
 			return NULL;
@@ -269,22 +269,22 @@
 		self->intents = 0; // int - 0 - ?
 		self->intenti = 0; // int - 0 - ?
 		self->noembicc = 0; // bool
-		self->solidpr = PyString_FromString("");
+		self->solidpr = Legacy_PyString_FromString("");
 		if (!self->solidpr){
 			Py_DECREF(self);
 			return NULL;
 		}
-		self->imagepr = PyString_FromString("");
+		self->imagepr = Legacy_PyString_FromString("");
 		if (!self->imagepr){
 			Py_DECREF(self);
 			return NULL;
 		}
-		self->printprofc = PyString_FromString("");
+		self->printprofc = Legacy_PyString_FromString("");
 		if (!self->printprofc){
 			Py_DECREF(self);
 			return NULL;
 		}
-		self->info = PyString_FromString("");
+		self->info = Legacy_PyString_FromString("");
 		if (!self->info){
 			Py_DECREF(self);
 			return NULL;
@@ -313,7 +313,7 @@
 		self->hideToolBar = 0;
 		self->hideMenuBar = 0;
 		self->fitWindow = 0;
-		self->openAction = PyString_FromString("");
+		self->openAction = Legacy_PyString_FromString("");
 		if (!self->openAction){
 			Py_DECREF(self);
 			return NULL;
@@ -339,7 +339,7 @@
 		tf = fi.path()+"/"+fi.baseName()+".pdf";
 	}
 	PyObject *file = NULL;
-	file = PyString_FromString(tf.toLatin1());
+	file = Legacy_PyString_FromString(tf.toUtf8());
 	if (file){
 		Py_DECREF(self->file);
 		self->file = file;
@@ -375,7 +375,7 @@
 	{
 		QString fontName = tmpEm.at(i);
 		PyObject *tmp= NULL;
-		tmp = PyString_FromString(fontName.toLatin1());
+		tmp = Legacy_PyString_FromString(fontName.toUtf8());
 		if (tmp) {
 			PyList_Append(self->fonts, tmp);
 // do i need Py_DECREF(tmp) here?
@@ -401,7 +401,7 @@
 	for (int fe = 0; fe < pdfOptions.SubsetList.count(); ++fe)
 	{
 		PyObject *tmp= NULL;
-		tmp = PyString_FromString(pdfOptions.SubsetList[fe].toLatin1().data());
+		tmp = Legacy_PyString_FromString(pdfOptions.SubsetList[fe].toUtf8());
 		if (tmp) {
 			PyList_Append(self->subsetList, tmp);
 			Py_DECREF(tmp);
@@ -536,7 +536,7 @@
 	QMap<QString,LPIData>::Iterator it = pdfOptions.LPISettings.begin();
 	while (it != pdfOptions.LPISettings.end()) {
 		PyObject *tmp;
-		tmp = Py_BuildValue(const_cast<char*>("[siii]"), it.key().toLatin1().constData(), it.value().Frequency, it.value().Angle, it.value().SpotFunc);
+		tmp = Py_BuildValue(const_cast<char*>("[siii]"), it.key().toUtf8().constData(), it.value().Frequency, it.value().Angle, it.value().SpotFunc);
 		if (!tmp) {
 			PyErr_SetString(PyExc_SystemError, "Can not initialize 'lpival' attribute");
 			return -1;
@@ -549,7 +549,7 @@
 	self->lpival = lpival;
 // set owner's password
 	PyObject *owner = NULL;
-	owner = PyString_FromString(pdfOptions.PassOwner.toLatin1());
+	owner = Legacy_PyString_FromString(pdfOptions.PassOwner.toUtf8());
 	if (owner){
 		Py_DECREF(self->owner);
 		self->owner = owner;
@@ -559,7 +559,7 @@
 	}
 // set user'a password
 	PyObject *user = NULL;
-	user = PyString_FromString(pdfOptions.PassUser.toLatin1());
+	user = Legacy_PyString_FromString(pdfOptions.PassUser.toUtf8());
 	if (user){
 		Py_DECREF(self->user);
 		self->user = user;
@@ -589,7 +589,7 @@
 	if (!ScCore->InputProfiles.contains(tp))
 		tp = currentDoc->cmsSettings().DefaultSolidColorRGBProfile;
 	PyObject *solidpr = NULL;
-	solidpr = PyString_FromString(tp.toLatin1());
+	solidpr = Legacy_PyString_FromString(tp.toUtf8());
 	if (solidpr){
 		Py_DECREF(self->solidpr);
 		self->solidpr = solidpr;
@@ -601,7 +601,7 @@
 	if (!ScCore->InputProfiles.contains(tp2))
 		tp2 = currentDoc->cmsSettings().DefaultSolidColorRGBProfile;
 	PyObject *imagepr = NULL;
-	imagepr = PyString_FromString(tp2.toLatin1());
+	imagepr = Legacy_PyString_FromString(tp2.toUtf8());
 	if (imagepr){
 		Py_DECREF(self->imagepr);
 		self->imagepr = imagepr;
@@ -613,7 +613,7 @@
 	if (!ScCore->PDFXProfiles.contains(tp3))
 		tp3 = currentDoc->cmsSettings().DefaultPrinterProfile;
 	PyObject *printprofc = NULL;
-	printprofc = PyString_FromString(tp3.toLatin1());
+	printprofc = Legacy_PyString_FromString(tp3.toUtf8());
 	if (printprofc){
 		Py_DECREF(self->printprofc);
 		self->printprofc = printprofc;
@@ -623,7 +623,7 @@
 	}
 	QString tinfo = pdfOptions.Info;
 	PyObject *info = NULL;
-	info = PyString_FromString(tinfo.toLatin1());
+	info = Legacy_PyString_FromString(tinfo.toUtf8());
 	if (info){
 		Py_DECREF(self->info);
 		self->info = info;
@@ -661,7 +661,7 @@
 	self->fitWindow = pdfOptions.fitWindow; // bool
 
 	PyObject *openAction = NULL;
-	openAction = PyString_FromString(pdfOptions.openAction.toLatin1().data());
+	openAction = Legacy_PyString_FromString(pdfOptions.openAction.toUtf8().data());
 	if (openAction){
 		Py_DECREF(self->openAction);
 		self->openAction = openAction;
@@ -1528,7 +1528,7 @@
 		fn  = "Cannot write the File: " + fn;
 		if (!errorMessage.isEmpty())
 			fn += QString("\n%1").arg(errorMessage);
-		PyErr_SetString(PyExc_SystemError, fn.toLatin1());
+		PyErr_SetString(PyExc_SystemError, fn.toUtf8());
 	}
 
 	if (self->useDocBleeds)
@@ -1546,7 +1546,9 @@
 
 PyTypeObject PDFfile_Type = {
 	PyObject_HEAD_INIT(NULL) // PyObject_VAR_HEAD
-	0,		      //
+#if !IS_PY3K
+	0,
+#endif
 	const_cast<char*>("scribus.PDFfile"), // char *tp_name; /* For printing, in format "<module>.<name>" */
 	sizeof(PDFfile),     // int tp_basicsize, /* For allocation */
 	0,		    // int tp_itemsize; /* For allocation */
@@ -1575,9 +1577,11 @@
 	0, //     setattrofunc tp_setattro;
 
 	/* Functions to access object as input/output buffer */
+
 	0, //     PyBufferProcs *tp_as_buffer;
 
 	/* Flags to define presence of optional/expanded features */
+
 	Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,    // long tp_flags;
 
 	pdffile__doc__,      // char *tp_doc; /* Documentation string */
@@ -1622,6 +1626,15 @@
 	0, //     PyObject *tp_weaklist;
 	0, //     destructor tp_del;
 
+#if IS_PY3K || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION >= 6)
+	/* Type attribute cache version tag. Added in version 2.6 */
+	0, //	 unsigned int tp_version_tag;
+#endif
+
+#if IS_PY3K
+	0, //	 destructor tp_finalize;
+#endif
+	
 #ifdef COUNT_ALLOCS
 	/* these must be last and never explicitly initialized */
 	//    int tp_allocs;
Index: scribus/plugins/scriptplugin/objprinter.cpp
===================================================================
--- scribus/plugins/scriptplugin/objprinter.cpp	(Revision 22369)
+++ scribus/plugins/scriptplugin/objprinter.cpp	(Arbeitskopie)
@@ -59,7 +59,7 @@
 	Py_XDECREF(self->cmd);
 	Py_XDECREF(self->pages);
 	Py_XDECREF(self->separation);
-	self->ob_type->tp_free((PyObject *)self);
+	Py_TYPE(self)->tp_free((PyObject *)self);
 }
 
 static PyObject * Printer_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
@@ -79,19 +79,19 @@
 			return NULL;
 		}
 // set printer attribute
-		self->printer = PyString_FromString("");
+		self->printer = Legacy_PyString_FromString("");
 		if (self->printer == NULL){
 			Py_DECREF(self);
 			return NULL;
 		}
 // set file attribute
-		self->file = PyString_FromString("");
+		self->file = Legacy_PyString_FromString("");
 		if (self->file == NULL){
 			Py_DECREF(self);
 			return NULL;
 		}
 // set cmd attribute
-		self->cmd = PyString_FromString("");
+		self->cmd = Legacy_PyString_FromString("");
 		if (self->cmd == NULL){
 			Py_DECREF(self);
 			return NULL;
@@ -103,7 +103,7 @@
 			return NULL;
 		}
 // set separation attribute
-		self->separation = PyString_FromString("No");
+		self->separation = Legacy_PyString_FromString("No");
 		if (self->separation == NULL){
 			Py_DECREF(self);
 			return NULL;
@@ -144,18 +144,18 @@
 		QString prn = printers[i];
 		if (prn.isEmpty())
 			continue;
-		PyObject *tmppr = PyString_FromString(prn.toLocal8Bit().constData());
+		PyObject *tmppr = Legacy_PyString_FromString(prn.toLocal8Bit().constData());
 		if (tmppr){
 			PyList_Append(self->allPrinters, tmppr);
 			Py_DECREF(tmppr);
 		}
 	}
-	PyObject *tmp2 = PyString_FromString("File");
+	PyObject *tmp2 = Legacy_PyString_FromString("File");
 	PyList_Append(self->allPrinters, tmp2);
 	Py_DECREF(tmp2);
 // as defaut set to print into file
 	PyObject *printer = NULL;
-	printer = PyString_FromString("File");
+	printer = Legacy_PyString_FromString("File");
 	if (printer){
 		Py_DECREF(self->printer);
 		self->printer = printer;
@@ -167,7 +167,7 @@
 		tf = fi.path()+"/"+fi.baseName()+".pdf";
 	}
 	PyObject *file = NULL;
-	file = PyString_FromString(tf.toLatin1());
+	file = Legacy_PyString_FromString(tf.toLatin1());
 	if (file){
 		Py_DECREF(self->file);
 		self->file = file;
@@ -177,7 +177,7 @@
 	}
 // alternative printer commands default to ""
 	PyObject *cmd = NULL;
-	cmd = PyString_FromString("");
+	cmd = Legacy_PyString_FromString("");
 	if (cmd){
 		Py_DECREF(self->cmd);
 		self->cmd = cmd;
@@ -199,7 +199,7 @@
 	}
 // do not print separation
 	PyObject *separation = NULL;
-	separation = PyString_FromString("No");
+	separation = Legacy_PyString_FromString("No");
 	if (separation){
 		Py_DECREF(self->separation);
 		self->separation = separation;
@@ -514,7 +514,9 @@
 
 PyTypeObject Printer_Type = {
 	PyObject_HEAD_INIT(NULL)   // PyObject_VAR_HEAD
-	0,			 //
+#if !IS_PY3K
+	0,
+#endif
 	const_cast<char*>("scribus.Printer"), // char *tp_name; /* For printing, in format "<module>.<name>" */
 	sizeof(Printer),   // int tp_basicsize, /* For allocation */
 	0,		       // int tp_itemsize; /* For allocation */
@@ -543,9 +545,11 @@
 	0, //     setattrofunc tp_setattro;
 
 	/* Functions to access object as input/output buffer */
+
 	0, //     PyBufferProcs *tp_as_buffer;
 
 	/* Flags to define presence of optional/expanded features */
+
 	Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,    // long tp_flags;
 
 	printer__doc__,      // char *tp_doc; /* Documentation string */
@@ -590,6 +594,15 @@
 	0, //     PyObject *tp_weaklist;
 	0, //     destructor tp_del;
 
+#if IS_PY3K || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION >= 6)
+	/* Type attribute cache version tag. Added in version 2.6 */
+	0, //	 unsigned int tp_version_tag;
+#endif
+
+#if IS_PY3K
+	0, //	 destructor tp_finalize;
+#endif
+	
 #ifdef COUNT_ALLOCS
 	/* these must be last and never explicitly initialized */
 	//    int tp_allocs;
Index: scribus/plugins/scriptplugin/scriptercore.cpp
===================================================================
--- scribus/plugins/scriptplugin/scriptercore.cpp	(Revision 22369)
+++ scribus/plugins/scriptplugin/scriptercore.cpp	(Arbeitskopie)
@@ -73,6 +73,10 @@
 
 	QObject::connect(ScQApp, SIGNAL(appStarted()) , this, SLOT(runStartupScript()) );
 	QObject::connect(ScQApp, SIGNAL(appStarted()) , this, SLOT(slotRunPythonScript()) );
+	
+	
+	num_main_interpreters = 0;
+	num_side_interpreters = 0;
 }
 
 ScripterCore::~ScripterCore()
@@ -240,6 +244,7 @@
 	if (ScCore->primaryMainWindow()->scriptIsRunning())
 		return;
 	disableMainWindowMenu();
+	emit starting_script(inMainInterpreter);
 
 	PyThreadState *state = NULL;
 	QFileInfo fi(fileName);
@@ -259,7 +264,7 @@
 		global_state = PyThreadState_Get();
 		state = Py_NewInterpreter();
 		// Init the scripter module in the sub-interpreter
-		initscribus(ScCore->primaryMainWindow());
+		initscribus(ScCore->primaryMainWindow(), true);
 	}
 
 	// Make sure sys.argv[0] is the path to the script
@@ -266,18 +271,35 @@
 	arguments.prepend(na.data());
 	//convert arguments (QListString) to char** for Python bridge
 	/* typically arguments == ['path/to/script.py','--argument1','valueforarg1','--flag']*/
+#if IS_PY3K
+	wchar_t **comm = new wchar_t*[arguments.size()];
+#else
 	char **comm = new char*[arguments.size()];
+#endif
 	for (int i = 0; i < arguments.size(); i++)
 	{
 		QByteArray localStr = arguments.at(i).toLocal8Bit();
+#if IS_PY3K
+		char * tmp = new char[localStr.size() + 1];
+		tmp[localStr.size()] = 0;
+		strncpy(tmp, localStr.data(), localStr.size());
+		comm[i] = Py_DecodeLocale(tmp, NULL);
+		delete[] tmp;
+#else
 		comm[i] = new char[localStr.size() + 1]; //+1 to allow adding '\0'. may be useless, don't know how to check.
 		comm[i][localStr.size()] = 0;
 		strncpy(comm[i], localStr.data(), localStr.size());
+#endif
 	}
 	PySys_SetArgv(arguments.size(), comm);
 
-	for (int i = 0; i < arguments.size(); i++)
+	for (int i = 0; i < arguments.size(); i++) {
+#if IS_PY3K
+		PyMem_RawFree(comm[i]);
+#else
 		delete[] comm[i];
+#endif
+	}
 	delete[] comm;
 	
 	// call python script
@@ -294,7 +316,11 @@
 		// Build the Python code to run the script
 		//QString cm = QString("from __future__ import division\n"); removed due #5252 PV
 		QString cm = QString("import sys\n");
+#if IS_PY3K
+		cm        += QString("import io\n");
+#else
 		cm        += QString("import cStringIO\n");
+#endif
 		/* Implementation of the help() in pydoc.py reads some OS variables
 		 * for output settings. I use ugly hack to stop freezing calling help()
 		 * in script. pv. */
@@ -302,7 +328,11 @@
 		cm        += QString("sys.path[0] = \"%1\"\n").arg(escapedAbsPath);
 		// Replace sys.stdin with a dummy StringIO that always returns
 		// "" for read
+#if IS_PY3K
+		cm        += QString("sys.stdin = io.StringIO()\n");
+#else
 		cm        += QString("sys.stdin = cStringIO.StringIO()\n");
+#endif
 		// tell the script if it's running in the main intepreter or a subinterpreter
 		cm        += QString("import scribus\n");
 		if (inMainInterpreter)
@@ -310,7 +340,11 @@
 		else
 			cm+= QString("scribus.mainInterpreter = False\n");
 		cm        += QString("try:\n");
+#if IS_PY3K
+		cm        += QString("    exec(open(\"%1\").read())\n").arg(escapedFileName);
+#else
 		cm        += QString("    execfile(\"%1\")\n").arg(escapedFileName);
+#endif
 		cm        += QString("except SystemExit:\n");
 		cm        += QString("    pass\n");
 		// Capture the text of any other exception that's raised by the interpreter
@@ -344,7 +378,11 @@
 			}
 			else if (ScCore->usingGUI())
 			{
+#if IS_PY3K
+				QString errorMsg = PyUnicode_AsUTF8(errorMsgPyStr);
+#else
 				QString errorMsg = PyString_AsString(errorMsgPyStr);
+#endif
 				// Display a dialog to the user with the exception
 				QClipboard *cp = QApplication::clipboard();
 				cp->setText(errorMsg);
@@ -372,7 +410,8 @@
 		qApp->restoreOverrideCursor();
 		ScCore->primaryMainWindow()->setScriptRunning(false);
 	}
-
+	
+	emit finishing_script(inMainInterpreter);
 	enableMainWindowMenu();
 }
 
@@ -392,6 +431,7 @@
 	if (ScCore->primaryMainWindow()->scriptIsRunning())
 		return;
 	disableMainWindowMenu();
+	emit starting_script(true);
 
 	ScCore->primaryMainWindow()->propertiesPalette->unsetDoc();
 	ScCore->primaryMainWindow()->textPalette->unsetDoc();
@@ -402,7 +442,7 @@
 	cm = "# -*- coding: utf8 -*- \n";
 	if (PyThreadState_Get() != NULL)
 	{
-		initscribus(ScCore->primaryMainWindow());
+		initscribus(ScCore->primaryMainWindow(), false);
 		/* HACK: following loop handles all input line by line.
 		It *should* use I.C. because of docstrings etc. I.I. cannot
 		handle docstrings right.
@@ -411,8 +451,14 @@
 		works fine in plain Python. Not here. WTF? */
 		cm += (
 				"try:\n"
+				"    print('Started script console.') # Outputs to stdout of scribus\n"
+#if IS_PY3K
+				"    import io\n"
+				"    scribus._bu = io.StringIO()\n"
+#else
 				"    import cStringIO\n"
 				"    scribus._bu = cStringIO.StringIO()\n"
+#endif
 				"    sys.stdout = scribus._bu\n"
 				"    sys.stderr = scribus._bu\n"
 				"    sys.argv = ['scribus']\n" // this is the PySys_SetArgv replacement
@@ -423,9 +469,9 @@
 				"    sys.stdout = sys.__stdout__\n"
 				"    sys.stderr = sys.__stderr__\n"
 				"except SystemExit:\n"
-				"    print 'Catched SystemExit - it is not good for Scribus'\n"
+				"    print ('Caught SystemExit - it is not good for Scribus')\n"
 				"except KeyboardInterrupt:\n"
-				"    print 'Catched KeyboardInterrupt - it is not good for Scribus'\n"
+				"    print ('Caught KeyboardInterrupt - it is not good for Scribus')\n"
 			  );
 	}
 	// Set up sys.argv
@@ -459,6 +505,7 @@
 	}
 	ScCore->primaryMainWindow()->setScriptRunning(false);
 
+	emit finishing_script(true);
 	enableMainWindowMenu();
 }
 
@@ -596,14 +643,21 @@
 
 bool ScripterCore::setupMainInterpreter()
 {
+	// Code duplication - StringIO several times assigned to sys.stdin?
 	QString cm = QString(
 		"# -*- coding: utf-8 -*-\n"
-		"import scribus\n"
+		"import scribus\n" // TODO: This line without effect?
 		"import sys\n"
 		"import code\n"
 		"sys.path.insert(0, \"%1\")\n"
+#if IS_PY3K
+		"import io\n"
+		"sys.stdin = io.StringIO()\n"
+#else
 		"import cStringIO\n"
 		"sys.stdin = cStringIO.StringIO()\n"
+#endif
+		"#print('    scriptercore.cpp: This is the .so plugin loading code.')\n"
 		"scribus._ia = code.InteractiveConsole(globals())\n"
 		).arg(ScPaths::instance().scriptDir());
 	if (m_importAllNames)
@@ -636,6 +690,74 @@
 	pcon->updateSyntaxHighlighter();
 }
 
+void ScripterCore::disable_updates(bool main_thread)
+{
+	if (main_thread) 
+	{
+		if (num_main_interpreters == 0)
+		{
+			// Freeze the GUI
+			ScCore->primaryMainWindow()->doc->DoDrawing = false;
+			ScCore->primaryMainWindow()->doc->view()->updatesOn(false);
+			main_checkpoints = 0;
+		}
+		num_main_interpreters ++;
+		return;
+	}
+	
+	num_side_interpreters ++;
+	
+}
+
+void ScripterCore::test_checkpoint(int num)
+{
+	main_checkpoints += num;
+	
+	// FIXME: Magic Number!
+	if (main_checkpoints >= 1000) {
+		ScCore->primaryMainWindow()->doc->DoDrawing = true;
+		ScCore->primaryMainWindow()->doc->view()->updatesOn(true);
+		
+		ScCore->primaryMainWindow()->doc->view()->DrawNew();
+		ScCore->primaryMainWindow()->doc->changed();
+		
+		ScCore->primaryMainWindow()->doc->DoDrawing = false;
+		ScCore->primaryMainWindow()->doc->view()->updatesOn(false);
+	}
+}
+
+void ScripterCore::enable_updates(bool main_thread)
+{
+	if (main_thread) 
+	{
+		if (num_main_interpreters == 0)
+		{
+			qDebug() << "ScripterCore::script_finished(): slot WARNING: more scripts finished than started.";
+			num_main_interpreters++;
+		}
+		num_main_interpreters --;
+		if (num_main_interpreters == 0)
+		{
+			ScCore->primaryMainWindow()->doc->DoDrawing = true;
+			ScCore->primaryMainWindow()->doc->view()->updatesOn(true);
+			ScCore->primaryMainWindow()->doc->view()->DrawNew();
+			ScCore->primaryMainWindow()->doc->changed();
+		}
+		return;
+	}
+	
+	
+	if (num_side_interpreters == 0)
+	{
+		qDebug() << "ScripterCore::script_finished(): slot WARNING: more side scripts finished than started.";
+		num_side_interpreters++;
+	}
+	num_side_interpreters --;
+	
+}
+
+
+
 const QString & ScripterCore::startupScript() const
 {
 	return m_startupScript;
Index: scribus/plugins/scriptplugin/scriptercore.h
===================================================================
--- scribus/plugins/scriptplugin/scriptercore.h	(Revision 22369)
+++ scribus/plugins/scriptplugin/scriptercore.h	(Arbeitskopie)
@@ -62,7 +62,17 @@
 	void setStartupScript(const QString& newScript);
 	void setExtensionsEnabled(bool enable);
 	void updateSyntaxHighlighter();
+	
+	void disable_updates(bool main_thread);
+	void test_checkpoint(int num); // How many counters the checkpoint should be raised.
+	void enable_updates(bool main_thread);
 
+signals:
+	void starting_script(bool main);
+	void checkpoint(int num);
+	void finishing_script(bool main);
+	
+	
 protected:
 	// Private helper functions
 	void FinishScriptRun();
@@ -81,7 +91,11 @@
 	MenuManager *menuMgr;
 	QMap<QString, QPointer<ScrAction> > scrScripterActions;
 	QMap<QString, QPointer<ScrAction> > scrRecentScriptActions;
-
+	
+	int num_main_interpreters;
+	int num_side_interpreters;
+	int main_checkpoints;
+	
 	// Preferences
 	/** \brief pref: Enable access to main interpreter and 'extension scripts' */
 	bool m_enableExtPython;
Index: scribus/plugins/scriptplugin/scriptplugin.cpp
===================================================================
--- scribus/plugins/scriptplugin/scriptplugin.cpp	(Revision 22369)
+++ scribus/plugins/scriptplugin/scriptplugin.cpp	(Arbeitskopie)
@@ -171,16 +171,27 @@
 		Py_SetPythonHome(pythonHome.data());
 	}
 #endif
+
+#if IS_PY3K
+	scripterCore = new ScripterCore(ScCore->primaryMainWindow());
+	Q_CHECK_PTR(scripterCore);
+	
+	PyImport_AppendInittab("scribus", &PyInit_scribus);
+#endif
+
 	Py_Initialize();
-	if (PyUnicode_SetDefaultEncoding("utf-8"))
-	{
+
+#if !IS_PY3K
+	scripterCore = new ScripterCore(ScCore->primaryMainWindow());
+	Q_CHECK_PTR(scripterCore);
+	
+	if (PyUnicode_SetDefaultEncoding("utf-8")) {
 		qDebug("Failed to set default encoding to utf-8.\n");
 		PyErr_Clear();
 	}
+	initscribus(ScCore->primaryMainWindow(), false);
+#endif
 
-	scripterCore = new ScripterCore(ScCore->primaryMainWindow());
-	Q_CHECK_PTR(scripterCore);
-	initscribus(ScCore->primaryMainWindow());
 #ifdef HAVE_SCRIPTER2
 	scripter2_init();
 #endif
@@ -255,7 +266,7 @@
 
 /*static */PyObject *scribus_getval(PyObject* /*self*/)
 {
-	return PyString_FromString(scripterCore->inValue.toUtf8().data());
+	return PyUnicode_FromString(scripterCore->inValue.toUtf8().data());
 }
 
 /*! \brief Translate a docstring. Small helper function for use with the
@@ -460,6 +471,7 @@
 	{const_cast<char*>("redrawAll"), (PyCFunction)scribus_redraw, METH_NOARGS, tr(scribus_redraw__doc__)},
 	{const_cast<char*>("removeTableRows"), scribus_removetablerows, METH_VARARGS, tr(scribus_removetablerows__doc__)},
 	{const_cast<char*>("removeTableColumns"), scribus_removetablecolumns, METH_VARARGS, tr(scribus_removetablecolumns__doc__)},
+	{const_cast<char*>("renameObject"), (PyCFunction)scribus_renameobject, METH_VARARGS, tr(scribus_renameobject__doc__)},
 	{const_cast<char*>("renderFont"), (PyCFunction)scribus_renderfont, METH_KEYWORDS, tr(scribus_renderfont__doc__)},
 	{const_cast<char*>("replaceColor"), scribus_replcolor, METH_VARARGS, tr(scribus_replcolor__doc__)},
 	{const_cast<char*>("resizeTableColumn"), scribus_resizetablecolumn, METH_VARARGS, tr(scribus_resizetablecolumn__doc__)},
@@ -578,8 +590,9 @@
 	{const_cast<char*>("setProperty"), (PyCFunction)scribus_setproperty, METH_KEYWORDS, tr(scribus_setproperty__doc__)},
 // 	{const_cast<char*>("getChildren"), (PyCFunction)scribus_getchildren, METH_KEYWORDS, tr(scribus_getchildren__doc__)},
 // 	{const_cast<char*>("getChild"), (PyCFunction)scribus_getchild, METH_KEYWORDS, tr(scribus_getchild__doc__)},
+	{const_cast<char*>("duplicateObject"), scribus_duplicateobject, METH_VARARGS, tr(scribus_duplicateobject__doc__)},
 	// by Christian Hausknecht
-	{const_cast<char*>("duplicateObject"), scribus_duplicateobject, METH_VARARGS, tr(scribus_duplicateobject__doc__)},
+	{const_cast<char*>("duplicateObject_legacy"), scribus_duplicateobject_legacy, METH_VARARGS, tr(scribus_duplicateobject_legacy__doc__)},
 	{const_cast<char*>("copyObject"), scribus_copyobject, METH_VARARGS, tr(scribus_copyobject__doc__)},
 	{const_cast<char*>("pasteObject"), scribus_pasteobject, METH_VARARGS, tr(scribus_pasteobject__doc__)},
 	// Internal methods - Not for public use
@@ -594,6 +607,36 @@
 	{NULL, (PyCFunction)(0), 0, NULL} /* sentinel */
 };
 
+
+#if IS_PY3K
+struct module_state {
+    PyObject *error;
+};
+#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
+
+static int myextension_traverse(PyObject *m, visitproc visit, void *arg) {
+    Py_VISIT(GETSTATE(m)->error);
+    return 0;
+}
+
+static int myextension_clear(PyObject *m) {
+    Py_CLEAR(GETSTATE(m)->error);
+    return 0;
+}
+
+static struct PyModuleDef moduledef = {
+        PyModuleDef_HEAD_INIT,
+        "scribus",
+        NULL,
+        sizeof(struct module_state),
+        scribus_methods,
+        NULL,
+        myextension_traverse,
+        myextension_clear,
+        NULL
+};
+#endif
+
 void initscribus_failed(const char* fileName, int lineNo)
 {
 	qDebug("Scripter setup failed (%s:%i)", fileName, lineNo);
@@ -602,8 +645,18 @@
 	return;
 }
 
-void initscribus(ScribusMainWindow *pl)
+#if IS_PY3K
+// explanation on how it's to be done: https://docs.python.org/3/howto/cporting.html
+// Additional hint: has to be called by PyImport_AppendInittab before Py_Initialize
+/*static*/ PyObject* PyInit_scribus(void) {
+	PyObject *m;
+	m = PyModule_Create(&moduledef);
+	return m;
+}
+#endif
+void initscribus(ScribusMainWindow *pl, bool subinit)
 {
+	
 	if (!scripterCore)
 	{
 		qWarning("scriptplugin: Tried to init scribus module, but no scripter core. Aborting.");
@@ -610,16 +663,33 @@
 		return;
 	}
 	PyObject *m, *d;
-	PyImport_AddModule((char*)"scribus");
-
+	int result;
+	
+#if !IS_PY3K
+	subinit = false;
+#endif
+	if (!subinit)
+		m = PyImport_AddModule((char*)"scribus");
+	else
+		m = PyImport_ImportModule((char*)"scribus");
+	
 	PyType_Ready(&Printer_Type);
 	PyType_Ready(&PDFfile_Type);
 	PyType_Ready(&ImageExport_Type);
+#if !IS_PY3K
 	m = Py_InitModule((char*)"scribus", scribus_methods);
+#endif
+	
 	Py_INCREF(&Printer_Type);
-	PyModule_AddObject(m, (char*)"Printer", (PyObject *) &Printer_Type);
+	result = PyModule_AddObject(m, (char*)"Printer", (PyObject *) &Printer_Type);
+	if (result != 0) {
+		qDebug("scriptplugin: Could not create scribus.Printer module");
+	}
 	Py_INCREF(&PDFfile_Type);
-	PyModule_AddObject(m, (char*)"PDFfile", (PyObject *) &PDFfile_Type);
+	result = PyModule_AddObject(m, (char*)"PDFfile", (PyObject *) &PDFfile_Type);
+	if (result != 0) {
+		qDebug("scriptplugin: Could not create scribus.PDFfile module");
+	}
 	Py_INCREF(&ImageExport_Type);
 	PyModule_AddObject(m, (char*)"ImageExport", (PyObject *) &ImageExport_Type);
 	d = PyModule_GetDict(m);
@@ -652,6 +722,114 @@
 	// Done with exception setup
 
 	// CONSTANTS
+#if IS_PY3K
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("UNIT_POINTS")), PyInt_FromLong(unitIndexFromString("pt")));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("UNIT_MILLIMETERS")), PyInt_FromLong(unitIndexFromString("mm")));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("UNIT_INCHES")), PyInt_FromLong(unitIndexFromString("in")));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("UNIT_PICAS")), PyInt_FromLong(unitIndexFromString("p")));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("UNIT_CENTIMETRES")), PyInt_FromLong(unitIndexFromString("cm")));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("UNIT_CICERO")), PyInt_FromLong(unitIndexFromString("c")));
+        PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("UNIT_PT")), PyInt_FromLong(unitIndexFromString("pt")));
+        PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("UNIT_MM")), PyInt_FromLong(unitIndexFromString("mm")));
+        PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("UNIT_IN")), PyInt_FromLong(unitIndexFromString("in")));
+        PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("UNIT_P")), PyInt_FromLong(unitIndexFromString("p")));
+        PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("UNIT_CM")), PyInt_FromLong(unitIndexFromString("cm")));
+        PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("UNIT_C")), PyInt_FromLong(unitIndexFromString("c")));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PORTRAIT")), Py_BuildValue(const_cast<char*>("i"), portraitPage));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("LANDSCAPE")), Py_BuildValue(const_cast<char*>("i"), landscapePage));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("NOFACINGPAGES")), Py_BuildValue(const_cast<char*>("i"), 0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("FACINGPAGES")),  Py_BuildValue(const_cast<char*>("i"), 1));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("FIRSTPAGERIGHT")), Py_BuildValue(const_cast<char*>("i"), 1));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("FIRSTPAGELEFT")), Py_BuildValue(const_cast<char*>("i"), 0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("ALIGN_LEFT")), Py_BuildValue(const_cast<char*>("i"), 0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("ALIGN_RIGHT")), Py_BuildValue(const_cast<char*>("i"), 2));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("ALIGN_CENTERED")), Py_BuildValue(const_cast<char*>("i"), 1));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("ALIGN_BLOCK")), Py_BuildValue(const_cast<char*>("i"), 3));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("ALIGN_FORCED")), Py_BuildValue(const_cast<char*>("i"), 4));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("DIRECTION_LTR")), Py_BuildValue(const_cast<char*>("i"), 0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("DIRECTION_RTL")), Py_BuildValue(const_cast<char*>("i"), 1));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("FILL_NOG")), Py_BuildValue(const_cast<char*>("i"), 0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("FILL_HORIZONTALG")), Py_BuildValue(const_cast<char*>("i"), 1));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("FILL_VERTICALG")), Py_BuildValue(const_cast<char*>("i"), 2));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("FILL_DIAGONALG")), Py_BuildValue(const_cast<char*>("i"), 3));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("FILL_CROSSDIAGONALG")), Py_BuildValue(const_cast<char*>("i"), 4));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("FILL_RADIALG")), Py_BuildValue(const_cast<char*>("i"), 5));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("LINE_SOLID")), Py_BuildValue(const_cast<char*>("i"), Qt::SolidLine));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("LINE_DASH")), Py_BuildValue(const_cast<char*>("i"), Qt::DashLine));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("LINE_DOT")), Py_BuildValue(const_cast<char*>("i"), Qt::DotLine));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("LINE_DASHDOT")), Py_BuildValue(const_cast<char*>("i"), Qt::DashDotLine));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("LINE_DASHDOTDOT")), Py_BuildValue(const_cast<char*>("i"), Qt::DashDotDotLine));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("JOIN_MITTER")), Py_BuildValue(const_cast<char*>("i"), Qt::MiterJoin));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("JOIN_BEVEL")), Py_BuildValue(const_cast<char*>("i"), Qt::BevelJoin));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("JOIN_ROUND")), Py_BuildValue(const_cast<char*>("i"), Qt::RoundJoin));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("CAP_FLAT")), Py_BuildValue(const_cast<char*>("i"), Qt::FlatCap));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("CAP_SQUARE")), Py_BuildValue(const_cast<char*>("i"), Qt::SquareCap));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("CAP_ROUND")), Py_BuildValue(const_cast<char*>("i"), Qt::RoundCap));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("BUTTON_NONE")), Py_BuildValue(const_cast<char*>("i"), QMessageBox::NoButton));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("BUTTON_OK")), Py_BuildValue(const_cast<char*>("i"), QMessageBox::Ok));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("BUTTON_CANCEL")), Py_BuildValue(const_cast<char*>("i"), QMessageBox::Cancel));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("BUTTON_YES")), Py_BuildValue(const_cast<char*>("i"), QMessageBox::Yes));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("BUTTON_NO")), Py_BuildValue(const_cast<char*>("i"), QMessageBox::No));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("BUTTON_ABORT")), Py_BuildValue(const_cast<char*>("i"), QMessageBox::Abort));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("BUTTON_RETRY")), Py_BuildValue(const_cast<char*>("i"), QMessageBox::Retry));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("BUTTON_IGNORE")), Py_BuildValue(const_cast<char*>("i"), QMessageBox::Ignore));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("BUTTON_DEFAULT")), Py_BuildValue(const_cast<char*>("i"), QMessageBox::Default));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("ICON_NONE")), Py_BuildValue(const_cast<char*>("i"), QMessageBox::NoIcon));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("ICON_INFORMATION")), Py_BuildValue(const_cast<char*>("i"), QMessageBox::Information));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("ICON_WARNING")), Py_BuildValue(const_cast<char*>("i"), QMessageBox::Warning));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("ICON_CRITICAL")), Py_BuildValue(const_cast<char*>("i"), QMessageBox::Critical));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_A0")), Py_BuildValue(const_cast<char*>("(ff)"), 2380.0, 3368.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_A1")), Py_BuildValue(const_cast<char*>("(ff)"), 1684.0, 2380.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_A2")), Py_BuildValue(const_cast<char*>("(ff)"), 1190.0, 1684.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_A3")), Py_BuildValue(const_cast<char*>("(ff)"), 842.0, 1190.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_A4")), Py_BuildValue(const_cast<char*>("(ff)"), 595.0, 842.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_A5")), Py_BuildValue(const_cast<char*>("(ff)"), 421.0, 595.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_A6")), Py_BuildValue(const_cast<char*>("(ff)"), 297.0, 421.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_A7")), Py_BuildValue(const_cast<char*>("(ff)"), 210.0, 297.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_A8")), Py_BuildValue(const_cast<char*>("(ff)"), 148.0, 210.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_A9")), Py_BuildValue(const_cast<char*>("(ff)"), 105.0, 148.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_B0")), Py_BuildValue(const_cast<char*>("(ff)"), 2836.0, 4008.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_B1")), Py_BuildValue(const_cast<char*>("(ff)"), 2004.0, 2836.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_B2")), Py_BuildValue(const_cast<char*>("(ff)"), 1418.0, 2004.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_B3")), Py_BuildValue(const_cast<char*>("(ff)"), 1002.0, 1418.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_B4")), Py_BuildValue(const_cast<char*>("(ff)"), 709.0, 1002.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_B5")), Py_BuildValue(const_cast<char*>("(ff)"), 501.0, 709.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_B6")), Py_BuildValue(const_cast<char*>("(ff)"), 355.0, 501.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_B7")), Py_BuildValue(const_cast<char*>("(ff)"), 250.0, 355.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_B8")), Py_BuildValue(const_cast<char*>("(ff)"), 178.0, 250.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_B9")), Py_BuildValue(const_cast<char*>("(ff)"), 125.0, 178.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_B10")), Py_BuildValue(const_cast<char*>("(ff)"), 89.0, 125.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_C5E")), Py_BuildValue(const_cast<char*>("(ff)"), 462.0, 649.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_COMM10E")), Py_BuildValue(const_cast<char*>("(ff)"), 298.0, 683.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_DLE")),  Py_BuildValue(const_cast<char*>("(ff)"), 312.0, 624.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_EXECUTIVE")), Py_BuildValue(const_cast<char*>("(ff)"), 542.0, 720.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_FOLIO")), Py_BuildValue(const_cast<char*>("(ff)"), 595.0, 935.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_LEDGER")), Py_BuildValue(const_cast<char*>("(ff)"), 1224.0, 792.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_LEGAL")), Py_BuildValue(const_cast<char*>("(ff)"), 612.0, 1008.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_LETTER")), Py_BuildValue(const_cast<char*>("(ff)"), 612.0, 792.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAPER_TABLOID")), Py_BuildValue(const_cast<char*>("(ff)"), 792.0, 1224.0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("NORMAL")), Py_BuildValue(const_cast<char*>("i"), 0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("DARKEN")), Py_BuildValue(const_cast<char*>("i"), 1));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("LIGHTEN")), Py_BuildValue(const_cast<char*>("i"), 2));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("MULTIPLY")), Py_BuildValue(const_cast<char*>("i"), 3));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("SCREEN")), Py_BuildValue(const_cast<char*>("i"), 4));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("OVERLAY")), Py_BuildValue(const_cast<char*>("i"), 5));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("HARD_LIGHT")), Py_BuildValue(const_cast<char*>("i"), 6));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("SOFT_LIGHT")), Py_BuildValue(const_cast<char*>("i"), 7));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("DIFFERENCE")), Py_BuildValue(const_cast<char*>("i"), 8));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("EXCLUSION")), Py_BuildValue(const_cast<char*>("i"), 9));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("COLOR_DODGE")), Py_BuildValue(const_cast<char*>("i"), 10));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("COLOR_BURN")), Py_BuildValue(const_cast<char*>("i"), 11));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("HUE")), Py_BuildValue(const_cast<char*>("i"), 12));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("SATURATION")), Py_BuildValue(const_cast<char*>("i"), 13));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("COLOR")), Py_BuildValue(const_cast<char*>("i"), 14));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("LUMINOSITY")), Py_BuildValue(const_cast<char*>("i"), 15));
+	// preset page layouts
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAGE_1")), Py_BuildValue(const_cast<char*>("i"), 0));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAGE_2")), Py_BuildValue(const_cast<char*>("i"), 1));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAGE_3")), Py_BuildValue(const_cast<char*>("i"), 2));
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("PAGE_4")), Py_BuildValue(const_cast<char*>("i"), 3));
+#else
 	PyDict_SetItemString(d, const_cast<char*>("UNIT_POINTS"), PyInt_FromLong(unitIndexFromString("pt")));
 	PyDict_SetItemString(d, const_cast<char*>("UNIT_MILLIMETERS"), PyInt_FromLong(unitIndexFromString("mm")));
 	PyDict_SetItemString(d, const_cast<char*>("UNIT_INCHES"), PyInt_FromLong(unitIndexFromString("in")));
@@ -758,6 +936,7 @@
 	PyDict_SetItemString(d, const_cast<char*>("PAGE_2"), Py_BuildValue(const_cast<char*>("i"), 1));
 	PyDict_SetItemString(d, const_cast<char*>("PAGE_3"), Py_BuildValue(const_cast<char*>("i"), 2));
 	PyDict_SetItemString(d, const_cast<char*>("PAGE_4"), Py_BuildValue(const_cast<char*>("i"), 3));
+#endif
 
 	// Measurement units understood by Scribus's units.cpp functions are exported as constant conversion
 	// factors to be used from Python.
@@ -772,9 +951,19 @@
 		// `in' is a reserved word in Python so we must replace it
 		PyObject* name;
 		if (unitGetUntranslatedStrFromIndex(i) == "in")
+		{
+#if IS_PY3K
+			name = PyUnicode_FromString("inch");
+#else
 			name = PyString_FromString("inch");
-		else
+#endif
+		} else {
+#if IS_PY3K
+			name = PyUnicode_FromString(unitGetUntranslatedStrFromIndex(i).toLatin1().constData());
+#else
 			name = PyString_FromString(unitGetUntranslatedStrFromIndex(i).toLatin1().constData());
+#endif
+		}
 		if (!name)
 		{
 			initscribus_failed(__FILE__, __LINE__);
@@ -788,7 +977,11 @@
 	}
 
 	// Export the Scribus version into the module namespace so scripts know what they're running in
+#if IS_PY3K
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("scribus_version")), PyUnicode_FromString(const_cast<char*>(VERSION)));
+#else
 	PyDict_SetItemString(d, const_cast<char*>("scribus_version"), PyString_FromString(const_cast<char*>(VERSION)));
+#endif	
 	// Now build a version tuple like that provided by Python in sys.version_info
 	// The tuple is of the form (major, minor, patchlevel, extraversion, reserved)
 	QRegExp version_re("(\\d+)\\.(\\d+)\\.(\\d+)(.*)");
@@ -804,7 +997,13 @@
 		PyObject* versionTuple = Py_BuildValue(const_cast<char*>("(iiisi)"),\
 				majorVersion, minorVersion, patchVersion, (const char*)extraVersion.toUtf8(), 0);
 		if (versionTuple != NULL)
+		{
+#if IS_PY3K
+			PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("scribus_version_info")), versionTuple);
+#else
 			PyDict_SetItemString(d, const_cast<char*>("scribus_version_info"), versionTuple);
+#endif
+		}
 		else
 			qDebug("Failed to build version tuple for version string '%s' in scripter", VERSION);
 	}
@@ -813,18 +1012,36 @@
 
 // 	ScMW = pl;
 	// Function aliases for compatibility
-	// We need to import the __builtins__, warnings and exceptions modules to be able to run
+	// We need to import the builtins, warnings and exceptions modules to be able to run
 	// the generated Python functions from inside the `scribus' module's context.
 	// This code makes it possible to extend the `scribus' module by running Python code
 	// from C in other ways too.
+	// JONAS: __builtin__ -> builtins (Python3)
+#if IS_PY3K
+	PyObject* builtinModule = PyImport_ImportModuleEx(const_cast<char*>("builtins"),
+			d, d, Py_BuildValue(const_cast<char*>("[]")));
+#else
 	PyObject* builtinModule = PyImport_ImportModuleEx(const_cast<char*>("__builtin__"),
 			d, d, Py_BuildValue(const_cast<char*>("[]")));
+#endif
 	if (builtinModule == NULL)
 	{
+#if IS_PY3K
+		qDebug("Failed to import 'builtins' module. Something is probably broken with your Python.");
+#else
 		qDebug("Failed to import __builtin__ module. Something is probably broken with your Python.");
+#endif
 		return;
 	}
+#if IS_PY3K
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("builtins")), builtinModule);
+#else
 	PyDict_SetItemString(d, const_cast<char*>("__builtin__"), builtinModule);
+#endif
+	
+#if IS_PY3K
+	/* "exceptions" has been merged into "builtins" in Python 3 */
+#else
 	PyObject* exceptionsModule = PyImport_ImportModuleEx(const_cast<char*>("exceptions"),
 			d, d, Py_BuildValue(const_cast<char*>("[]")));
 	if (exceptionsModule == NULL)
@@ -832,7 +1049,9 @@
 		qDebug("Failed to import exceptions module. Something is probably broken with your Python.");
 		return;
 	}
-	PyDict_SetItemString(d, const_cast<char*>("exceptions"), exceptionsModule);
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("exceptions")), exceptionsModule);
+#endif
+	
 	PyObject* warningsModule = PyImport_ImportModuleEx(const_cast<char*>("warnings"),
 			d, d, Py_BuildValue(const_cast<char*>("[]")));
 	if (warningsModule == NULL)
@@ -840,7 +1059,11 @@
 		qDebug("Failed to import warnings module. Something is probably broken with your Python.");
 		return;
 	}
+#if IS_PY3K
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("warnings")), warningsModule);
+#else
 	PyDict_SetItemString(d, const_cast<char*>("warnings"), warningsModule);
+#endif
 	// Create the module-level docstring. This can be a proper unicode string, unlike
 	// the others, because we can just create a Unicode object and insert it in our
 	// module dictionary.
@@ -876,11 +1099,18 @@
 is not exhaustive due to exceptions from called functions.\n\
 ");
 
+#if IS_PY3K
+	PyObject* docStr = PyUnicode_FromString(docstring.toUtf8().data());
+#else
 	PyObject* docStr = PyString_FromString(docstring.toUtf8().data());
+#endif
 	if (!docStr)
 		qDebug("Failed to create module-level docstring (couldn't make str)");
 	else
 	{
+#if IS_PY3K
+		PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("__doc__")), docStr);
+#else
 		PyObject* uniDocStr = PyUnicode_FromEncodedObject(docStr, "utf-8", NULL);
 		Py_DECREF(docStr);
 		docStr = NULL;
@@ -887,9 +1117,16 @@
 		if (!uniDocStr)
 			qDebug("Failed to create module-level docstring object (couldn't make unicode)");
 		else
+		{
+#if IS_PY3K
+			PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("__doc__")), uniDocStr);
+#else
 			PyDict_SetItemString(d, const_cast<char*>("__doc__"), uniDocStr);
+#endif
+		}
 		Py_DECREF(uniDocStr);
 		uniDocStr = NULL;
+#endif
 	}
 
 	// Wrap up pointers to the the QApp and main window and push them out
@@ -901,7 +1138,11 @@
 		PyErr_Print();
 	}
 	// Push it into the module dict, stealing a ref in the process
+#if IS_PY3K
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("qApp")), wrappedQApp);
+#else
 	PyDict_SetItemString(d, const_cast<char*>("qApp"), wrappedQApp);
+#endif
 	Py_DECREF(wrappedQApp);
 	wrappedQApp = NULL;
 
@@ -912,9 +1153,15 @@
 		PyErr_Print();
 	}
 	// Push it into the module dict, stealing a ref in the process
+#if IS_PY3K
+	PyDict_SetItem(d, PyUnicode_FromString(const_cast<char*>("mainWindow")), wrappedMainWindow);
+#else
 	PyDict_SetItemString(d, const_cast<char*>("mainWindow"), wrappedMainWindow);
+#endif
 	Py_DECREF(wrappedMainWindow);
 	wrappedMainWindow = NULL;
+	
+	return;
 }
 
 /*! HACK: this removes "warning: 'blah' defined but not used" compiler warnings
Index: scribus/plugins/scriptplugin/cmdobj.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdobj.cpp	(Revision 22369)
+++ scribus/plugins/scriptplugin/cmdobj.cpp	(Arbeitskopie)
@@ -16,7 +16,9 @@
 #include "selection.h"
 #include "util_math.h"
 
+#include "scriptercore.h"
 
+
 PyObject *scribus_newrect(PyObject* /* self */, PyObject* args)
 {
 	double x, y, w, h;
@@ -43,7 +45,7 @@
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(i)->setItemName(objName);
 	}
-	return PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
+	return Legacy_PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
 }
 
 
@@ -69,7 +71,7 @@
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(i)->setItemName(objName);
 	}
-	return PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
+	return Legacy_PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
 }
 
 
@@ -94,7 +96,7 @@
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(i)->setItemName(objName);
 	}
-	return PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
+	return Legacy_PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
 }
 
 
@@ -119,7 +121,7 @@
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(i)->setItemName(objName);
 	}
-	return PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
+	return Legacy_PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
 }
 
 PyObject *scribus_newtable(PyObject* /* self */, PyObject* args)
@@ -155,7 +157,7 @@
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(i)->setItemName(objName);
 	}
-	return PyString_FromString(table->itemName().toUtf8());
+	return Legacy_PyString_FromString(table->itemName().toUtf8());
 }
 
 PyObject *scribus_newline(PyObject* /* self */, PyObject* args)
@@ -215,7 +217,7 @@
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(i)->setItemName(objName);
 	}
-	return PyString_FromString(it->itemName().toUtf8());
+	return Legacy_PyString_FromString(it->itemName().toUtf8());
 }
 
 
@@ -292,7 +294,7 @@
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(ic)->setItemName(objName);
 	}
-	return PyString_FromString(it->itemName().toUtf8());
+	return Legacy_PyString_FromString(it->itemName().toUtf8());
 }
 
 
@@ -374,7 +376,7 @@
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(ic)->setItemName(objName);
 	}
-	return PyString_FromString(it->itemName().toUtf8());
+	return Legacy_PyString_FromString(it->itemName().toUtf8());
 }
 
 PyObject *scribus_bezierline(PyObject* /* self */, PyObject* args)
@@ -465,7 +467,7 @@
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(ic)->setItemName(objName);
 	}
-	return PyString_FromString(it->itemName().toUtf8());
+	return Legacy_PyString_FromString(it->itemName().toUtf8());
 }
 
 
@@ -506,7 +508,7 @@
 		if (!ItemExists(objName))
 			i->setItemName(objName);
 	}
-	return PyString_FromString(i->itemName().toUtf8());
+	return Legacy_PyString_FromString(i->itemName().toUtf8());
 }
 
 
@@ -527,6 +529,9 @@
 	ScCore->primaryMainWindow()->doc->itemSelection_DeleteItem();
 //	Py_INCREF(Py_None);
 //	return Py_None;
+	
+	emit scripterCore->checkpoint(10);
+	
 	Py_RETURN_NONE;
 }
 
@@ -760,7 +765,7 @@
 	styleList = PyList_New(0);
 	for (int i=0; i < ScCore->primaryMainWindow()->doc->paragraphStyles().count(); ++i)
 	{
-		if (PyList_Append(styleList, PyString_FromString(ScCore->primaryMainWindow()->doc->paragraphStyles()[i].name().toUtf8())))
+		if (PyList_Append(styleList, Legacy_PyString_FromString(ScCore->primaryMainWindow()->doc->paragraphStyles()[i].name().toUtf8())))
 		{
 			// An exception will have already been set by PyList_Append apparently.
 			return NULL;
@@ -777,7 +782,7 @@
 	charStyleList = PyList_New(0);
 	for (int i=0; i < ScCore->primaryMainWindow()->doc->charStyles().count(); ++i)
 	{
-		if (PyList_Append(charStyleList, PyString_FromString(ScCore->primaryMainWindow()->doc->charStyles()[i].name().toUtf8())))
+		if (PyList_Append(charStyleList, Legacy_PyString_FromString(ScCore->primaryMainWindow()->doc->charStyles()[i].name().toUtf8())))
 		{
 			// An exception will have already been set by PyList_Append apparently.
 			return NULL;
@@ -786,16 +791,82 @@
 	return charStyleList;
 }
 
+PyObject *scribus_renameobject(PyObject * /* self */, PyObject *args)
+{
+	char* origname = const_cast<char*>("");
+	char* newname = const_cast<char*>("");
+	if (!PyArg_ParseTuple(args, "es|es", "utf-8", &newname, "utf-8", &origname)) {
+		Py_RETURN_NONE;
+	}
+	if(!checkHaveDocument()) {
+		Py_RETURN_NONE;
+	}
+	
+	PageItem *src = GetUniqueItem(QString::fromUtf8(origname));
+	if (src == NULL) {
+		qDebug() << QString("Cannot get item \"%1\".").arg(origname);
+		Py_RETURN_NONE;
+	}
+	
+	src->setItemName(newname);
+	if (src->itemName() != newname)
+	{
+		PyErr_SetString(
+			NameExistsError,
+			QObject::tr("An object with the requested name already exists.",
+			            "python error").toUtf8().constData());
+		src->setItemName(origname);
+		qDebug() << QString("Wanted back to \"%1\", got \"%2\".").arg(origname, src->itemName());
+		Py_RETURN_NONE;
+	}
+	
+	emit scripterCore->checkpoint(5);
+	
+	return Legacy_PyString_FromString(src->itemName().toUtf8());
+}
+
 PyObject *scribus_duplicateobject(PyObject * /* self */, PyObject *args)
 {
 	char* name = const_cast<char*>("");
+	char* newname = const_cast<char*>("");
+	if (!PyArg_ParseTuple(args, "|eses", "utf-8", &newname, "utf-8", &name)) {
+		Py_RETURN_NONE;
+	}
+	if(!checkHaveDocument()) {
+		Py_RETURN_NONE;
+	}
+	// We require a name given and duplicate only one object at one time.
+	PageItem *src = GetUniqueItem(QString::fromUtf8(name));
+	if (src == NULL) {
+		qDebug() << "Cannot duplicate NULL.";
+		Py_RETURN_NONE;
+	}
+	
+	QString qnewname = QString::fromUtf8(newname);
+	
+	// do the duplicate
+	PageItem *dst = ScCore->primaryMainWindow()->slotDuplicateSingle(src, &qnewname);
+	
+	if (dst == NULL) {
+		emit scripterCore->checkpoint(4);
+		Py_RETURN_NONE;
+	}
+	
+	emit scripterCore->checkpoint(12);
+	
+	return Legacy_PyString_FromString(dst->itemName().toUtf8());
+}
+
+PyObject *scribus_duplicateobject_legacy(PyObject * /* self */, PyObject *args)
+{
+	char* name = const_cast<char*>("");
 	if (!PyArg_ParseTuple(args, "|es", "utf-8", &name)) {
-		return NULL;
+		Py_RETURN_NONE;
 	}
 	if(!checkHaveDocument()) {
-		return NULL;
+		Py_RETURN_NONE;
 	}
-	// Is there a special name given? Yes -> add this to selection
+	// Is there a special name given? Yes -> make a selection of it
 	PageItem *i = GetUniqueItem(QString::fromUtf8(name));
 	if (i != NULL) {
 		ScCore->primaryMainWindow()->doc->m_Selection->clear();
@@ -802,12 +873,15 @@
 		ScCore->primaryMainWindow()->doc->m_Selection->addItem(i);
 	}
 	else
-		return NULL;
+		Py_RETURN_NONE;
 	// do the duplicate
 	ScCore->primaryMainWindow()->slotEditCopy();
 	ScCore->primaryMainWindow()->slotEditPaste();
 //	Py_INCREF(Py_None);
 //	return Py_None;
+	
+	emit scripterCore->checkpoint(20);
+	
 	Py_RETURN_NONE;
 }
 
@@ -855,8 +929,8 @@
 /*! HACK: this removes "warning: 'blah' defined but not used" compiler warnings
 with header files structure untouched (docstrings are kept near declarations)
 PV */
-void cmdobjdocwarnings()
+inline void cmdobjdocwarnings()
 {
 	QStringList s;
-	s << scribus_newrect__doc__ <<scribus_newellipse__doc__ << scribus_newimage__doc__ << scribus_newtext__doc__ << scribus_newtable__doc__ << scribus_newline__doc__ <<scribus_polyline__doc__ << scribus_polygon__doc__ << scribus_bezierline__doc__ <<scribus_pathtext__doc__ <<scribus_deleteobj__doc__ <<scribus_textflow__doc__ <<scribus_objectexists__doc__ <<scribus_setstyle__doc__ <<scribus_getstylenames__doc__ <<scribus_getcharstylenames__doc__ <<scribus_duplicateobject__doc__ <<scribus_copyobject__doc__ <<scribus_pasteobject__doc__;
+	s << scribus_newrect__doc__ <<scribus_newellipse__doc__ << scribus_newimage__doc__ << scribus_newtext__doc__ << scribus_newtable__doc__ << scribus_newline__doc__ <<scribus_polyline__doc__ << scribus_polygon__doc__ << scribus_bezierline__doc__ <<scribus_pathtext__doc__ <<scribus_deleteobj__doc__ <<scribus_textflow__doc__ <<scribus_objectexists__doc__ <<scribus_setstyle__doc__ <<scribus_setcharstyle__doc__ <<scribus_getstylenames__doc__ <<scribus_getcharstylenames__doc__ <<scribus_renameobject__doc__ <<scribus_duplicateobject__doc__ <<scribus_duplicateobject__doc__ <<scribus_duplicateobject_legacy__doc__ <<scribus_copyobject__doc__ <<scribus_pasteobject__doc__;
 }
Index: scribus/plugins/scriptplugin/cmdtable.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdtable.cpp	(Revision 22369)
+++ scribus/plugins/scriptplugin/cmdtable.cpp	(Arbeitskopie)
@@ -338,7 +338,7 @@
 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get table style on a non-table item.","python error").toLocal8Bit().constData());
 		return NULL;
 	}
-	return PyString_FromString(table->styleName().toUtf8());
+	return Legacy_PyString_FromString(table->styleName().toUtf8());
 }
 
 PyObject *scribus_settablestyle(PyObject* /* self */, PyObject* args)
@@ -378,7 +378,7 @@
 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get table fill color on a non-table item.","python error").toLocal8Bit().constData());
 		return NULL;
 	}
-	return PyString_FromString(table->fillColor().toUtf8());
+	return Legacy_PyString_FromString(table->fillColor().toUtf8());
 }
 
 PyObject *scribus_settablefillcolor(PyObject* /* self */, PyObject* args)
Index: scribus/plugins/scriptplugin/cmdtext.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdtext.cpp	(Revision 22369)
+++ scribus/plugins/scriptplugin/cmdtext.cpp	(Arbeitskopie)
@@ -17,6 +17,7 @@
 #include "selection.h"
 #include "util.h"
 
+#include "scriptercore.h"
 
 template<typename T>
 class ApplyCharstyleHelper {
@@ -91,11 +92,11 @@
 	{
 		for (int b = 0; b < it->itemText.length(); b++)
 			if (it->itemText.selected(b))
-				return PyString_FromString(it->itemText.charStyle(b).font().scName().toUtf8());
+				return Legacy_PyString_FromString(it->itemText.charStyle(b).font().scName().toUtf8());
 		return NULL;
 	}
 	else
-		return PyString_FromString(it->currentCharStyle().font().scName().toUtf8());
+		return Legacy_PyString_FromString(it->currentCharStyle().font().scName().toUtf8());
 }
 
 PyObject *scribus_gettextsize(PyObject* /* self */, PyObject* args)
@@ -171,11 +172,11 @@
 	{
 		for (int b = 0; b < it->itemText.length(); b++)
 			if (it->itemText.selected(b))
-				return PyString_FromString(it->itemText.charStyle(b).fontFeatures().toUtf8());
+				return Legacy_PyString_FromString(it->itemText.charStyle(b).fontFeatures().toUtf8());
 		return NULL;
 	}
 	else
-		return PyString_FromString(it->currentCharStyle().fontFeatures().toUtf8());
+		return Legacy_PyString_FromString(it->currentCharStyle().fontFeatures().toUtf8());
 }
 
 PyObject *scribus_getlinespace(PyObject* /* self */, PyObject* args)
@@ -264,7 +265,7 @@
 			text += it->itemText.text(a);
 		}
 	}
-	return PyString_FromString(text.toUtf8());
+	return Legacy_PyString_FromString(text.toUtf8());
 }
 
 PyObject *scribus_gettext(PyObject* /* self */, PyObject* args)
@@ -297,7 +298,7 @@
 			text += it->itemText.text(a);
 		}
 	} // for
-	return PyString_FromString(text.toUtf8());
+	return Legacy_PyString_FromString(text.toUtf8());
 }
 
 PyObject *scribus_setboxtext(PyObject* /* self */, PyObject* args)
@@ -358,12 +359,16 @@
 	if (pos == -1)
 		pos = it->itemText.length();
 	it->itemText.insertChars(pos, textData, true);
-	it->Dirty = true;
+	
+	/*it->Dirty = true;
 	if (ScCore->primaryMainWindow()->doc->DoDrawing)
 	{
 		// FIXME adapt to Qt-4 painting style
 		it->Dirty = false;
-	}
+	}*/ // (We are not in editMode.)
+	
+	emit scripterCore->checkpoint(2);
+	
 	Py_RETURN_NONE;
 }
 
Index: scribus/plugins/scriptplugin/cmdvar.h
===================================================================
--- scribus/plugins/scriptplugin/cmdvar.h	(Revision 22369)
+++ scribus/plugins/scriptplugin/cmdvar.h	(Arbeitskopie)
@@ -32,6 +32,41 @@
 	#define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True
 #endif
 
+
+#if PY_MAJOR_VERSION >= 3
+#define IS_PY3K 1
+#endif
+
+#if IS_PY3K
+// Python 2 -> Python 3 transition:
+//   Convert a Utf8 buffer to a Python String Object
+#define Legacy_PyString_FromString PyUnicode_FromString
+//   Convert a data buffer to Python bytes
+#define Legacy_PyBytes_FromStringAndSize PyBytes_FromStringAndSize
+//   Return True if a Python Object is a Unicode String
+#define PyString_Check PyUnicode_Check
+// rather CheckExact?
+#define PyString_Size PyBytes_Size
+//   Convert a Python String Object to a char* that points to a null-terminated Utf8 buffer
+#define PyString_AsString PyUnicode_AsUTF8
+#define PyInt_FromLong PyLong_FromLong
+#define PyInt_Check PyLong_Check
+#define PyInt_AsLong PyLong_AsLong
+#define PyCObject_Check PyCapsule_CheckExact
+#define PyCObject_AsVoidPtr(capsule) \
+		(PyCapsule_GetPointer(capsule, NULL))
+#define PyCObject_FromVoidPtr(pointer, destructor) \
+		(PyCapsule_New(pointer, NULL, destructor))
+// Helpful is:
+// https://docs.python.org/3/howto/cporting.html#cobject-replaced-with-capsule
+// as well as:
+// https://docs.python.org/3/c-api/bytes.html 
+// etc.
+#else
+#define Legacy_PyString_FromString PyString_FromString 
+#define Legacy_PyBytes_FromStringAndSize PyString_FromStringAndSize
+#endif
+
 #include <QString>
 
 #include "scribus.h"
@@ -50,7 +85,10 @@
 extern ScripterCore* scripterCore;
 
 /** @brief Initialize the 'scribus' Python module in the currently active interpreter */
-extern "C" void initscribus(ScribusMainWindow *pl);
+extern "C" void initscribus(ScribusMainWindow *pl, bool subinit);
+#if IS_PY3K
+/*static*/ PyObject* PyInit_scribus(void);
+#endif
 
 /* Exceptions */
 /*! Common scribus Exception */

william

2018-02-07 21:01

updater   ~0044944

I applied all three patches.
scribus-20180205-095552-jonas-scripterpart.patch is similar to my last patch.
After applying it, the build failed with
scriptplugin/cmdobj.cpp:848:47: error: class ScribusMainWindow has no member named slotDuplicateSingle
so I applied scribus-20180205-095552-jonas-duplicate.patch
Then the build failed with
scriptplugin/cmdobj.cpp:935:478: error: scribus_renameobject__doc__ was not declared in this scope
so I applied scribus-20180205-095552-jonas-duplicate_python_invokation.patch
and then Scribus built cleanly.

I had line ending issues with some hunks in the patches -- the patches had unix-style <nl> endings, but some of the Scribus source files have MSDOS-style <cr><nl> endings. I edited the patches to add <cr>s to the ends of the lines of those hunks. Some day the line ends in the Scribus source needs to be cleaned up...
In scribus-20180205-095552-jonas-duplicate.patch, hunk 1 to fix scribus150format.h #ifndef SCRIBUS150FORMAT_H is already in svn.
In scribus-20180205-095552-jonas-duplicate_python_invokation.patch, it looked like the changes for cmdobj.cpp were already applied by another patch.

In any case, it is all built and running. Scripts work from Scripter -> Execute Script on the menu and from inside the scripter console, but when running from a command line, the python interpreter does not find items inside the 'scribus' module.
Is that expected (and I need to make the changes that you suggested a few comments ago) or was it supposed to have worked?

I am going to keep working with the combined version of the patches. Probably for the likelihood of having the python3 patches accepted, it would have been better to have a stand-alone python3 patch and then for the patches in https://bugs.scribus.net/view.php?id=15131 to apply on top of those patches (even if it means that some files are touched by both patches), but at least for now, your combined patches are a good base for python3 and the other changes can be separated later if necessary.

u ltd.

2018-02-08 08:23

reporter   ~0044945

Answering your questions:

I've made the changes for another revision, then successfully invoked 'svn up' and then made svn diff.
-> SCRIBUS150FORMAT_H: maybe you have a newer svn revision than the patchtime (r22369). What says "svn log scribus/plugins/fileloader/scribus150format/scribus150format.h | head"?
I have split the patches manually in text editor.
-> This text editor did equalize the line endings which have been reported correctly by svn. Sorry, I wasn't aware.
To have a working version for the different parts, I had to include cmdobj.cpp in two patches.
-> cmdobj.cpp: Yes, there may occure some merge errors.

I'm only using python 3. For me scripter console is working. Can you show me the output of "dir(scribus)"? I would expect a very long line which starts with ALIGN_BLOCK and ends with zoomDocument.

william

2018-02-08 16:52

updater   ~0044948

> Can you show me the output of "dir(scribus)"?

It works as expected if I execute the command inside a script from the menu or if I type it into the console. I get about 400 items.
But if I run the same script from the command line, dir(scribus) sometimes returns nothing.
It looks like it depends on whether standard output is redirected to a file.
I ran
/u/scribus15p3bin/bin/scribus-1.5.4.svn -g -py scribus-dir.py -- Document-1.sla > junk 2>&1
and it never showed even the --start-- line, but gdb does not show a crash, but if I run it without redirection, I get the expected long list from dir(scribus).
When I run
/u/scribus15p3bin/bin/scribus-1.5.4.svn -g -py export_to_pdf.py -file test.pdf -- Document-1.sla
I get
Traceback (most recent call last):
  File "<string>", line 10, in <module>
  File "<string>", line 53, in <module>
  File "<string>", line 25, in main
AttributeError: module 'scribus' has no attribute 'PDFfile'

I attached the results (pasted from the terminal window) of running scribus-dir.py from inside Scribus with Scripter -> Execute Script
and from running it from the command line with /u/scribus15p3bin/bin/scribus-1.5.4.svn -g -py scribus-dir.py
When it is run from the command line, it is missing about 125 items, including the ALIGN_* items and PDFfile.

I think that it has the items in scribus_methods[] but not the items in initscribus().
I put in debug code, and I think that it is not calling initscribus() before running a script from the command line.
show-commands.py (873 bytes)   
#!/usr/bin/env python
# -*- coding: utf-8 -*-

""" Show all scribus commands. """

import sys

try:
    from scribus import *
except ImportError:
    print("This script only runs from within Scribus.")
    sys.exit(1)

import os

d = dir(scribus)
for j in d:
   try:
       exec('res = '+j+'.__doc__')
       if res[0:5] == 'float':
           print('\nCONSTANT:\n',j,'\nVALUE: float')
           exec('print '+j+'\n')
       elif res[0:5] == 'int(x':
           print('\nCONSTANT:\n',j,'\nVALUE: integer')
           exec('print '+j+'\n')
       elif res[0:5] == 'tuple':
           print('\nTUPLE:\n',j,'\nVALUE:')
           exec('print repr('+j+')\n')
       elif res[0:4] == 'str(':
           print('\nSTRING:\n',j,'\nVALUE:')
           exec('print repr('+j+')\n')
       else:
           print('\nFUNCTION:\n'+j+'\n\nSINTAX:')
           print(res)
   except: pass
show-commands.py (873 bytes)   
scribus-dir.py (162 bytes)   
#!/usr/bin/env python
# -*- coding: utf-8 -*-

""" Show all scribus commands. """

from scribus import *
print('--start--')
print(dir(scribus))
print('--end--')

scribus-dir.py (162 bytes)   
export_to_pdf.py (1,705 bytes)   
#!/usr/bin/env python
# -*- coding: utf-8 -*-

""" 
Convert a document to a PDF

Run with a command like
        scribus -g -py export_to_pdf.py -version 13 -useDocBleeds 0 -bleedr 2 -compress 1 -info 'test title' -file 'test.pdf' -pages '[1, 2]' -- testdoc.sla

You can set any "pdf" attribute with "-attribute value".

Tested with scribus 1.5.2.svn r21147

Author: William Bader, Director of Research and Development, SCS, http://www.newspapersystems.com
15Sep15 wb		initial version
31Mar16 Jural Fedel	simplified, added support for page ranges

"""

import scribus
import sys
import ast

def main(argv):
        pdf = scribus.PDFfile()
        i = 1
        while i < len(argv):
                if (argv[i][0] != '-'):
                        raise Exception("PDF option expected instead of: '{0}'".format(argv[i]))
                name = argv[i][1:]
                pdf_attr = getattr(pdf, name)
                i = i + 1
                try:
                        value = argv[i]
                except:
                        msg = "Option '{0}' require value".format(name)
                        raise Exception(msg)
                if isinstance(pdf_attr, basestring):
                        setattr(pdf, name, value)
                else:
                        val = None
                        try:
                                val = ast.literal_eval(value)
                        except:
                                msg = "'{0}' =/= '{1}'".format(name, value)
                                raise ValueError(msg)
                        setattr(pdf, name, val)
                i = i + 1
        pdf.save()

# start the script
if __name__ == '__main__':
        main(sys.argv)

export_to_pdf.py (1,705 bytes)   
scribus-dir-from-inside-scribus.txt (6,761 bytes)   
--start--
['ALIGN_BLOCK', 'ALIGN_CENTERED', 'ALIGN_FORCED', 'ALIGN_LEFT', 'ALIGN_RIGHT', 'BUTTON_ABORT', 'BUTTON_CANCEL', 'BUTTON_DEFAULT', 'BUTTON_IGNORE', 'BUTTON_NO', 'BUTTON_NONE', 'BUTTON_OK', 'BUTTON_RETRY', 'BUTTON_YES', 'CAP_FLAT', 'CAP_ROUND', 'CAP_SQUARE', 'COLOR', 'COLOR_BURN', 'COLOR_DODGE', 'DARKEN', 'DIFFERENCE', 'DIRECTION_LTR', 'DIRECTION_RTL', 'EXCLUSION', 'FACINGPAGES', 'FILL_CROSSDIAGONALG', 'FILL_DIAGONALG', 'FILL_HORIZONTALG', 'FILL_NOG', 'FILL_RADIALG', 'FILL_VERTICALG', 'FIRSTPAGELEFT', 'FIRSTPAGERIGHT', 'HARD_LIGHT', 'HUE', 'ICON_CRITICAL', 'ICON_INFORMATION', 'ICON_NONE', 'ICON_WARNING', 'ImageExport', 'JOIN_BEVEL', 'JOIN_MITTER', 'JOIN_ROUND', 'LANDSCAPE', 'LIGHTEN', 'LINE_DASH', 'LINE_DASHDOT', 'LINE_DASHDOTDOT', 'LINE_DOT', 'LINE_SOLID', 'LUMINOSITY', 'MULTIPLY', 'NOFACINGPAGES', 'NORMAL', 'NameExistsError', 'NoDocOpenError', 'NoValidObjectError', 'NotFoundError', 'OVERLAY', 'PAGE_1', 'PAGE_2', 'PAGE_3', 'PAGE_4', 'PAPER_A0', 'PAPER_A1', 'PAPER_A2', 'PAPER_A3', 'PAPER_A4', 'PAPER_A5', 'PAPER_A6', 'PAPER_A7', 'PAPER_A8', 'PAPER_A9', 'PAPER_B0', 'PAPER_B1', 'PAPER_B10', 'PAPER_B2', 'PAPER_B3', 'PAPER_B4', 'PAPER_B5', 'PAPER_B6', 'PAPER_B7', 'PAPER_B8', 'PAPER_B9', 'PAPER_C5E', 'PAPER_COMM10E', 'PAPER_DLE', 'PAPER_EXECUTIVE', 'PAPER_FOLIO', 'PAPER_LEDGER', 'PAPER_LEGAL', 'PAPER_LETTER', 'PAPER_TABLOID', 'PDFfile', 'PORTRAIT', 'Printer', 'SATURATION', 'SCREEN', 'SOFT_LIGHT', 'ScribusException', 'UNIT_C', 'UNIT_CENTIMETRES', 'UNIT_CICERO', 'UNIT_CM', 'UNIT_IN', 'UNIT_INCHES', 'UNIT_MILLIMETERS', 'UNIT_MM', 'UNIT_P', 'UNIT_PICAS', 'UNIT_POINTS', 'UNIT_PT', 'WrongFrameTypeError', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'applyMasterPage', 'builtins', 'c', 'changeColor', 'changeColorCMYK', 'changeColorCMYKFloat', 'changeColorLab', 'changeColorRGB', 'changeColorRGBFloat', 'closeDoc', 'closeMasterPage', 'cm', 'copyObject', 'createBezierLine', 'createCharStyle', 'createCustomLineStyle', 'createEllipse', 'createImage', 'createLayer', 'createLine', 'createMasterPage', 'createParagraphStyle', 'createPathText', 'createPdfAnnotation', 'createPolyLine', 'createPolygon', 'createRect', 'createTable', 'createText', 'currentPage', 'defineColor', 'defineColorCMYK', 'defineColorCMYKFloat', 'defineColorLab', 'defineColorRGB', 'defineColorRGBFloat', 'dehyphenateText', 'deleteColor', 'deleteLayer', 'deleteMasterPage', 'deleteObject', 'deletePage', 'deleteText', 'deselectAll', 'docChanged', 'duplicateObject', 'duplicateObject_legacy', 'editMasterPage', 'fileDialog', 'fileQuit', 'flipObject', 'getActiveLayer', 'getAllObjects', 'getAllStyles', 'getAllText', 'getCellColumnSpan', 'getCellFillColor', 'getCellRowSpan', 'getCellStyle', 'getCharStyles', 'getColor', 'getColorAsRGB', 'getColorAsRGBFloat', 'getColorFloat', 'getColorNames', 'getColumnGap', 'getColumns', 'getCornerRadius', 'getCustomLineStyle', 'getDocName', 'getFillBlendmode', 'getFillColor', 'getFillShade', 'getFillTransparency', 'getFont', 'getFontFeatures', 'getFontNames', 'getFontSize', 'getGuiLanguage', 'getHGuides', 'getImageFile', 'getImageScale', 'getLayerBlendmode', 'getLayerTransparency', 'getLayers', 'getLineBlendmode', 'getLineCap', 'getLineColor', 'getLineJoin', 'getLineShade', 'getLineSpacing', 'getLineStyle', 'getLineTransparency', 'getLineWidth', 'getMasterPage', 'getObjectAttributes', 'getObjectType', 'getPageItems', 'getPageMargins', 'getPageNMargins', 'getPageNSize', 'getPageSize', 'getPageType', 'getPosition', 'getProperty', 'getPropertyCType', 'getPropertyNames', 'getRotation', 'getSelectedObject', 'getSize', 'getTableColumnWidth', 'getTableColumns', 'getTableFillColor', 'getTableRowHeight', 'getTableRows', 'getTableStyle', 'getText', 'getTextColor', 'getTextDistances', 'getTextLength', 'getTextLines', 'getTextShade', 'getUnit', 'getVGuides', 'getXFontNames', 'getval', 'gotoPage', 'groupObjects', 'haveDoc', 'hyphenateText', 'importPage', 'inch', 'insertHtmlText', 'insertTableColumns', 'insertTableRows', 'insertText', 'isAnnotated', 'isLayerFlow', 'isLayerLocked', 'isLayerOutlined', 'isLayerPrintable', 'isLayerVisible', 'isLocked', 'isPDFBookmark', 'isSpotColor', 'linkTextFrames', 'loadImage', 'loadStylesFromFile', 'lockObject', 'mainInterpreter', 'mainWindow', 'masterPageNames', 'mergeTableCells', 'messageBox', 'messagebarText', 'mm', 'moveObject', 'moveObjectAbs', 'moveSelectionToBack', 'moveSelectionToFront', 'newDoc', 'newDocDialog', 'newDocument', 'newPage', 'newStyleDialog', 'objectExists', 'openDoc', 'p', 'pageCount', 'pageDimension', 'pasteObject', 'placeEPS', 'placeODG', 'placeSVG', 'placeSXD', 'placeVectorFile', 'progressReset', 'progressSet', 'progressTotal', 'pt', 'qApp', 'readPDFOptions', 'redrawAll', 'removeTableColumns', 'removeTableRows', 'renameObject', 'renderFont', 'replaceColor', 'resizeTableColumn', 'resizeTableRow', 'retval', 'rotateObject', 'rotateObjectAbs', 'saveDoc', 'saveDocAs', 'savePDFOptions', 'savePageAsEPS', 'scaleGroup', 'scaleImage', 'scribus_version', 'scribus_version_info', 'scrollDocument', 'selectObject', 'selectText', 'selectionCount', 'sentToLayer', 'setActiveLayer', 'setBaseLine', 'setCellBottomBorder', 'setCellBottomPadding', 'setCellFillColor', 'setCellLeftBorder', 'setCellLeftPadding', 'setCellRightBorder', 'setCellRightPadding', 'setCellStyle', 'setCellText', 'setCellTopBorder', 'setCellTopPadding', 'setCharacterStyle', 'setColumnGap', 'setColumns', 'setCornerRadius', 'setCursor', 'setCustomLineStyle', 'setDocType', 'setFileAnnotation', 'setFillBlendmode', 'setFillColor', 'setFillShade', 'setFillTransparency', 'setFont', 'setFontFeatures', 'setFontSize', 'setGradientFill', 'setGradientStop', 'setHGuides', 'setImageBrightness', 'setImageGrayscale', 'setImageOffset', 'setImageScale', 'setInfo', 'setLayerBlendmode', 'setLayerFlow', 'setLayerLocked', 'setLayerOutlined', 'setLayerPrintable', 'setLayerTransparency', 'setLayerVisible', 'setLineBlendmode', 'setLineCap', 'setLineColor', 'setLineJoin', 'setLineShade', 'setLineSpacing', 'setLineSpacingMode', 'setLineStyle', 'setLineTransparency', 'setLineWidth', 'setLinkAnnotation', 'setMargins', 'setMultiLine', 'setNewName', 'setObjectAttributes', 'setPDFBookmark', 'setProperty', 'setRedraw', 'setScaleImageToFrame', 'setSpotColor', 'setStyle', 'setTableBottomBorder', 'setTableFillColor', 'setTableLeftBorder', 'setTableRightBorder', 'setTableStyle', 'setTableTopBorder', 'setText', 'setTextAlignment', 'setTextAnnotation', 'setTextColor', 'setTextDirection', 'setTextDistances', 'setTextScalingH', 'setTextScalingV', 'setTextShade', 'setTextStroke', 'setURIAnnotation', 'setUnit', 'setVGuides', 'sizeObject', 'statusMessage', 'textFlowMode', 'textOverflows', 'traceText', 'unGroupObject', 'unlinkTextFrames', 'valueDialog', 'warnings', 'zoomDocument']
--end--
scribus-dir-from-command-line.txt (5,026 bytes)   
--start--
['__doc__', '__loader__', '__name__', '__package__', '__spec__', '_ia', 'applyMasterPage', 'changeColor', 'changeColorCMYK', 'changeColorCMYKFloat', 'changeColorLab', 'changeColorRGB', 'changeColorRGBFloat', 'closeDoc', 'closeMasterPage', 'copyObject', 'createBezierLine', 'createCharStyle', 'createCustomLineStyle', 'createEllipse', 'createImage', 'createLayer', 'createLine', 'createMasterPage', 'createParagraphStyle', 'createPathText', 'createPdfAnnotation', 'createPolyLine', 'createPolygon', 'createRect', 'createTable', 'createText', 'currentPage', 'defineColor', 'defineColorCMYK', 'defineColorCMYKFloat', 'defineColorLab', 'defineColorRGB', 'defineColorRGBFloat', 'dehyphenateText', 'deleteColor', 'deleteLayer', 'deleteMasterPage', 'deleteObject', 'deletePage', 'deleteText', 'deselectAll', 'docChanged', 'duplicateObject', 'duplicateObject_legacy', 'editMasterPage', 'fileDialog', 'fileQuit', 'flipObject', 'getActiveLayer', 'getAllObjects', 'getAllStyles', 'getAllText', 'getCellColumnSpan', 'getCellFillColor', 'getCellRowSpan', 'getCellStyle', 'getCharStyles', 'getColor', 'getColorAsRGB', 'getColorAsRGBFloat', 'getColorFloat', 'getColorNames', 'getColumnGap', 'getColumns', 'getCornerRadius', 'getCustomLineStyle', 'getDocName', 'getFillBlendmode', 'getFillColor', 'getFillShade', 'getFillTransparency', 'getFont', 'getFontFeatures', 'getFontNames', 'getFontSize', 'getGuiLanguage', 'getHGuides', 'getImageFile', 'getImageScale', 'getLayerBlendmode', 'getLayerTransparency', 'getLayers', 'getLineBlendmode', 'getLineCap', 'getLineColor', 'getLineJoin', 'getLineShade', 'getLineSpacing', 'getLineStyle', 'getLineTransparency', 'getLineWidth', 'getMasterPage', 'getObjectAttributes', 'getObjectType', 'getPageItems', 'getPageMargins', 'getPageNMargins', 'getPageNSize', 'getPageSize', 'getPageType', 'getPosition', 'getProperty', 'getPropertyCType', 'getPropertyNames', 'getRotation', 'getSelectedObject', 'getSize', 'getTableColumnWidth', 'getTableColumns', 'getTableFillColor', 'getTableRowHeight', 'getTableRows', 'getTableStyle', 'getText', 'getTextColor', 'getTextDistances', 'getTextLength', 'getTextLines', 'getTextShade', 'getUnit', 'getVGuides', 'getXFontNames', 'getval', 'gotoPage', 'groupObjects', 'haveDoc', 'hyphenateText', 'importPage', 'insertHtmlText', 'insertTableColumns', 'insertTableRows', 'insertText', 'isAnnotated', 'isLayerFlow', 'isLayerLocked', 'isLayerOutlined', 'isLayerPrintable', 'isLayerVisible', 'isLocked', 'isPDFBookmark', 'isSpotColor', 'linkTextFrames', 'loadImage', 'loadStylesFromFile', 'lockObject', 'mainInterpreter', 'masterPageNames', 'mergeTableCells', 'messageBox', 'messagebarText', 'moveObject', 'moveObjectAbs', 'moveSelectionToBack', 'moveSelectionToFront', 'newDoc', 'newDocDialog', 'newDocument', 'newPage', 'newStyleDialog', 'objectExists', 'openDoc', 'pageCount', 'pageDimension', 'pasteObject', 'placeEPS', 'placeODG', 'placeSVG', 'placeSXD', 'placeVectorFile', 'progressReset', 'progressSet', 'progressTotal', 'readPDFOptions', 'redrawAll', 'removeTableColumns', 'removeTableRows', 'renameObject', 'renderFont', 'replaceColor', 'resizeTableColumn', 'resizeTableRow', 'retval', 'rotateObject', 'rotateObjectAbs', 'saveDoc', 'saveDocAs', 'savePDFOptions', 'savePageAsEPS', 'scaleGroup', 'scaleImage', 'scrollDocument', 'selectObject', 'selectText', 'selectionCount', 'sentToLayer', 'setActiveLayer', 'setBaseLine', 'setCellBottomBorder', 'setCellBottomPadding', 'setCellFillColor', 'setCellLeftBorder', 'setCellLeftPadding', 'setCellRightBorder', 'setCellRightPadding', 'setCellStyle', 'setCellText', 'setCellTopBorder', 'setCellTopPadding', 'setCharacterStyle', 'setColumnGap', 'setColumns', 'setCornerRadius', 'setCursor', 'setCustomLineStyle', 'setDocType', 'setFileAnnotation', 'setFillBlendmode', 'setFillColor', 'setFillShade', 'setFillTransparency', 'setFont', 'setFontFeatures', 'setFontSize', 'setGradientFill', 'setGradientStop', 'setHGuides', 'setImageBrightness', 'setImageGrayscale', 'setImageOffset', 'setImageScale', 'setInfo', 'setLayerBlendmode', 'setLayerFlow', 'setLayerLocked', 'setLayerOutlined', 'setLayerPrintable', 'setLayerTransparency', 'setLayerVisible', 'setLineBlendmode', 'setLineCap', 'setLineColor', 'setLineJoin', 'setLineShade', 'setLineSpacing', 'setLineSpacingMode', 'setLineStyle', 'setLineTransparency', 'setLineWidth', 'setLinkAnnotation', 'setMargins', 'setMultiLine', 'setNewName', 'setObjectAttributes', 'setPDFBookmark', 'setProperty', 'setRedraw', 'setScaleImageToFrame', 'setSpotColor', 'setStyle', 'setTableBottomBorder', 'setTableFillColor', 'setTableLeftBorder', 'setTableRightBorder', 'setTableStyle', 'setTableTopBorder', 'setText', 'setTextAlignment', 'setTextAnnotation', 'setTextColor', 'setTextDirection', 'setTextDistances', 'setTextScalingH', 'setTextScalingV', 'setTextShade', 'setTextStroke', 'setURIAnnotation', 'setUnit', 'setVGuides', 'sizeObject', 'statusMessage', 'textFlowMode', 'textOverflows', 'traceText', 'unGroupObject', 'unlinkTextFrames', 'valueDialog', 'zoomDocument']
--end--

william

2018-02-24 21:29

updater   ~0044981

Just a note that a recent patch to scriptplugin.cpp will probably require a corresponding change the python3 patch. https://www.scribus.net/websvn/diff.php?repname=Scribus&rev=22407&path=/trunk/Scribus/scribus/plugins/scriptplugin/scriptplugin.cpp

u ltd.

2018-03-24 08:35

reporter   ~0045086

Thanks for the hints. I'm sorry that I cannot work on this till at least May/June. Then I will run 'svn up' and hope that there's no mountain of work to do ...

HJarausch

2018-11-05 15:03

reporter   ~0045576

Would anybody please an up-to-date version of all patches necessary to use Python3 with Scribus-1.5.4 or the SVN-version of Scribus?
Many thanks,
Helmut

cbradney

2019-08-03 08:28

administrator   ~0046427

@william or @u ltd. Are any of you using an updated patch? Now we have released 1.5.5, we want to get the python3 conversion done.

william

2019-08-03 23:09

updater   ~0046429

@cbradney I haven't looked at it since the last set of patches in Feb 2018, part for lack of time and part because the build overheats my laptop. It never worked right because something doesn't always get initialized. I suspect that it is only a few lines of code away from working, but the hard part is finding those lines. The patches will need a bit of work for the current version of Scribus due to recent renaming and refactoring in Scribus. I tried applying them to recent svn source and had 65 successful hunks and 87 failed hunks.
It would have been helpful if the patches would have been accepted in Feb 2018, even though they don't work completely, so that the code could have been kept updated for the renamings and refactorings. If you really need an updated patch and someone is ready to look at the python initialization issues, I could try to update the patches if no one else volunteers. I have Fedora 30 on my laptop now.

Archange

2019-08-07 14:31

reporter   ~0046447

Just as a side note, as I was looking for information regarding Python 3 support in Scribus, and initially found https://bugs.scribus.net/view.php?id=11207. Seems this is now an (older) duplicate, right?

william

2019-08-07 15:32

updater   ~0046448

@Archange I hadn't seen https://bugs.scribus.net/view.php?id=11207 by QuLogic before. It is 436 lines while the patch in this issue https://bugs.scribus.net/view.php?id=15030 by u ltd is 2608 lines. The 15030 patch is longer in part because it handles the changes in the implementation of text strings in python3. The 11207 patch notes "CMake will happily allow building scribus against Python 3, even though the code doesn't work with it" so it might never have worked, in part due to the string issue. The 15030 patch produces a working Scribus except that the initialization isn't right and sometimes when you run a python script, it doesn't see Scribus objects. It is unfortunate that the 11207 patch wasn't accepted (to give a start for other developers) and that commenters on the 11207 patch discouraged the author from continuing (since there aren't many people with the interest, time, and knowledge to help with the python3 port).

jghali

2019-10-23 09:52

administrator   ~0046839

I spent my last night trying to see where I could get with this Python 3 port. Good news: I managed to get a scripter which can execute some scripts. I started to look at the Scribus provided scripts and it appears they need quite a few modifications. The attached patch already contains a few fixes for these. The FontSample and CalendarWizard scripts appear to be functional. The other scripts are to still to be tested.

On the side note, I used a different approach than the first patches posted here : I completely dropped support for Python 2. The distros have started the process intended at removing Python 2 from their repositories. So in this situation and given how long we may have to support 1.6.x when it will be released, I just preferred to get away with Python 2. For the Python strings manipulation, I also favored the Python 3 way, ie I mostly used the PyUnicode_* functions in my patch.

Fyi, I used Python 3.7.4 to build on Windows and only did the minimal modifications to the CMakeLists.txt. As Craig has recently changed the Python detection cmake code, there may be some more changes for Python 3 to be detected correctly.
15030_python3_jghali.patch (140,567 bytes)   
Index: CMakeLists_Dependencies.cmake
===================================================================
--- CMakeLists_Dependencies.cmake	(revision 23269)
+++ CMakeLists_Dependencies.cmake	(working copy)
@@ -144,8 +144,8 @@
 #	set(COMPILE_PYTHON ON)
 #endif()
 #
-find_package (Python2 REQUIRED COMPONENTS Interpreter Development)
-if (Python2_Development_FOUND)
+find_package (Python3 REQUIRED COMPONENTS Interpreter Development)
+if (Python3_Development_FOUND)
 	message("Python Library Found OK")
 	set(HAVE_PYTHON ON)
 	set(COMPILE_PYTHON ON)
Index: scribus/main_win32.cpp
===================================================================
--- scribus/main_win32.cpp	(revision 23269)
+++ scribus/main_win32.cpp	(working copy)
@@ -153,11 +153,13 @@
 	QString pythonHome = appPath + "/python";
 	if (!QDir(pythonHome).exists())
 		return; //assume a custom python
+	pythonHome = QFileInfo(pythonHome).canonicalFilePath();
 
 	QString tmp = "PYTHONHOME=" + QDir::toNativeSeparators(pythonHome);
 	_wputenv((const wchar_t*) tmp.utf16());
 
-	QString nativePath = QDir::toNativeSeparators(appPath);
+	QString nativePath = QFileInfo(appPath).canonicalFilePath();
+	nativePath = QDir::toNativeSeparators(nativePath);
 	tmp = "PYTHONPATH=";
 	tmp += nativePath;
 	tmp += "\\python;";
Index: scribus/plugins/scriptplugin/cmdannotations.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdannotations.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/cmdannotations.cpp	(working copy)
@@ -169,7 +169,7 @@
 		break;
 	}
 
-	PyObject *rstr = PyString_FromString(rv.toUtf8());
+	PyObject *rstr = PyUnicode_FromString(rv.toUtf8());
 	return rstr;
 }
 
@@ -211,8 +211,8 @@
 
 			getLinkData(drv, a.Ziel(), a.Action());
 			const char path[] = "path";
-			PyObject *pathkey = PyString_FromString(path);
-			PyObject *pathvalue = PyString_FromString(a.Extern().toUtf8());
+			PyObject *pathkey = PyUnicode_FromString(path);
+			PyObject *pathvalue = PyUnicode_FromString(a.Extern().toUtf8());
 			PyDict_SetItem(drv, pathkey, pathvalue);
 			add_text_to_dict(drv, item);
 			PyObject *rv = Py_BuildValue("(sO)", name3, drv);
@@ -221,8 +221,8 @@
 		if (atype == Annotation::Link && actype == Annotation::Action_URI)
 		{
 			const char uri[] = "uri";
-			PyObject *ukey = PyString_FromString(uri);
-			PyObject *uval = PyString_FromString(a.Extern().toUtf8());
+			PyObject *ukey = PyUnicode_FromString(uri);
+			PyObject *uval = PyUnicode_FromString(a.Extern().toUtf8());
 			PyDict_SetItem(drv, ukey, uval);
 			add_text_to_dict(drv, item);
 			char *name4= const_cast<char*>("Link URI");
@@ -295,12 +295,12 @@
 			};
 			if (icon >= 0 && icon < 9)
 			{
-				PyObject *iconkey = PyString_FromString("icon");
-				PyObject *iconvalue = PyString_FromString(icons[icon]);
+				PyObject *iconkey = PyUnicode_FromString("icon");
+				PyObject *iconvalue = PyUnicode_FromString(icons[icon]);
 				PyDict_SetItem(drv, iconkey, iconvalue);
 			}
 
-			PyObject *openkey = PyString_FromString("open");
+			PyObject *openkey = PyUnicode_FromString("open");
 			PyObject *open = Py_False;
 			if (a.IsAnOpen())
 				open = Py_True;
@@ -585,7 +585,7 @@
 			break;
 	}
 	
-	return PyString_FromString(m_doc->Items->at(i)->itemName().toUtf8());
+	return PyUnicode_FromString(m_doc->Items->at(i)->itemName().toUtf8());
 }
 
 
@@ -613,8 +613,8 @@
 	int x, y;
 
 	const char pagenum[] = "page";
-	PyObject *pagekey = PyString_FromString(pagenum);
-	PyObject *pagevalue = PyInt_FromLong((long)page);
+	PyObject *pagekey = PyUnicode_FromString(pagenum);
+	PyObject *pagevalue = PyLong_FromLong((long)page);
 	PyDict_SetItem(rv, pagekey, pagevalue);
 	
 	QStringList qsl = action.split(" ", QString::SkipEmptyParts);
@@ -621,15 +621,15 @@
 
 	x = qsl[0].toInt();
 	const char x2[] = "x";
-	PyObject *xkey = PyString_FromString(x2);
-	PyObject *xvalue = PyInt_FromLong((long)x);
+	PyObject *xkey = PyUnicode_FromString(x2);
+	PyObject *xvalue = PyLong_FromLong((long)x);
 	PyDict_SetItem(rv, xkey, xvalue);
 
 	int height =ScCore->primaryMainWindow()->doc->pageHeight();
 	y = height - qsl[1].toInt();
 	const char y2[] = "y";
-	PyObject *ykey = PyString_FromString(y2);
-	PyObject *yvalue = PyInt_FromLong((long)y);
+	PyObject *ykey = PyUnicode_FromString(y2);
+	PyObject *yvalue = PyLong_FromLong((long)y);
 	PyDict_SetItem(rv, ykey, yvalue);
 
 	return rv;
@@ -670,9 +670,9 @@
 static void add_text_to_dict(PyObject *drv, PageItem * item)
 {
 	const char text[] = "text";
-	PyObject *textkey = PyString_FromString(text);
+	PyObject *textkey = PyUnicode_FromString(text);
 	QString txt = item->itemText.text(0, item->itemText.length());
-	PyObject *textvalue = PyString_FromString(txt.toUtf8());
+	PyObject *textvalue = PyUnicode_FromString(txt.toUtf8());
 	PyDict_SetItem(drv, textkey, textvalue);
 
 	Annotation &a = item->annotation();
@@ -681,8 +681,8 @@
 	if (actype == Annotation::Action_JavaScript)
 	{
 		const char text[] = "javascript";
-		PyObject *jskey = PyString_FromString(text);
-		PyObject *jsvalue = PyString_FromString(item->annotation().Action().toUtf8());
+		PyObject *jskey = PyUnicode_FromString(text);
+		PyObject *jsvalue = PyUnicode_FromString(item->annotation().Action().toUtf8());
 		PyDict_SetItem(drv, jskey, jsvalue);
 	}
 
@@ -694,10 +694,10 @@
 						"Named", nullptr };
 
 	const char action[] = "action";
-	PyObject *akey = PyString_FromString(action);
+	PyObject *akey = PyUnicode_FromString(action);
 	if (actype > 10)
 		actype = 6;
-	PyObject *avalue = PyString_FromString(aactions[actype]);
+	PyObject *avalue = PyUnicode_FromString(aactions[actype]);
 	PyDict_SetItem(drv, akey, avalue);
 
 	int atype = a.Type();
@@ -704,7 +704,7 @@
 	if (atype == Annotation::Checkbox || atype == Annotation::RadioButton)
 	{
 		const char checked[] = "checked";
-		PyObject *checkkey = PyString_FromString(checked);
+		PyObject *checkkey = PyUnicode_FromString(checked);
 		PyObject *checkvalue = Py_False;
 		if (a.IsChk())
 			checkvalue = Py_True;
@@ -714,7 +714,7 @@
 	if (atype == Annotation::Combobox || atype == Annotation::Listbox)
 	{
 		const char editable[] = "editable";
-		PyObject *ekey = PyString_FromString(editable);
+		PyObject *ekey = PyUnicode_FromString(editable);
 
 		PyObject *edit = Py_False;
 		int result = Annotation::Flag_Edit & a.Flag();
Index: scribus/plugins/scriptplugin/cmdcell.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdcell.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/cmdcell.cpp	(working copy)
@@ -61,7 +61,7 @@
 		PyErr_SetString(PyExc_ValueError, QObject::tr("The cell %1,%2 does not exist in table", "python error").arg(row).arg(column).toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyString_FromString(table->cellAt(row, column).styleName().toUtf8());
+	return PyUnicode_FromString(table->cellAt(row, column).styleName().toUtf8());
 }
 
 PyObject *scribus_setcellstyle(PyObject* /* self */, PyObject* args)
@@ -108,7 +108,7 @@
 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get cell row span from non-table item.","python error").toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyInt_FromLong(static_cast<long>(table->cellAt(row, column).rowSpan()));
+	return PyLong_FromLong(static_cast<long>(table->cellAt(row, column).rowSpan()));
 }
 
 PyObject *scribus_getcellcolumnspan(PyObject* /* self */, PyObject* args)
@@ -128,7 +128,7 @@
 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get cell column span from non-table item.","python error").toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyInt_FromLong(static_cast<long>(table->cellAt(row, column).columnSpan()));
+	return PyLong_FromLong(static_cast<long>(table->cellAt(row, column).columnSpan()));
 }
 
 PyObject *scribus_getcellfillcolor(PyObject* /* self */, PyObject* args)
@@ -153,7 +153,7 @@
 		PyErr_SetString(PyExc_ValueError, QObject::tr("The cell %1,%2 does not exist in table", "python error").arg(row).arg(column).toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyString_FromString(table->cellAt(row, column).fillColor().toUtf8());
+	return PyUnicode_FromString(table->cellAt(row, column).fillColor().toUtf8());
 }
 
 PyObject *scribus_setcellfillcolor(PyObject* /* self */, PyObject* args)
Index: scribus/plugins/scriptplugin/cmdcolor.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdcolor.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/cmdcolor.cpp	(working copy)
@@ -22,7 +22,7 @@
 	l = PyList_New(edc.count());
 	for (it = edc.begin(); it != edc.end(); ++it)
 	{
-		PyList_SetItem(l, cc, PyString_FromString(it.key().toUtf8()));
+		PyList_SetItem(l, cc, PyUnicode_FromString(it.key().toUtf8()));
 		cc++;
 	}
 	return l;
Index: scribus/plugins/scriptplugin/cmddialog.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmddialog.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/cmddialog.cpp	(working copy)
@@ -21,7 +21,7 @@
 	QApplication::changeOverrideCursor(QCursor(Qt::ArrowCursor));
 	bool ret = ScCore->primaryMainWindow()->slotFileNew();
 	QApplication::changeOverrideCursor(Qt::ArrowCursor);
-	return PyInt_FromLong(static_cast<long>(ret));
+	return PyLong_FromLong(static_cast<long>(ret));
 }
 
 PyObject *scribus_filedia(PyObject* /* self */, PyObject* args, PyObject* kw)
@@ -68,7 +68,7 @@
 										);
 //	QApplication::restoreOverrideCursor();
 	// FIXME: filename return unicode OK?
-	return PyString_FromString(fName.toUtf8());
+	return PyUnicode_FromString(fName.toUtf8());
 }
 
 PyObject *scribus_messdia(PyObject* /* self */, PyObject* args, PyObject* kw)
@@ -103,7 +103,7 @@
 	}
 	result = mb.exec();
 //	QApplication::restoreOverrideCursor();
-	return PyInt_FromLong(static_cast<long>(result));
+	return PyLong_FromLong(static_cast<long>(result));
 }
 
 PyObject *scribus_valdialog(PyObject* /* self */, PyObject* args)
@@ -120,7 +120,7 @@
 										QLineEdit::Normal,
 										QString::fromUtf8(value));
 //	QApplication::restoreOverrideCursor();
-	return PyString_FromString(txt.toUtf8());
+	return PyUnicode_FromString(txt.toUtf8());
 }
 
 PyObject *scribus_newstyledialog(PyObject*, PyObject* args)
@@ -143,7 +143,7 @@
 		st.create(p);
 		d->redefineStyles(st, false);
 		ScCore->primaryMainWindow()->styleMgr()->setDoc(d);
-		return PyString_FromString(s.toUtf8());
+		return PyUnicode_FromString(s.toUtf8());
 	}
 	Py_RETURN_NONE;
 }
Index: scribus/plugins/scriptplugin/cmddoc.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmddoc.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/cmddoc.cpp	(working copy)
@@ -74,7 +74,7 @@
 								orientation, firstPageNr, "Custom", true, numPages);
 	ScCore->primaryMainWindow()->doc->setPageSetFirstPage(pagesType, firstPageOrder);
 
-	return PyInt_FromLong(static_cast<long>(ret));
+	return PyLong_FromLong(static_cast<long>(ret));
 }
 
 PyObject *scribus_newdoc(PyObject* /* self */, PyObject* args)
@@ -109,7 +109,7 @@
 	btr = value2pts(btr, unit);
 	bool ret = ScCore->primaryMainWindow()->doFileNew(b, h, tpr, lr, rr, btr, 0, 1, false, ds, unit, fsl, ori, fNr, "Custom", true);
 	//	qApp->processEvents();
-	return PyInt_FromLong(static_cast<long>(ret));
+	return PyLong_FromLong(static_cast<long>(ret));
 }
 
 PyObject *scribus_setmargins(PyObject* /* self */, PyObject* args)
@@ -160,12 +160,12 @@
 	ScCore->primaryMainWindow()->doc->setModified(false);
 	bool ret = ScCore->primaryMainWindow()->slotFileClose();
 	qApp->processEvents();
-	return PyInt_FromLong(static_cast<long>(ret));
+	return PyLong_FromLong(static_cast<long>(ret));
 }
 
 PyObject *scribus_havedoc(PyObject* /* self */)
 {
-	return PyInt_FromLong(static_cast<long>(ScCore->primaryMainWindow()->HaveDoc));
+	return PyLong_FromLong(static_cast<long>(ScCore->primaryMainWindow()->HaveDoc));
 }
 
 PyObject *scribus_opendoc(PyObject* /* self */, PyObject* args)
@@ -199,9 +199,9 @@
 		return nullptr;
 	if (! ScCore->primaryMainWindow()->doc->hasName)
 	{
-		return PyString_FromString("");
+		return PyUnicode_FromString("");
 	}
-	return PyString_FromString(ScCore->primaryMainWindow()->doc->documentFileName().toUtf8());
+	return PyUnicode_FromString(ScCore->primaryMainWindow()->doc->documentFileName().toUtf8());
 }
 
 PyObject *scribus_savedocas(PyObject* /* self */, PyObject* args)
@@ -265,7 +265,7 @@
 {
 	if (!checkHaveDocument())
 		return nullptr;
-	return PyInt_FromLong(static_cast<long>(ScCore->primaryMainWindow()->doc->unitIndex()));
+	return PyLong_FromLong(static_cast<long>(ScCore->primaryMainWindow()->doc->unitIndex()));
 }
 
 PyObject *scribus_loadstylesfromfile(PyObject* /* self */, PyObject *args)
@@ -323,7 +323,7 @@
 	int n = 0;
 	for ( ; it != itEnd; ++it )
 	{
-		PyList_SET_ITEM(names, n++, PyString_FromString(it.key().toUtf8().data()) );
+		PyList_SET_ITEM(names, n++, PyUnicode_FromString(it.key().toUtf8().data()) );
 	}
 	return names;
 }
@@ -411,7 +411,7 @@
 		PyErr_SetString(PyExc_IndexError, QObject::tr("Page number out of range: '%1'.","python error").arg(e+1).toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyString_FromString(currentDoc->DocPages.at(e)->masterPageName().toUtf8());
+	return PyUnicode_FromString(currentDoc->DocPages.at(e)->masterPageName().toUtf8());
 }
 
 PyObject* scribus_applymasterpage(PyObject* /* self */, PyObject* args)
Index: scribus/plugins/scriptplugin/cmdgetprop.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdgetprop.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/cmdgetprop.cpp	(working copy)
@@ -44,7 +44,7 @@
 		result = "Multiple";
 	}
 
-	return PyString_FromString(result.toUtf8());
+	return PyUnicode_FromString(result.toUtf8());
 }
 
 PyObject *scribus_getfillcolor(PyObject* /* self */, PyObject* args)
@@ -57,7 +57,7 @@
 	PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
 	if (item == nullptr)
 		return nullptr;
-	return PyString_FromString(item->fillColor().toUtf8());
+	return PyUnicode_FromString(item->fillColor().toUtf8());
 }
 
 PyObject *scribus_getfilltrans(PyObject* /* self */, PyObject* args)
@@ -83,7 +83,7 @@
 	PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
 	if (item == nullptr)
 		return nullptr;
-	return PyInt_FromLong(static_cast<long>(item->fillBlendmode()));
+	return PyLong_FromLong(static_cast<long>(item->fillBlendmode()));
 }
 
 PyObject *scribus_getcustomlinestyle(PyObject* /* self */, PyObject* args)
@@ -96,7 +96,7 @@
 	PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
 	if (item == nullptr)
 		return nullptr;
-	return PyString_FromString(item->customLineStyle().toUtf8());
+	return PyUnicode_FromString(item->customLineStyle().toUtf8());
 }
 
 PyObject *scribus_getlinecolor(PyObject* /* self */, PyObject* args)
@@ -109,7 +109,7 @@
 	PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
 	if (item == nullptr)
 		return nullptr;
-	return PyString_FromString(item->lineColor().toUtf8());
+	return PyUnicode_FromString(item->lineColor().toUtf8());
 }
 
 PyObject *scribus_getlinetrans(PyObject* /* self */, PyObject* args)
@@ -135,7 +135,7 @@
 	PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
 	if (item == nullptr)
 		return nullptr;
-	return PyInt_FromLong(static_cast<long>(item->lineBlendmode()));
+	return PyLong_FromLong(static_cast<long>(item->lineBlendmode()));
 }
 
 PyObject *scribus_getlinewidth(PyObject* /* self */, PyObject* args)
@@ -161,7 +161,7 @@
 	PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
 	if (item == nullptr)
 		return nullptr;
-	return PyInt_FromLong(static_cast<long>(item->lineShade()));
+	return PyLong_FromLong(static_cast<long>(item->lineShade()));
 }
 
 PyObject *scribus_getlinejoin(PyObject* /* self */, PyObject* args)
@@ -174,7 +174,7 @@
 	PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
 	if (item == nullptr)
 		return nullptr;
-	return PyInt_FromLong(static_cast<long>(item->PLineJoin));
+	return PyLong_FromLong(static_cast<long>(item->PLineJoin));
 }
 
 PyObject *scribus_getlinecap(PyObject* /* self */, PyObject* args)
@@ -187,7 +187,7 @@
 	PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
 	if (item == nullptr)
 		return nullptr;
-	return PyInt_FromLong(static_cast<long>(item->PLineEnd));
+	return PyLong_FromLong(static_cast<long>(item->PLineEnd));
 }
 
 PyObject *scribus_getlinestyle(PyObject* /* self */, PyObject* args)
@@ -200,7 +200,7 @@
 	PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
 	if (item == nullptr)
 		return nullptr;
-	return PyInt_FromLong(static_cast<long>(item->PLineArt));
+	return PyLong_FromLong(static_cast<long>(item->PLineArt));
 }
 
 PyObject *scribus_getfillshade(PyObject* /* self */, PyObject* args)
@@ -213,7 +213,7 @@
 	PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
 	if (item == nullptr)
 		return nullptr;
-	return PyInt_FromLong(static_cast<long>(item->fillShade()));
+	return PyLong_FromLong(static_cast<long>(item->fillShade()));
 }
 
 PyObject *scribus_getcornerrad(PyObject* /* self */, PyObject* args)
@@ -226,7 +226,7 @@
 	PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
 	if (item == nullptr)
 		return nullptr;
-	return PyInt_FromLong(static_cast<long>(item->cornerRadius()));
+	return PyLong_FromLong(static_cast<long>(item->cornerRadius()));
 }
 
 PyObject *scribus_getimgoffset(PyObject* /* self */, PyObject* args)
@@ -265,7 +265,7 @@
 	PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
 	if (item == nullptr)
 		return nullptr;
-	return PyString_FromString(item->Pfile.toUtf8());
+	return PyUnicode_FromString(item->Pfile.toUtf8());
 }
 
 PyObject *scribus_getposi(PyObject* /* self */, PyObject* args)
@@ -358,13 +358,13 @@
 			{
 				if (currentDoc->Items->at(lam)->itemType() == typ)
 				{
-					PyList_SetItem(l, counter2, PyString_FromString(currentDoc->Items->at(lam)->itemName().toUtf8()));
+					PyList_SetItem(l, counter2, PyUnicode_FromString(currentDoc->Items->at(lam)->itemName().toUtf8()));
 					counter2++;
 				}
 			}
 			else
 			{
-				PyList_SetItem(l, counter2, PyString_FromString(currentDoc->Items->at(lam)->itemName().toUtf8()));
+				PyList_SetItem(l, counter2, PyUnicode_FromString(currentDoc->Items->at(lam)->itemName().toUtf8()));
 				counter2++;
 			}
 		}
@@ -431,7 +431,7 @@
 
 	const ScImage& pixm = item->pixm;
 	if (pixm.width() == 0 || pixm.height() == 0)
-		return PyInt_FromLong(static_cast<long>(-1));
+		return PyLong_FromLong(static_cast<long>(-1));
 
 	const ImageInfoRecord& iir = pixm.imgInfo;
 	int cspace = iir.colorspace;
@@ -442,7 +442,7 @@
 	Duotone = 3,
 	Monochrome = 4
 	*/
-	return PyInt_FromLong(static_cast<long>(cspace));
+	return PyLong_FromLong(static_cast<long>(cspace));
 }
 
 
Index: scribus/plugins/scriptplugin/cmdgetsetprop.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdgetsetprop.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/cmdgetsetprop.cpp	(working copy)
@@ -15,16 +15,16 @@
 
 QObject* getQObjectFromPyArg(PyObject* arg)
 {
-	if (PyString_Check(arg))
+	if (PyUnicode_Check(arg))
 		// It's a string. Look for a pageItem by that name. Do NOT accept a
 		// selection.
-		return getPageItemByName(QString::fromUtf8(PyString_AsString(arg)));
-	if (PyCObject_Check(arg))
+		return getPageItemByName(PyUnicode_asQString(arg));
+	if (PyCapsule_CheckExact(arg))
 	{
 		// It's a PyCObject, ie a wrapped pointer. Check it's not nullptr
 		// and return it.
 		// FIXME: Try to check that its a pointer to a QObject instance
-		QObject* tempObject = (QObject*)PyCObject_AsVoidPtr(arg);
+		QObject* tempObject = (QObject*) PyCapsule_GetPointer(arg, nullptr);
 		if (!tempObject)
 		{
 			PyErr_SetString(PyExc_TypeError, "INTERNAL: Passed nullptr PyCObject");
@@ -40,7 +40,7 @@
 
 PyObject* wrapQObject(QObject* obj)
 {
-	return PyCObject_FromVoidPtr((void*)obj, nullptr);
+	return PyCapsule_New((void*) obj, nullptr, nullptr);
 }
 
 
@@ -78,13 +78,13 @@
 	objArg = nullptr; // no need to decref, it's borrowed
 
 	// Look up the property and retrive its type information
-	const char* type = getpropertytype( (QObject*)obj, propertyname, includesuper);
+	const char* type = getpropertytype( (QObject*) obj, propertyname, includesuper);
 	if (type == nullptr)
 	{
 		PyErr_SetString(PyExc_KeyError, QObject::tr("Property not found").toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyString_FromString(type);
+	return PyUnicode_FromString(type);
 }
 
 PyObject* convert_QStringList_to_PyListObject(QStringList& origlist)
@@ -94,7 +94,7 @@
 		return nullptr;
 
 	for ( QStringList::Iterator it = origlist.begin(); it != origlist.end(); ++it )
-		if (PyList_Append(resultList, PyString_FromString((*it).toUtf8().data())) == -1)
+		if (PyList_Append(resultList, PyUnicode_FromString((*it).toUtf8().data())) == -1)
 			return nullptr;
 
 	return resultList;
@@ -283,9 +283,12 @@
 		resultobj = PyBool_FromLong(prop.toBool());
 	// STRING TYPES
 	else if (prop.type() == QVariant::ByteArray)
-		resultobj = PyString_FromString(prop.toByteArray().data());
+	{
+		QByteArray ba = prop.toByteArray();
+		resultobj = PyBytes_FromStringAndSize(ba.data(), ba.size());
+	}
 	else if (prop.type() == QVariant::String)
-		resultobj = PyString_FromString(prop.toString().toUtf8().data());
+		resultobj = PyUnicode_FromString(prop.toString().toUtf8().data());
 	// HIGHER ORDER TYPES
 	else if (prop.type() == QVariant::Point)
 	{
@@ -372,10 +375,10 @@
 			success = obj->setProperty(propertyName, 0);
 		else if (PyObject_IsTrue(objValue) == 1)
 			success = obj->setProperty(propertyName, 1);
-		else if (PyInt_Check(objValue))
-			success = obj->setProperty(propertyName, PyInt_AsLong(objValue) == 0);
 		else if (PyLong_Check(objValue))
 			success = obj->setProperty(propertyName, PyLong_AsLong(objValue) == 0);
+		else if (PyLong_Check(objValue))
+			success = obj->setProperty(propertyName, PyLong_AsLong(objValue) == 0);
 		else
 			matched = false;
 	}
@@ -382,10 +385,10 @@
 	else if (propertyType == "int")
 	{
 		matched = true;
-		if (PyInt_Check(objValue))
-			success = obj->setProperty(propertyName, (int)PyInt_AsLong(objValue));
+		if (PyLong_Check(objValue))
+			success = obj->setProperty(propertyName, (int) PyLong_AsLong(objValue));
 		else if (PyLong_Check(objValue))
-			success = obj->setProperty(propertyName, (int)PyLong_AsLong(objValue));
+			success = obj->setProperty(propertyName, (int) PyLong_AsLong(objValue));
 		else
 			matched = false;
 	}
@@ -402,8 +405,8 @@
 	else if (propertyType == "QString")
 	{
 		matched = true;
-		if (PyString_Check(objValue))
-			success = obj->setProperty(propertyName, QString::fromUtf8(PyString_AsString(objValue)));
+		if (PyBytes_Check(objValue))
+			success = obj->setProperty(propertyName, QString::fromUtf8(PyBytes_AsString(objValue)));
 		else if (PyUnicode_Check(objValue))
 		{
 			// Get a pointer to the internal buffer of the Py_Unicode object, which is UCS2 formatted
@@ -417,11 +420,11 @@
 	else if (propertyType == "QCString")
 	{
 		matched = true;
-		if (PyString_Check(objValue))
+		if (PyBytes_Check(objValue))
 		{
 			// FIXME: should raise an exception instead of mangling the string when
 			// out of charset chars present.
-			QString utfString = QString::fromUtf8(PyString_AsString(objValue));
+			QString utfString = QString::fromUtf8(PyBytes_AsString(objValue));
 			success = obj->setProperty(propertyName, utfString.toLatin1());
 		}
 		else if (PyUnicode_Check(objValue))
@@ -454,7 +457,7 @@
 		if (!objRepr)
 			return nullptr;
 		// Extract the repr() string
-		QString reprString = QString::fromUtf8(PyString_AsString(objRepr));
+		QString reprString = PyUnicode_asQString(objRepr);
 		Py_DECREF(objRepr);
 
 		// And return an error
Index: scribus/plugins/scriptplugin/cmdmani.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdmani.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/cmdmani.cpp	(working copy)
@@ -350,7 +350,7 @@
 
 PyObject *scribus_groupobj(PyObject* /* self */, PyObject* args)
 {
-	char *Name = const_cast<char*>("");
+	const char *Name = const_cast<char*>("");
 	PyObject *il = nullptr;
 	if (!PyArg_ParseTuple(args, "|O", &il))
 		return nullptr;
@@ -361,8 +361,8 @@
 		PyErr_SetString(PyExc_TypeError, QObject::tr("Need selection or argument list of items to group", "python error").toLocal8Bit().constData());
 		return nullptr;
 	}
-	Selection *tempSelection=nullptr;
-	Selection *finalSelection=nullptr;
+	Selection *tempSelection = nullptr;
+	Selection *finalSelection = nullptr;
 	//uint ap = ScCore->primaryMainWindow()->doc->currentPage()->pageNr();
 	// If we were passed a list of items to group...
 	if (il != nullptr)
@@ -374,7 +374,7 @@
 			// FIXME: We might need to explicitly get this string as utf8
 			// but as sysdefaultencoding is utf8 it should be a no-op to do
 			// so anyway.
-			Name = PyString_AsString(PyList_GetItem(il, i));
+			Name = PyUnicode_AsUTF8(PyList_GetItem(il, i));
 			PageItem *ic = GetUniqueItem(QString::fromUtf8(Name));
 			if (ic == nullptr)
 			{
@@ -383,10 +383,10 @@
 			}
 			tempSelection->addItem (ic, true);
 		}
-		finalSelection=tempSelection;
+		finalSelection = tempSelection;
 	}
 	else
-		finalSelection=ScCore->primaryMainWindow()->doc->m_Selection;
+		finalSelection = ScCore->primaryMainWindow()->doc->m_Selection;
 	if (finalSelection->count() < 2)
 	{
 		// We can't very well group only one item
@@ -400,7 +400,7 @@
 	finalSelection=nullptr;
 	delete tempSelection;
 	
-	return (group ? PyString_FromString(group->itemName().toUtf8()) : nullptr);
+	return (group ? PyUnicode_FromString(group->itemName().toUtf8()) : nullptr);
 }
 
 PyObject *scribus_ungroupobj(PyObject* /* self */, PyObject* args)
@@ -460,10 +460,11 @@
 		return nullptr;
 	if (!checkHaveDocument())
 		return nullptr;
-	if ((i < static_cast<int>(ScCore->primaryMainWindow()->doc->m_Selection->count())) && (i > -1))
-		return PyString_FromString(ScCore->primaryMainWindow()->doc->m_Selection->itemAt(i)->itemName().toUtf8());
+	Selection * selection = ScCore->primaryMainWindow()->doc->m_Selection;
+	if ((i < selection->count()) && (i > -1))
+		return PyUnicode_FromString(selection->itemAt(i)->itemName().toUtf8());
 	// FIXME: Should probably return None if no selection?
-	return PyString_FromString("");
+	return PyUnicode_FromString("");
 }
 
 PyObject *scribus_selcount(PyObject* /* self */)
@@ -470,7 +471,7 @@
 {
 	if (!checkHaveDocument())
 		return nullptr;
-	return PyInt_FromLong(static_cast<long>(ScCore->primaryMainWindow()->doc->m_Selection->count()));
+	return PyLong_FromLong(static_cast<long>(ScCore->primaryMainWindow()->doc->m_Selection->count()));
 }
 
 PyObject *scribus_selectobj(PyObject* /* self */, PyObject* args)
@@ -507,8 +508,8 @@
 		return nullptr;
 	item->toggleLock();
 	if (item->locked())
-		return PyInt_FromLong(1);
-	return PyInt_FromLong(0);
+		return PyLong_FromLong(1);
+	return PyLong_FromLong(0);
 }
 
 PyObject *scribus_islocked(PyObject* /* self */, PyObject* args)
Index: scribus/plugins/scriptplugin/cmdmisc.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdmisc.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/cmdmisc.cpp	(working copy)
@@ -47,7 +47,7 @@
 	{
 		if (it.current().usable())
 		{
-			PyList_SetItem(l, cc, PyString_FromString(it.currentKey().toUtf8()));
+			PyList_SetItem(l, cc, PyUnicode_FromString(it.currentKey().toUtf8()));
 			cc++;
 		}
 	}
@@ -110,8 +110,7 @@
 		// User specified no format, so use the historical default of PPM format.
 		format =  const_cast<char*>("PPM");
 	QPixmap pm = FontSample(PrefsManager::instance().appPrefs.fontPrefs.AvailFonts[QString::fromUtf8(Name)], Size, ts, Qt::white);
-	// If the user specified an empty filename, return the image data as
-	// a string. Otherwise, save it to disk.
+	// If the user specified an empty filename, return the image data as bytes. Otherwise, save it to disk.
 	if (QString::fromUtf8(FileName).isEmpty())
 	{
 		QByteArray buffer_string = "";
@@ -126,7 +125,7 @@
 		int bufferSize = buffer.size();
 		buffer.close();
 		// Now make a Python string from the data we generated
-		PyObject* stringPython = PyString_FromStringAndSize(buffer_string,bufferSize);
+		PyObject* stringPython = PyBytes_FromStringAndSize(buffer_string, bufferSize);
 		// Return even if the result is nullptr (error) since an exception will have been
 		// set in that case.
 		return stringPython;
@@ -150,10 +149,10 @@
 {
 	if (!checkHaveDocument())
 		return nullptr;
-	PyObject *l;
-	l = PyList_New(ScCore->primaryMainWindow()->doc->Layers.count());
-	for (int lam=0; lam < ScCore->primaryMainWindow()->doc->Layers.count(); lam++)
-		PyList_SetItem(l, lam, PyString_FromString(ScCore->primaryMainWindow()->doc->Layers[lam].Name.toUtf8()));
+	ScribusDoc* doc = ScCore->primaryMainWindow()->doc;
+	PyObject *l = PyList_New(doc->Layers.count());
+	for (int i = 0; i < doc->Layers.count(); i++)
+		PyList_SetItem(l, i, PyUnicode_FromString(doc->Layers[i].Name.toUtf8()));
 	return l;
 }
 
@@ -184,7 +183,7 @@
 {
 	if (!checkHaveDocument())
 		return nullptr;
-	return PyString_FromString(ScCore->primaryMainWindow()->doc->activeLayerName().toUtf8());
+	return PyUnicode_FromString(ScCore->primaryMainWindow()->doc->activeLayerName().toUtf8());
 }
 
 PyObject *scribus_senttolayer(PyObject* /* self */, PyObject* args)
@@ -474,7 +473,7 @@
 		PyErr_SetString(NotFoundError, QObject::tr("Layer not found.","python error").toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyInt_FromLong(static_cast<long>(i));
+	return PyLong_FromLong(static_cast<long>(i));
 }
 
 PyObject *scribus_glayerprint(PyObject* /* self */, PyObject* args)
@@ -505,7 +504,7 @@
 		PyErr_SetString(NotFoundError, QObject::tr("Layer not found.","python error").toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyInt_FromLong(static_cast<long>(i));
+	return PyLong_FromLong(static_cast<long>(i));
 }
 
 PyObject *scribus_glayerlock(PyObject* /* self */, PyObject* args)
@@ -536,7 +535,7 @@
 		PyErr_SetString(NotFoundError, QObject::tr("Layer not found.","python error").toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyInt_FromLong(static_cast<long>(i));
+	return PyLong_FromLong(static_cast<long>(i));
 }
 
 PyObject *scribus_glayeroutline(PyObject* /* self */, PyObject* args)
@@ -567,7 +566,7 @@
 		PyErr_SetString(NotFoundError, QObject::tr("Layer not found.","python error").toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyInt_FromLong(static_cast<long>(i));
+	return PyLong_FromLong(static_cast<long>(i));
 }
 
 PyObject *scribus_glayerflow(PyObject* /* self */, PyObject* args)
@@ -598,7 +597,7 @@
 		PyErr_SetString(NotFoundError, QObject::tr("Layer not found.","python error").toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyInt_FromLong(static_cast<long>(i));
+	return PyLong_FromLong(static_cast<long>(i));
 }
 
 PyObject *scribus_glayerblend(PyObject* /* self */, PyObject* args)
@@ -629,7 +628,7 @@
 		PyErr_SetString(NotFoundError, QObject::tr("Layer not found.","python error").toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyInt_FromLong(static_cast<long>(i));
+	return PyLong_FromLong(static_cast<long>(i));
 }
 
 PyObject *scribus_glayertrans(PyObject* /* self */, PyObject* args)
@@ -735,7 +734,7 @@
 
 PyObject *scribus_getlanguage(PyObject* /* self */)
 {
-	return PyString_FromString(ScCore->getGuiLanguage().toUtf8());
+	return PyUnicode_FromString(ScCore->getGuiLanguage().toUtf8());
 }
 
 /*! 04.01.2007 : Joachim Neu : Moves item selection to front. */
Index: scribus/plugins/scriptplugin/cmdobj.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdobj.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/cmdobj.cpp	(working copy)
@@ -31,19 +31,20 @@
 //		PyErr_SetString(NameExistsError, QObject::tr("An object with the requested name already exists.","python error"));
 //		return nullptr;
 //	}
-	int i = ScCore->primaryMainWindow()->doc->itemAdd(PageItem::Polygon, PageItem::Rectangle,
-								pageUnitXToDocX(x), pageUnitYToDocY(y),
-								ValueToPoint(w), ValueToPoint(h),
-								ScCore->primaryMainWindow()->doc->itemToolPrefs().shapeLineWidth,
-								ScCore->primaryMainWindow()->doc->itemToolPrefs().shapeFillColor, ScCore->primaryMainWindow()->doc->itemToolPrefs().shapeLineColor);
+	ScribusDoc* doc = ScCore->primaryMainWindow()->doc;
+	int i = doc->itemAdd(PageItem::Polygon, PageItem::Rectangle,
+						pageUnitXToDocX(x), pageUnitYToDocY(y),
+						ValueToPoint(w), ValueToPoint(h),
+						doc->itemToolPrefs().shapeLineWidth,
+						doc->itemToolPrefs().shapeFillColor, doc->itemToolPrefs().shapeLineColor);
 //	ScCore->primaryMainWindow()->doc->setRedrawBounding(ScCore->primaryMainWindow()->doc->Items->at(i));
 	if (strlen(Name) > 0)
 	{
 		QString objName = QString::fromUtf8(Name);
 		if (!ItemExists(objName))
-			ScCore->primaryMainWindow()->doc->Items->at(i)->setItemName(objName);
+			doc->Items->at(i)->setItemName(objName);
 	}
-	return PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
+	return PyUnicode_FromString(doc->Items->at(i)->itemName().toUtf8());
 }
 
 
@@ -69,7 +70,7 @@
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(i)->setItemName(objName);
 	}
-	return PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
+	return PyUnicode_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
 }
 
 
@@ -94,7 +95,7 @@
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(i)->setItemName(objName);
 	}
-	return PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
+	return PyUnicode_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
 }
 
 
@@ -119,7 +120,7 @@
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(i)->setItemName(objName);
 	}
-	return PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
+	return PyUnicode_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
 }
 
 PyObject *scribus_newtable(PyObject* /* self */, PyObject* args)
@@ -155,7 +156,7 @@
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(i)->setItemName(objName);
 	}
-	return PyString_FromString(table->itemName().toUtf8());
+	return PyUnicode_FromString(table->itemName().toUtf8());
 }
 
 PyObject *scribus_newline(PyObject* /* self */, PyObject* args)
@@ -215,7 +216,7 @@
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(i)->setItemName(objName);
 	}
-	return PyString_FromString(it->itemName().toUtf8());
+	return PyUnicode_FromString(it->itemName().toUtf8());
 }
 
 
@@ -292,7 +293,7 @@
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(ic)->setItemName(objName);
 	}
-	return PyString_FromString(it->itemName().toUtf8());
+	return PyUnicode_FromString(it->itemName().toUtf8());
 }
 
 
@@ -374,7 +375,7 @@
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(ic)->setItemName(objName);
 	}
-	return PyString_FromString(it->itemName().toUtf8());
+	return PyUnicode_FromString(it->itemName().toUtf8());
 }
 
 PyObject *scribus_bezierline(PyObject* /* self */, PyObject* args)
@@ -465,7 +466,7 @@
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(ic)->setItemName(objName);
 	}
-	return PyString_FromString(it->itemName().toUtf8());
+	return PyUnicode_FromString(it->itemName().toUtf8());
 }
 
 
@@ -506,7 +507,7 @@
 		if (!ItemExists(objName))
 			i->setItemName(objName);
 	}
-	return PyString_FromString(i->itemName().toUtf8());
+	return PyUnicode_FromString(i->itemName().toUtf8());
 }
 
 
@@ -605,13 +606,13 @@
 		int selectionStart = item->itemText.startOfSelection();
 		const ParagraphStyle& currentStyle = item->itemText.paragraphStyle(selectionStart);
 		if (currentStyle.hasParent())
-			return PyString_FromString(currentStyle.parentStyle()->name().toUtf8());
+			return PyUnicode_FromString(currentStyle.parentStyle()->name().toUtf8());
 	}
 	else
 	{
 		const ParagraphStyle& itemDefaultStyle = item->itemText.defaultStyle();
 		if (itemDefaultStyle.hasParent())
-			return PyString_FromString(itemDefaultStyle.parentStyle()->name().toUtf8());
+			return PyUnicode_FromString(itemDefaultStyle.parentStyle()->name().toUtf8());
 	}
 	Py_RETURN_NONE;
 };
@@ -798,7 +799,7 @@
 	styleList = PyList_New(0);
 	for (int i = 0; i < paragraphStyles.count(); ++i)
 	{
-		if (PyList_Append(styleList, PyString_FromString(paragraphStyles[i].name().toUtf8())))
+		if (PyList_Append(styleList, PyUnicode_FromString(paragraphStyles[i].name().toUtf8())))
 		{
 			// An exception will have already been set by PyList_Append apparently.
 			return nullptr;
@@ -817,7 +818,7 @@
 	charStyleList = PyList_New(0);
 	for (int i = 0; i < charStyles.count(); ++i)
 	{
-		if (PyList_Append(charStyleList, PyString_FromString(charStyles[i].name().toUtf8())))
+		if (PyList_Append(charStyleList, PyUnicode_FromString(charStyles[i].name().toUtf8())))
 		{
 			// An exception will have already been set by PyList_Append apparently.
 			return nullptr;
Index: scribus/plugins/scriptplugin/cmdpage.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdpage.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/cmdpage.cpp	(working copy)
@@ -18,7 +18,7 @@
 {
 	if (!checkHaveDocument())
 		return nullptr;
-	return PyInt_FromLong(static_cast<long>(ScCore->primaryMainWindow()->doc->currentPageNumber() + 1));
+	return PyLong_FromLong(static_cast<long>(ScCore->primaryMainWindow()->doc->currentPageNumber() + 1));
 }
 
 PyObject *scribus_redraw(PyObject* /* self */)
@@ -45,7 +45,7 @@
 		PyErr_SetString(PyExc_IndexError, QObject::tr("Page number out of range.","python error").toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyInt_FromLong(static_cast<long>(ScCore->primaryMainWindow()->doc->locationOfPage(e)));
+	return PyLong_FromLong(static_cast<long>(ScCore->primaryMainWindow()->doc->locationOfPage(e)));
 }
 
 PyObject *scribus_savepageeps(PyObject* /* self */, PyObject* args)
@@ -167,7 +167,7 @@
 {
 	if (!checkHaveDocument())
 		return nullptr;
-	return PyInt_FromLong(static_cast<long>(ScCore->primaryMainWindow()->doc->Pages->count()));
+	return PyLong_FromLong(static_cast<long>(ScCore->primaryMainWindow()->doc->Pages->count()));
 }
 
 PyObject *scribus_pagedimension(PyObject* /* self */)
Index: scribus/plugins/scriptplugin/cmdsetprop.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdsetprop.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/cmdsetprop.cpp	(working copy)
@@ -447,7 +447,7 @@
 		}
 		ObjectAttribute blank;
 		PyObject *val;
-		char* data;
+		const char* data;
 
 		val = PyDict_GetItemString(tmp, "Name");
 		if (!val) {
@@ -454,10 +454,10 @@
 			PyErr_SetString(PyExc_TypeError, "attribute does not have 'Name' key.");
 			return nullptr;
 		}
-		data = PyString_AsString(val);
+		data = PyUnicode_AsUTF8(val);
 		if (!data)
 			return nullptr;
-		blank.name = QString(data);
+		blank.name = QString::fromUtf8(data);
 
 		val = PyDict_GetItemString(tmp, "Type");
 		if (!val) {
@@ -464,10 +464,10 @@
 			PyErr_SetString(PyExc_TypeError, "attribute does not have 'Type' key.");
 			return nullptr;
 		}
-		data = PyString_AsString(val);
+		data = PyUnicode_AsUTF8(val);
 		if (!data)
 			return nullptr;
-		blank.type = QString(data);
+		blank.type = QString::fromUtf8(data);
 
 		val = PyDict_GetItemString(tmp, "Value");
 		if (!val) {
@@ -474,10 +474,10 @@
 			PyErr_SetString(PyExc_TypeError, "attribute does not have 'Value' key.");
 			return nullptr;
 		}
-		data = PyString_AsString(val);
+		data = PyUnicode_AsUTF8(val);
 		if (!data)
 			return nullptr;
-		blank.value = QString(data);
+		blank.value = QString::fromUtf8(data);
 
 		val = PyDict_GetItemString(tmp, "Parameter");
 		if (!val) {
@@ -484,10 +484,10 @@
 			PyErr_SetString(PyExc_TypeError, "attribute does not have 'Parameter' key.");
 			return nullptr;
 		}
-		data = PyString_AsString(val);
+		data = PyUnicode_AsUTF8(val);
 		if (!data)
 			return nullptr;
-		blank.parameter = QString(data);
+		blank.parameter = QString::fromUtf8(data);
 
 		val = PyDict_GetItemString(tmp, "Relationship");
 		if (!val) {
@@ -494,10 +494,10 @@
 			PyErr_SetString(PyExc_TypeError, "attribute does not have 'Relationship' key.");
 			return nullptr;
 		}
-		data = PyString_AsString(val);
+		data = PyUnicode_AsUTF8(val);
 		if (!data)
 			return nullptr;
-		blank.relationship = QString(data);
+		blank.relationship = QString::fromUtf8(data);
 
 		val = PyDict_GetItemString(tmp, "RelationshipTo");
 		if (!val) {
@@ -504,10 +504,10 @@
 			PyErr_SetString(PyExc_TypeError, "attribute does not have 'RelationshipTo' key.");
 			return nullptr;
 		}
-		data = PyString_AsString(val);
+		data = PyUnicode_AsUTF8(val);
 		if (!data)
 			return nullptr;
-		blank.relationshipto = QString(data);
+		blank.relationshipto = QString::fromUtf8(data);
 
 		val = PyDict_GetItemString(tmp, "AutoAddTo");
 		if (!val) {
@@ -514,10 +514,10 @@
 			PyErr_SetString(PyExc_TypeError, "attribute does not have 'AutoAddTo' key.");
 			return nullptr;
 		}
-		data = PyString_AsString(val);
+		data = PyUnicode_AsUTF8(val);
 		if (!data)
 			return nullptr;
-		blank.autoaddto = QString(data);
+		blank.autoaddto = QString::fromUtf8(data);
 
 		attributes.append(blank);
 	}
Index: scribus/plugins/scriptplugin/cmdstyle.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdstyle.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/cmdstyle.cpp	(working copy)
@@ -344,31 +344,31 @@
 
 		val = PyDict_GetItemString(line, "Color");
 		if (val)
-			sl.Color = PyString_AsString(val);
+			sl.Color = PyUnicode_asQString(val);
 		else 
 			sl.Color = currentDoc->itemToolPrefs().lineColor;
 
 		val = PyDict_GetItemString(line, "Dash");
 		if (val)
-			sl.Dash = PyInt_AsLong(val);
+			sl.Dash = PyLong_AsLong(val);
 		else 
 			sl.Dash = Qt::SolidLine;
 
 		val = PyDict_GetItemString(line, "LineEnd");
 		if (val)
-			sl.LineEnd = PyInt_AsLong(val);
+			sl.LineEnd = PyLong_AsLong(val);
 		else 
 			sl.LineEnd = Qt::FlatCap;
 
 		val = PyDict_GetItemString(line, "LineJoin");
 		if (val)
-			sl.LineJoin = PyInt_AsLong(val);
+			sl.LineJoin = PyLong_AsLong(val);
 		else 
 			sl.LineJoin = Qt::MiterJoin;
 
 		val = PyDict_GetItemString(line, "Shade");
 		if (val)
-			sl.Shade = PyInt_AsLong(val);
+			sl.Shade = PyLong_AsLong(val);
 		else 
 			sl.Shade = currentDoc->itemToolPrefs().lineColorShade;
 
@@ -380,7 +380,7 @@
 
 		val = PyDict_GetItemString(line, "Shortcut");
 		if (val)
-			ml.shortcut = PyString_AsString(val);
+			ml.shortcut = PyUnicode_asQString(val);
 		else 
 			ml.shortcut = "";
 
Index: scribus/plugins/scriptplugin/cmdtable.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdtable.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/cmdtable.cpp	(working copy)
@@ -28,7 +28,7 @@
 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get table row count of non-table item.","python error").toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyInt_FromLong(static_cast<long>(table->rows()));
+	return PyLong_FromLong(static_cast<long>(table->rows()));
 }
 
 PyObject *scribus_gettablecolumns(PyObject* /* self */, PyObject* args)
@@ -48,7 +48,7 @@
 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get table column count of non-table item.","python error").toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyInt_FromLong(static_cast<long>(table->columns()));
+	return PyLong_FromLong(static_cast<long>(table->columns()));
 }
 
 PyObject *scribus_inserttablerows(PyObject* /* self */, PyObject* args)
@@ -338,7 +338,7 @@
 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get table style on a non-table item.","python error").toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyString_FromString(table->styleName().toUtf8());
+	return PyUnicode_FromString(table->styleName().toUtf8());
 }
 
 PyObject *scribus_settablestyle(PyObject* /* self */, PyObject* args)
@@ -378,7 +378,7 @@
 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get table fill color on a non-table item.","python error").toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyString_FromString(table->fillColor().toUtf8());
+	return PyUnicode_FromString(table->fillColor().toUtf8());
 }
 
 PyObject *scribus_settablefillcolor(PyObject* /* self */, PyObject* args)
Index: scribus/plugins/scriptplugin/cmdtext.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdtext.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/cmdtext.cpp	(working copy)
@@ -92,10 +92,10 @@
 	{
 		for (int i = 0; i < item->itemText.length(); i++)
 			if (item->itemText.selected(i))
-				return PyString_FromString(item->itemText.charStyle(i).font().scName().toUtf8());
+				return PyUnicode_FromString(item->itemText.charStyle(i).font().scName().toUtf8());
 		return nullptr;
 	}
-	return PyString_FromString(item->currentCharStyle().font().scName().toUtf8());
+	return PyUnicode_FromString(item->currentCharStyle().font().scName().toUtf8());
 }
 
 PyObject *scribus_gettextcolor(PyObject* /* self */, PyObject* args)
@@ -118,11 +118,11 @@
 		for (int i = 0; i < item->itemText.length(); ++i)
 		{
 			if (item->itemText.selected(i))
-				return PyString_FromString(item->itemText.charStyle(i).fillColor().toUtf8());
+				return PyUnicode_FromString(item->itemText.charStyle(i).fillColor().toUtf8());
 		}
         return nullptr;
 	}
-    return PyString_FromString(item->currentCharStyle().fillColor().toUtf8());
+    return PyUnicode_FromString(item->currentCharStyle().fillColor().toUtf8());
 }
 
 PyObject *scribus_gettextshade(PyObject* /* self */, PyObject* args)
@@ -145,11 +145,11 @@
 		for (int i = 0; i < item->itemText.length(); ++i)
 		{
 			if (item->itemText.selected(i))
-				return PyInt_FromLong(item->itemText.charStyle(i).fillShade());
+				return PyLong_FromLong(item->itemText.charStyle(i).fillShade());
 		}
 		return nullptr;
 	}
-	return PyInt_FromLong(item->currentCharStyle().fillShade());
+	return PyLong_FromLong(item->currentCharStyle().fillShade());
 }
 
 PyObject *scribus_gettextsize(PyObject* /* self */, PyObject* args)
@@ -167,7 +167,7 @@
 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get text size of non-text frame.","python error").toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyInt_FromLong(static_cast<long>(item->itemText.length()));
+	return PyLong_FromLong(static_cast<long>(item->itemText.length()));
 }
 
 PyObject *scribus_gettextlines(PyObject* /* self */, PyObject* args)
@@ -185,7 +185,7 @@
 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get number of lines of non-text frame.","python error").toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyInt_FromLong(static_cast<long>(item->textLayout.lines()));
+	return PyLong_FromLong(static_cast<long>(item->textLayout.lines()));
 }
 
 PyObject *scribus_gettextverticalalignment(PyObject* /* self */, PyObject* args)
@@ -203,7 +203,7 @@
 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get vertical alignment of non-text frame.", "python error").toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyInt_FromLong(static_cast<long>(item->verticalAlignment()));
+	return PyLong_FromLong(static_cast<long>(item->verticalAlignment()));
 }
 
 PyObject *scribus_getcolumns(PyObject* /* self */, PyObject* args)
@@ -221,7 +221,7 @@
 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get column count of non-text frame.","python error").toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyInt_FromLong(static_cast<long>(item->m_columns));
+	return PyLong_FromLong(static_cast<long>(item->m_columns));
 }
 
 PyObject *scribus_getcolumngap(PyObject* /* self */, PyObject* args)
@@ -261,10 +261,10 @@
 	{
 		for (int i = 0; i < item->itemText.length(); i++)
 			if (item->itemText.selected(i))
-				return PyString_FromString(item->itemText.charStyle(i).fontFeatures().toUtf8());
+				return PyUnicode_FromString(item->itemText.charStyle(i).fontFeatures().toUtf8());
 		return nullptr;
 	}
-	return PyString_FromString(item->currentCharStyle().fontFeatures().toUtf8());
+	return PyUnicode_FromString(item->currentCharStyle().fontFeatures().toUtf8());
 }
 
 PyObject *scribus_getlinespace(PyObject* /* self */, PyObject* args)
@@ -335,7 +335,7 @@
 			text += item->itemText.text(i);
 		}
 	}
-	return PyString_FromString(text.toUtf8());
+	return PyUnicode_FromString(text.toUtf8());
 }
 
 PyObject *scribus_gettext(PyObject* /* self */, PyObject* args)
@@ -368,7 +368,7 @@
 			text += item->itemText.text(i);
 		}
 	} // for
-	return PyString_FromString(text.toUtf8());
+	return PyUnicode_FromString(text.toUtf8());
 }
 
 PyObject *scribus_setboxtext(PyObject* /* self */, PyObject* args)
@@ -1235,17 +1235,17 @@
 	}
 	// no overrun
 	if (nolinks)
-		return PyInt_FromLong(maxchars - firstFrame);
+		return PyLong_FromLong(maxchars - firstFrame);
 
 	if (maxchars > chars)
-		return PyInt_FromLong(0);
+		return PyLong_FromLong(0);
 	// number of overrunning letters
-	return PyInt_FromLong(static_cast<long>(chars - maxchars));
+	return PyLong_FromLong(static_cast<long>(chars - maxchars));
 	 */
 	// refresh overflow information
 	item->invalidateLayout();
 	item->layout();
-	return PyInt_FromLong(static_cast<long>(item->frameOverflows()));
+	return PyLong_FromLong(static_cast<long>(item->frameOverflows()));
 }
 
 /*
Index: scribus/plugins/scriptplugin/cmdutil.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdutil.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/cmdutil.cpp	(working copy)
@@ -241,3 +241,11 @@
 	return border;
 }
 
+QString PyUnicode_asQString(PyObject* arg)
+{
+	const char* utf8Str = PyUnicode_AsUTF8(arg);
+	if (!utf8Str)
+		return QString();
+	return QString::fromUtf8(utf8Str);
+}
+
Index: scribus/plugins/scriptplugin/cmdutil.h
===================================================================
--- scribus/plugins/scriptplugin/cmdutil.h	(revision 23269)
+++ scribus/plugins/scriptplugin/cmdutil.h	(working copy)
@@ -29,6 +29,7 @@
 
 PageItem *GetItem(const QString& Name);
 void ReplaceColor(const QString& col, const QString& rep);
+
 /*!
  * @brief Returns named PageItem, or selection if name '', or exception and NULL if no item.
  *
@@ -60,6 +61,7 @@
  * @brief Returns a list of the names of all selected PageItems
  */
 QStringList getSelectedItemsByName();
+
 /*!
  * @brief Replaces the current selection by selecting all the items named in the passed QStringList
  *
@@ -68,8 +70,14 @@
  */
 bool setSelectedItemsByName(QStringList& itemNames);
 
-/// Helper method to parse a border from a list of tuples.
+/*!
+ * @brief Helper method to parse a border from a list of tuples.
+ */
 TableBorder parseBorder(PyObject* borderLines, bool* ok);
 
+/*!
+ * @brief Helper method to convert a PyUnicode object to a QString
+ */
+QString PyUnicode_asQString(PyObject* arg);
 
 #endif
Index: scribus/plugins/scriptplugin/cmdvar.h
===================================================================
--- scribus/plugins/scriptplugin/cmdvar.h	(revision 23269)
+++ scribus/plugins/scriptplugin/cmdvar.h	(working copy)
@@ -18,6 +18,11 @@
 	#undef _POSIX_C_SOURCE
 #endif
 
+#if defined(_MSC_VER)
+#pragma push_macro("slots")
+#undef slots
+#endif
+
 #if defined(HAVE_BOOST_PYTHON)
 #include <boost/python.hpp>
 #else
@@ -24,6 +29,10 @@
 #include <Python.h>
 #endif
 
+#if defined(_MSC_VER)
+#pragma pop_macro("slots")
+#endif
+
 #ifndef Py_RETURN_NONE
 	#define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
 #endif
@@ -52,6 +61,8 @@
 /** @brief Initialize the 'scribus' Python module in the currently active interpreter */
 extern "C" void initscribus(ScribusMainWindow *pl);
 
+extern "C" PyObject* PyInit_scribus(void);
+
 /* Exceptions */
 /*! Common scribus Exception */
 extern PyObject* ScribusException;
Index: scribus/plugins/scriptplugin/objimageexport.cpp
===================================================================
--- scribus/plugins/scriptplugin/objimageexport.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/objimageexport.cpp	(working copy)
@@ -34,7 +34,7 @@
 	Py_XDECREF(self->name);
 	Py_XDECREF(self->type);
 	Py_XDECREF(self->allTypes);
-	self->ob_type->tp_free((PyObject *)self);
+	Py_TYPE(self)->tp_free((PyObject *)self);
 }
 
 static PyObject * ImageExport_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
@@ -45,8 +45,8 @@
 	ImageExport *self;
 	self = (ImageExport *)type->tp_alloc(type, 0);
 	if (self != nullptr) {
-		self->name = PyString_FromString("ImageExport.png");
-		self->type = PyString_FromString("PNG");
+		self->name = PyUnicode_FromString("ImageExport.png");
+		self->type = PyUnicode_FromString("PNG");
 		self->allTypes = PyList_New(0);
 		self->dpi = 72;
 		self->scale = 100;
@@ -77,11 +77,11 @@
 
 static int ImageExport_setName(ImageExport *self, PyObject *value, void * /*closure*/)
 {
-	if (!PyString_Check(value)) {
+	if (!PyUnicode_Check(value)) {
 		PyErr_SetString(PyExc_TypeError, QObject::tr("The filename must be a string.", "python error").toLocal8Bit().constData());
 		return -1;
 	}
-	if (PyString_Size(value) < 1)
+	if (PyUnicode_GET_LENGTH(value) < 1)
 	{
 		PyErr_SetString(PyExc_TypeError, QObject::tr("The filename should not be empty string.", "python error").toLocal8Bit().constData());
 		return -1;
@@ -104,7 +104,7 @@
 		PyErr_SetString(PyExc_TypeError, QObject::tr("Cannot delete image type settings.", "python error").toLocal8Bit().constData());
 		return -1;
 	}
-	if (!PyString_Check(value)) {
+	if (!PyUnicode_Check(value)) {
 		PyErr_SetString(PyExc_TypeError, QObject::tr("The image type must be a string.", "python error").toLocal8Bit().constData());
 		return -1;
 	}
@@ -122,7 +122,7 @@
 	l = PyList_New(list.count());
 	for (QList<QByteArray>::Iterator it = list.begin(); it != list.end(); ++it)
 	{
-		PyList_SetItem(l, pos, PyString_FromString(QString((*it)).toLatin1().constData()));
+		PyList_SetItem(l, pos, PyUnicode_FromString(QString((*it)).toLatin1().constData()));
 		++pos;
 	}
 	return l;
@@ -160,7 +160,9 @@
 	int dpi = qRound(100.0 / 2.54 * self->dpi);
 	im.setDotsPerMeterY(dpi);
 	im.setDotsPerMeterX(dpi);
-	if (!im.save(PyString_AsString(self->name), PyString_AsString(self->type)))
+
+	QString imgFileName = PyUnicode_asQString(self->name);
+	if (!im.save(imgFileName, PyUnicode_AsUTF8(self->type)))
 	{
 		PyErr_SetString(ScribusException, QObject::tr("Failed to export image", "python error").toLocal8Bit().constData());
 		return nullptr;
@@ -194,7 +196,9 @@
 	int dpi = qRound(100.0 / 2.54 * self->dpi);
 	im.setDotsPerMeterY(dpi);
 	im.setDotsPerMeterX(dpi);
-	if (!im.save(value, PyString_AsString(self->type)))
+
+	QString outputFileName = QString::fromUtf8(value);
+	if (!im.save(outputFileName, PyUnicode_AsUTF8(self->type)))
 	{
 		PyErr_SetString(ScribusException, QObject::tr("Failed to export image", "python error").toLocal8Bit().constData());
 		return nullptr;
@@ -212,8 +216,7 @@
 };
 
 PyTypeObject ImageExport_Type = {
-	PyObject_HEAD_INIT(nullptr)   // PyObject_VAR_HEAD
-	0,
+	PyVarObject_HEAD_INIT(nullptr, 0)   // PyObject_VAR_HEAD
 	const_cast<char*>("scribus.ImageExport"), // char *tp_name; /* For printing, in format "<module>.<name>" */
 	sizeof(ImageExport),   // int tp_basicsize, /* For allocation */
 	0,  // int tp_itemsize; /* For allocation */
@@ -259,6 +262,8 @@
 	nullptr, //	 PyObject *tp_subclasses;
 	nullptr, //	 PyObject *tp_weaklist;
 	nullptr, //	 destructor tp_del;
+	0, //	 unsigned int tp_version_tag;
+	0, //	 destructor tp_finalize;
 
 #ifdef COUNT_ALLOCS
 	/* these must be last and never explicitly initialized */
Index: scribus/plugins/scriptplugin/objpdffile.cpp
===================================================================
--- scribus/plugins/scriptplugin/objpdffile.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/objpdffile.cpp	(working copy)
@@ -135,7 +135,7 @@
 	Py_XDECREF(self->info);
 	Py_XDECREF(self->rotateDeg);
 	Py_XDECREF(self->openAction);
-	self->ob_type->tp_free((PyObject *)self);
+	Py_TYPE(self)->tp_free((PyObject *)self);
 }
 
 static PyObject * PDFfile_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
@@ -150,13 +150,13 @@
 	self = (PDFfile *)type->tp_alloc(type, 0);
 	if (self) {
 // set file attribute
-		self->file = PyString_FromString("");
+		self->file = PyUnicode_FromString("");
 		if (!self->file) {
 			Py_DECREF(self);
 			return nullptr;
 		}
 // set font embedding mode attribute
-		self->fontEmbedding = PyInt_FromLong(0);
+		self->fontEmbedding = PyLong_FromLong(0);
 		if (!self->fontEmbedding) {
 			Py_DECREF(self);
 			return nullptr;
@@ -201,13 +201,13 @@
 // set quality attribute
 		self->quality = 0;
 // set resolution attribute
-		self->resolution = PyInt_FromLong(300);
+		self->resolution = PyLong_FromLong(300);
 		if (!self->resolution){
 			Py_DECREF(self);
 			return nullptr;
 		}
 // set downsample attribute
-		self->downsample = PyInt_FromLong(0);
+		self->downsample = PyLong_FromLong(0);
 		if (!self->downsample){
 			Py_DECREF(self);
 			return nullptr;
@@ -239,13 +239,13 @@
 			return nullptr;
 		}
 // set owner attribute
-		self->owner = PyString_FromString("");
+		self->owner = PyUnicode_FromString("");
 		if (!self->owner){
 			Py_DECREF(self);
 			return nullptr;
 		}
 // set user attribute
-		self->user = PyString_FromString("");
+		self->user = PyUnicode_FromString("");
 		if (!self->user){
 			Py_DECREF(self);
 			return nullptr;
@@ -269,22 +269,22 @@
 		self->intents = 0; // int - 0 - ?
 		self->intenti = 0; // int - 0 - ?
 		self->noembicc = 0; // bool
-		self->solidpr = PyString_FromString("");
+		self->solidpr = PyUnicode_FromString("");
 		if (!self->solidpr){
 			Py_DECREF(self);
 			return nullptr;
 		}
-		self->imagepr = PyString_FromString("");
+		self->imagepr = PyUnicode_FromString("");
 		if (!self->imagepr){
 			Py_DECREF(self);
 			return nullptr;
 		}
-		self->printprofc = PyString_FromString("");
+		self->printprofc = PyUnicode_FromString("");
 		if (!self->printprofc){
 			Py_DECREF(self);
 			return nullptr;
 		}
-		self->info = PyString_FromString("");
+		self->info = PyUnicode_FromString("");
 		if (!self->info){
 			Py_DECREF(self);
 			return nullptr;
@@ -299,7 +299,7 @@
 		self->mirrorH = 0;
 		self->mirrorV = 0;
 		self->doClip = 0;
-		self->rotateDeg = PyInt_FromLong(0);
+		self->rotateDeg = PyLong_FromLong(0);
 		if (!self->rotateDeg){
 			Py_DECREF(self);
 			return nullptr;
@@ -313,7 +313,7 @@
 		self->hideToolBar = 0;
 		self->hideMenuBar = 0;
 		self->fitWindow = 0;
-		self->openAction = PyString_FromString("");
+		self->openAction = PyUnicode_FromString("");
 		if (!self->openAction){
 			Py_DECREF(self);
 			return nullptr;
@@ -336,10 +336,10 @@
 	QString tf = pdfOptions.fileName;
 	if (tf.isEmpty()) {
 		QFileInfo fi = QFileInfo(currentDoc->documentFileName());
-		tf = fi.path()+"/"+fi.baseName()+".pdf";
+		tf = fi.path() + "/" + fi.baseName() + ".pdf";
 	}
 	PyObject *file = nullptr;
-	file = PyString_FromString(tf.toLatin1());
+	file = PyUnicode_FromString(tf.toUtf8());
 	if (file){
 		Py_DECREF(self->file);
 		self->file = file;
@@ -349,7 +349,7 @@
 	}
 // font embedding mode
 	PyObject *embeddingMode = nullptr;
-	embeddingMode = PyInt_FromLong(pdfOptions.FontEmbedding);
+	embeddingMode = PyLong_FromLong(pdfOptions.FontEmbedding);
 	if (embeddingMode){
 		Py_DECREF(self->fontEmbedding);
 		self->fontEmbedding = embeddingMode;
@@ -375,7 +375,7 @@
 	{
 		const QString& fontName = tmpEm.at(i);
 		PyObject *tmp= nullptr;
-		tmp = PyString_FromString(fontName.toLatin1());
+		tmp = PyUnicode_FromString(fontName.toUtf8());
 		if (tmp) {
 			PyList_Append(self->fonts, tmp);
 // do i need Py_DECREF(tmp) here?
@@ -401,7 +401,7 @@
 	for (int fe = 0; fe < pdfOptions.SubsetList.count(); ++fe)
 	{
 		PyObject *tmp= nullptr;
-		tmp = PyString_FromString(pdfOptions.SubsetList[fe].toLatin1().data());
+		tmp = PyUnicode_FromString(pdfOptions.SubsetList[fe].toUtf8().data());
 		if (tmp) {
 			PyList_Append(self->subsetList, tmp);
 			Py_DECREF(tmp);
@@ -425,7 +425,7 @@
 	}
 	for (i = 0; i<num; ++i) {
 		PyObject *tmp;
-		tmp = PyInt_FromLong((long)i+1L);
+		tmp = PyLong_FromLong((long)i+1L);
 		if (tmp)
 			PyList_SetItem(pages, i, tmp);
 		else {
@@ -458,7 +458,7 @@
 	self->quality = pdfOptions.Quality;
 // default resolution
 	PyObject *resolution = nullptr;
-	resolution = PyInt_FromLong(300);
+	resolution = PyLong_FromLong(300);
 	if (resolution){
 		Py_DECREF(self->resolution);
 		self->resolution = resolution;
@@ -469,7 +469,7 @@
 // do not downsample images
 	int down = pdfOptions.RecalcPic ? pdfOptions.PicRes : 0;
 	PyObject *downsample = nullptr;
-	downsample = PyInt_FromLong(down);
+	downsample = PyLong_FromLong(down);
 	if (downsample){
 		Py_DECREF(self->downsample);
 		self->downsample = downsample;
@@ -549,7 +549,7 @@
 	self->lpival = lpival;
 // set owner's password
 	PyObject *owner = nullptr;
-	owner = PyString_FromString(pdfOptions.PassOwner.toLatin1());
+	owner = PyUnicode_FromString(pdfOptions.PassOwner.toUtf8());
 	if (owner){
 		Py_DECREF(self->owner);
 		self->owner = owner;
@@ -559,7 +559,7 @@
 	}
 // set user'a password
 	PyObject *user = nullptr;
-	user = PyString_FromString(pdfOptions.PassUser.toLatin1());
+	user = PyUnicode_FromString(pdfOptions.PassUser.toUtf8());
 	if (user){
 		Py_DECREF(self->user);
 		self->user = user;
@@ -589,7 +589,7 @@
 	if (!ScCore->InputProfiles.contains(tp))
 		tp = currentDoc->cmsSettings().DefaultSolidColorRGBProfile;
 	PyObject *solidpr = nullptr;
-	solidpr = PyString_FromString(tp.toLatin1());
+	solidpr = PyUnicode_FromString(tp.toUtf8());
 	if (solidpr){
 		Py_DECREF(self->solidpr);
 		self->solidpr = solidpr;
@@ -601,7 +601,7 @@
 	if (!ScCore->InputProfiles.contains(tp2))
 		tp2 = currentDoc->cmsSettings().DefaultSolidColorRGBProfile;
 	PyObject *imagepr = nullptr;
-	imagepr = PyString_FromString(tp2.toLatin1());
+	imagepr = PyUnicode_FromString(tp2.toUtf8());
 	if (imagepr){
 		Py_DECREF(self->imagepr);
 		self->imagepr = imagepr;
@@ -613,7 +613,7 @@
 	if (!ScCore->PDFXProfiles.contains(tp3))
 		tp3 = currentDoc->cmsSettings().DefaultPrinterProfile;
 	PyObject *printprofc = nullptr;
-	printprofc = PyString_FromString(tp3.toLatin1());
+	printprofc = PyUnicode_FromString(tp3.toUtf8());
 	if (printprofc){
 		Py_DECREF(self->printprofc);
 		self->printprofc = printprofc;
@@ -623,7 +623,7 @@
 	}
 	QString tinfo = pdfOptions.Info;
 	PyObject *info = nullptr;
-	info = PyString_FromString(tinfo.toLatin1());
+	info = PyUnicode_FromString(tinfo.toUtf8());
 	if (info){
 		Py_DECREF(self->info);
 		self->info = info;
@@ -642,7 +642,7 @@
 	self->mirrorV = pdfOptions.MirrorV; // bool
 	self->doClip = pdfOptions.doClip; // bool
 	PyObject *rotateDeg = nullptr;
-	rotateDeg = PyInt_FromLong(0);
+	rotateDeg = PyLong_FromLong(0);
 	if (rotateDeg){
 		Py_DECREF(self->rotateDeg);
 		self->rotateDeg = rotateDeg;
@@ -661,7 +661,7 @@
 	self->fitWindow = pdfOptions.fitWindow; // bool
 
 	PyObject *openAction = nullptr;
-	openAction = PyString_FromString(pdfOptions.openAction.toLatin1().data());
+	openAction = PyUnicode_FromString(pdfOptions.openAction.toUtf8().data());
 	if (openAction){
 		Py_DECREF(self->openAction);
 		self->openAction = openAction;
@@ -751,7 +751,7 @@
 		PyErr_SetString(PyExc_TypeError, "Cannot delete 'file' attribute.");
 		return -1;
 	}
-	if (!PyString_Check(value)) {
+	if (!PyUnicode_Check(value)) {
 		PyErr_SetString(PyExc_TypeError, "The 'file' attribute value must be string.");
 		return -1;
 	}
@@ -773,11 +773,11 @@
 		PyErr_SetString(PyExc_TypeError, "Cannot delete 'fontEmbedding' attribute.");
 		return -1;
 	}
-	if (!PyInt_Check(value)) {
+	if (!PyLong_Check(value)) {
 		PyErr_SetString(PyExc_TypeError, "'fontEmbedding' attribute value must be integer.");
 		return -1;
 	}
-	int n = PyInt_AsLong(value);
+	int n = PyLong_AsLong(value);
 	if (n < 0 || n > 2) {
 		PyErr_SetString(PyExc_ValueError, "'fontEmbedding' value must be an integer between 0 and 2");
 		return -1;
@@ -807,7 +807,7 @@
 	int n;
 	n = PyList_Size(value);
 	for (int i=0; i<n; ++i)
-		if (!PyString_Check(PyList_GetItem(value, i))) {
+		if (!PyUnicode_Check(PyList_GetItem(value, i))) {
 			PyErr_SetString(PyExc_TypeError, "The 'fonts' list must contain only strings.");
 			return -1;
 		}
@@ -840,7 +840,7 @@
 	int n;
 	n = PyList_Size(value);
 	for (int i=0; i<n; ++i)
-		if (!PyString_Check(PyList_GetItem(value, i))) {
+		if (!PyUnicode_Check(PyList_GetItem(value, i))) {
 			PyErr_SetString(PyExc_TypeError, "The 'subsetList' list must contain only strings.");
 			return -1;
 		}
@@ -873,11 +873,11 @@
 		// I did not check if tmp is nullptr
 		// how can PyList_GetItem fail in this case (my guess: short of available memory?)
 		// Also do I need Py_INCREF or Py_DECREF here?
-		if (!PyInt_Check(tmp)){
+		if (!PyLong_Check(tmp)){
 			PyErr_SetString(PyExc_TypeError, "'pages' list must contain only integers.");
 			return -1;
 		}
-		if (PyInt_AsLong(tmp) > static_cast<int>(ScCore->primaryMainWindow()->doc->Pages->count()) || PyInt_AsLong(tmp) < 1) {
+		if (PyLong_AsLong(tmp) > static_cast<int>(ScCore->primaryMainWindow()->doc->Pages->count()) || PyLong_AsLong(tmp) < 1) {
 			PyErr_SetString(PyExc_ValueError, "'pages' value out of range.");
 			return -1;
 		}
@@ -901,11 +901,11 @@
 		PyErr_SetString(PyExc_TypeError, "Cannot delete 'resolution' attribute.");
 		return -1;
 	}
-	if (!PyInt_Check(value)) {
+	if (!PyLong_Check(value)) {
 		PyErr_SetString(PyExc_TypeError, "'resolution' attribute value must be integer.");
 		return -1;
 	}
-	int n = PyInt_AsLong(value);
+	int n = PyLong_AsLong(value);
 	if (n<35 || n>4000) {
 		PyErr_SetString(PyExc_ValueError, "'resolution' value must be in interval from 35 to 4000");
 		return -1;
@@ -928,12 +928,12 @@
 		PyErr_SetString(PyExc_TypeError, "Cannot delete 'downsample' attribute.");
 		return -1;
 	}
-	if (!PyInt_Check(value)) {
+	if (!PyLong_Check(value)) {
 		PyErr_SetString(PyExc_TypeError, "'downsample' attribute value must be integer.");
 		return -1;
 	}
-	int n = PyInt_AsLong(value);
-	if (n!=0 && (n<35 || n>PyInt_AsLong(self->resolution))) {
+	int n = PyLong_AsLong(value);
+	if (n!=0 && (n < 35 || n > PyLong_AsLong(self->resolution))) {
 		PyErr_SetString(PyExc_TypeError, "'downsample' value must be 0 or in interval from 35 to value of 'resolution'");
 		return -1;
 	}
@@ -972,7 +972,7 @@
 			return -1;
 		}
 		for ( --j; j > -1; --j) {
-			if (!PyInt_Check(PyList_GetItem(tmp, j))) {
+			if (!PyLong_Check(PyList_GetItem(tmp, j))) {
 				PyErr_SetString(PyExc_TypeError, "innermost element of 'effval' must be integers.");
 				return -1;
 			}
@@ -1005,21 +1005,21 @@
 	for (int i=0; i<n; ++i) {
 		PyObject *tmp = PyList_GetItem(value, i);
 		if (!PyList_Check(tmp)) {
-			PyErr_SetString(PyExc_TypeError, "elemets of 'lpival' must be list of five integers.");
+			PyErr_SetString(PyExc_TypeError, "elements of 'lpival' must be list of five integers.");
 			return -1;
 		}
 		int j = PyList_Size(tmp);
 		if (j != 4) {
-			PyErr_SetString(PyExc_TypeError, "elemets of 'lpival' must have exactly four members.");
+			PyErr_SetString(PyExc_TypeError, "elements of 'lpival' must have exactly four members.");
 			return -1;
 		}
 		for ( --j; j > 0; --j) {
-			if (!PyInt_Check(PyList_GetItem(tmp, j))) {
+			if (!PyLong_Check(PyList_GetItem(tmp, j))) {
 				PyErr_SetString(PyExc_TypeError, "'lpival'elements must have structure [siii]");
 				return -1;
 			}
 		}
-		if (!PyString_Check(PyList_GetItem(tmp, 0))) {
+		if (!PyUnicode_Check(PyList_GetItem(tmp, 0))) {
 			PyErr_SetString(PyExc_TypeError, "'lpival'elements must have structure [siii]");
 			return -1;
 		}
@@ -1042,7 +1042,7 @@
 		PyErr_SetString(PyExc_TypeError, "Cannot delete 'owner' attribute.");
 		return -1;
 	}
-	if (!PyString_Check(value)) {
+	if (!PyUnicode_Check(value)) {
 		PyErr_SetString(PyExc_TypeError, "'owner' attribute value must be string.");
 		return -1;
 	}
@@ -1064,7 +1064,7 @@
 		PyErr_SetString(PyExc_TypeError, "Cannot delete 'user' attribute.");
 		return -1;
 	}
-	if (!PyString_Check(value)) {
+	if (!PyUnicode_Check(value)) {
 		PyErr_SetString(PyExc_TypeError, "'user' attribute value must be string.");
 		return -1;
 	}
@@ -1086,7 +1086,7 @@
 		PyErr_SetString(PyExc_TypeError, "Cannot delete 'solidpr' attribute.");
 		return -1;
 	}
-	if (!PyString_Check(value)) {
+	if (!PyUnicode_Check(value)) {
 		PyErr_SetString(PyExc_TypeError, "The 'solidpr' attribute value must be string.");
 		return -1;
 	}
@@ -1108,7 +1108,7 @@
 		PyErr_SetString(PyExc_TypeError, "Cannot delete 'imagepr' attribute.");
 		return -1;
 	}
-	if (!PyString_Check(value)) {
+	if (!PyUnicode_Check(value)) {
 		PyErr_SetString(PyExc_TypeError, "The 'imagepr' attribute value must be string.");
 		return -1;
 	}
@@ -1130,7 +1130,7 @@
 		PyErr_SetString(PyExc_TypeError, "Cannot delete 'printprofc' attribute.");
 		return -1;
 	}
-	if (!PyString_Check(value)) {
+	if (!PyUnicode_Check(value)) {
 		PyErr_SetString(PyExc_TypeError, "The 'printprofc' attribute value must be string.");
 		return -1;
 	}
@@ -1152,7 +1152,7 @@
 		PyErr_SetString(PyExc_TypeError, "Cannot delete 'info' attribute.");
 		return -1;
 	}
-	if (!PyString_Check(value)) {
+	if (!PyUnicode_Check(value)) {
 		PyErr_SetString(PyExc_TypeError, "The 'info' attribute value must be string.");
 		return -1;
 	}
@@ -1174,11 +1174,11 @@
 		PyErr_SetString(PyExc_TypeError, "Cannot delete 'rotateDeg' attribute.");
 		return -1;
 	}
-	if (!PyInt_Check(value)) {
+	if (!PyLong_Check(value)) {
 		PyErr_SetString(PyExc_TypeError, "'rotateDeg' attribute value must be integer.");
 		return -1;
 	}
-	int n = PyInt_AsLong(value);
+	int n = PyLong_AsLong(value);
 	if (n!=0 && n!=90 && n!=180 && n!=270) {
 		PyErr_SetString(PyExc_TypeError, "'rotateDeg' value must be 0 or 90 or 180 or 270");
 		return -1;
@@ -1201,7 +1201,7 @@
 		PyErr_SetString(PyExc_TypeError, "Cannot delete 'openAction' attribute.");
 		return -1;
 	}
-	if (!PyString_Check(value)) {
+	if (!PyUnicode_Check(value)) {
 		PyErr_SetString(PyExc_TypeError, "'openAction' attribute value must be string.");
 		return -1;
 	}
@@ -1275,10 +1275,10 @@
 // apply fonts attribute
 	pdfOptions.EmbedList.clear();
 	int n = PyList_Size(self->fonts);
-	for ( int i=0; i<n; ++i)
+	for (int i = 0; i < n; ++i)
 	{
 		QString tmpFon;
-		tmpFon = QString(PyString_AsString(PyList_GetItem(self->fonts, i)));
+		tmpFon = PyUnicode_asQString(PyList_GetItem(self->fonts, i));
 		pdfOptions.EmbedList.append(tmpFon);
 	}
 // apply SubsetList attribute
@@ -1287,11 +1287,11 @@
 	for (int i = 0; i < n; ++i)
 	{
 		QString tmpFon;
-		tmpFon = QString(PyString_AsString(PyList_GetItem(self->subsetList, i)));
+		tmpFon = PyUnicode_asQString(PyList_GetItem(self->subsetList, i));
 		pdfOptions.SubsetList.append(tmpFon);
 	}
 // apply font embedding mode
-	pdfOptions.FontEmbedding = (PDFOptions::PDFFontEmbedding) PyInt_AsLong(self->fontEmbedding);
+	pdfOptions.FontEmbedding = (PDFOptions::PDFFontEmbedding) PyLong_AsLong(self->fontEmbedding);
 	if (pdfOptions.Version == PDFOptions::PDFVersion_X1a ||
 	    pdfOptions.Version == PDFOptions::PDFVersion_X3 ||
 	    pdfOptions.Version == PDFOptions::PDFVersion_X4)
@@ -1326,13 +1326,13 @@
 	}
 // apply file attribute
 	QString fn;
-	fn = QString(PyString_AsString(self->file));
+	fn = PyUnicode_asQString(self->file);
 	pdfOptions.fileName = fn;
 // apply pages attribute
 	std::vector<int> pageNs;
-	int nn=PyList_Size(self->pages);
+	int nn = PyList_Size(self->pages);
 	for (int i = 0; i < nn; ++i) {
-		pageNs.push_back((int)PyInt_AsLong(PyList_GetItem(self->pages, i)));
+		pageNs.push_back((int) PyLong_AsLong(PyList_GetItem(self->pages, i)));
 	}
 // apply thumbnails attribute
 	pdfOptions.Thumbnails = self->thumbnails;
@@ -1358,11 +1358,11 @@
 	self->quality = minmaxi(self->quality, 0, 4);
 	pdfOptions.Quality = self->quality;
 // apply resolusion attribute
-	pdfOptions.Resolution = PyInt_AsLong(self->resolution);
+	pdfOptions.Resolution = PyLong_AsLong(self->resolution);
 // apply downsample attribute
-	pdfOptions.RecalcPic = PyInt_AsLong(self->downsample);
+	pdfOptions.RecalcPic = PyLong_AsLong(self->downsample);
 	if (pdfOptions.RecalcPic)
-		pdfOptions.PicRes = PyInt_AsLong(self->downsample);
+		pdfOptions.PicRes = PyLong_AsLong(self->downsample);
 	else
 		pdfOptions.PicRes = pdfOptions.Resolution;
 // apply bookmarks attribute
@@ -1379,13 +1379,13 @@
 		PyObject *ti = PyList_GetItem(self->effval, i);
 		if (!ti)
 			continue;
-		// Do I Need to check if every PyInt_AsLong and PyList_GetItem funtion succeed???
-		t.pageEffectDuration = PyInt_AsLong(PyList_GetItem(ti, 0));
-		t.pageViewDuration = PyInt_AsLong(PyList_GetItem(ti, 1));
-		t.effectType = PyInt_AsLong(PyList_GetItem(ti, 2));
-		t.Dm = PyInt_AsLong(PyList_GetItem(ti, 3));
-		t.M = PyInt_AsLong(PyList_GetItem(ti, 4));
-		t.Di = PyInt_AsLong(PyList_GetItem(ti, 5));
+		// Do I Need to check if every PyLong_AsLong and PyList_GetItem funtion succeed???
+		t.pageEffectDuration = PyLong_AsLong(PyList_GetItem(ti, 0));
+		t.pageViewDuration = PyLong_AsLong(PyList_GetItem(ti, 1));
+		t.effectType = PyLong_AsLong(PyList_GetItem(ti, 2));
+		t.Dm = PyLong_AsLong(PyList_GetItem(ti, 3));
+		t.M = PyLong_AsLong(PyList_GetItem(ti, 4));
+		t.Di = PyLong_AsLong(PyList_GetItem(ti, 5));
 		//	PresentVals.append(t);
 	}
 
@@ -1404,11 +1404,10 @@
 //			return nullptr;
 //		}
 //		pdfOptions.LPISettings[QString(s)]=lpi;
-		QString st;
-		st = QString(PyString_AsString(PyList_GetItem(t,0)));
-		lpi.Frequency = PyInt_AsLong(PyList_GetItem(t, 1));
-		lpi.Angle = PyInt_AsLong(PyList_GetItem(t, 2));
-		lpi.SpotFunc = PyInt_AsLong(PyList_GetItem(t, 3));
+		QString st = PyUnicode_asQString(PyList_GetItem(t, 0));
+		lpi.Frequency = PyLong_AsLong(PyList_GetItem(t, 1));
+		lpi.Angle = PyLong_AsLong(PyList_GetItem(t, 2));
+		lpi.SpotFunc = PyLong_AsLong(PyList_GetItem(t, 3));
 		pdfOptions.LPISettings[st] = lpi;
 	}
 
@@ -1432,8 +1431,8 @@
 		if (self->allowAnnots)
 			Perm += 32;
 		pdfOptions.Permissions = Perm;
-		pdfOptions.PassOwner = QString(PyString_AsString(self->owner));
-		pdfOptions.PassUser = QString(PyString_AsString(self->user));
+		pdfOptions.PassOwner = PyUnicode_asQString(self->owner);
+		pdfOptions.PassUser = PyUnicode_asQString(self->user);
 	}
 	if (self->outdst == 0)
 	{
@@ -1453,9 +1452,9 @@
 			self->intenti = minmaxi(self->intenti, 0, 3);
 			pdfOptions.Intent2 = self->intenti;
 			pdfOptions.EmbeddedI = self->noembicc;
-			pdfOptions.SolidProf = PyString_AsString(self->solidpr);
-			pdfOptions.ImageProf = PyString_AsString(self->imagepr);
-			pdfOptions.PrintProf = PyString_AsString(self->printprofc);
+			pdfOptions.SolidProf = PyUnicode_asQString(self->solidpr);
+			pdfOptions.ImageProf = PyUnicode_asQString(self->imagepr);
+			pdfOptions.PrintProf = PyUnicode_asQString(self->printprofc);
 			if (pdfOptions.Version == PDFOptions::PDFVersion_X1a ||
 				pdfOptions.Version == PDFOptions::PDFVersion_X3 ||
 				pdfOptions.Version == PDFOptions::PDFVersion_X4)
@@ -1469,7 +1468,7 @@
 					Components = 4;
 				if (profile.colorSpace() == ColorSpace_Cmy)
 					Components = 3;
-				pdfOptions.Info = PyString_AsString(self->info);
+				pdfOptions.Info = PyUnicode_asQString(self->info);
 				pdfOptions.Encrypt = false;
 				pdfOptions.PresentMode = false;
 			}
@@ -1512,7 +1511,7 @@
 	pdfOptions.MirrorH = self->mirrorH;
 	pdfOptions.MirrorV = self->mirrorV;
 	pdfOptions.doClip = self->doClip;
-	pdfOptions.RotateDeg = PyInt_AsLong(self->rotateDeg);
+	pdfOptions.RotateDeg = PyLong_AsLong(self->rotateDeg);
 	pdfOptions.isGrayscale = self->isGrayscale;
 	pdfOptions.PageLayout = minmaxi(self->pageLayout, 0, 3);
 	pdfOptions.displayBookmarks = self->displayBookmarks;
@@ -1522,7 +1521,7 @@
 	pdfOptions.hideToolBar = self->hideToolBar;
 	pdfOptions.hideMenuBar = self->hideMenuBar;
 	pdfOptions.fitWindow = self->fitWindow;
-	pdfOptions.openAction = QString(PyString_AsString(self->openAction));
+	pdfOptions.openAction = PyUnicode_asQString(self->openAction);
 	pdfOptions.firstUse = false;
 
 	QString errorMessage;
@@ -1548,8 +1547,7 @@
 };
 
 PyTypeObject PDFfile_Type = {
-	PyObject_HEAD_INIT(nullptr) // PyObject_VAR_HEAD
-	0,		      //
+	PyVarObject_HEAD_INIT(nullptr, 0) // PyObject_VAR_HEAD	      //
 	const_cast<char*>("scribus.PDFfile"), // char *tp_name; /* For printing, in format "<module>.<name>" */
 	sizeof(PDFfile),     // int tp_basicsize, /* For allocation */
 	0,		    // int tp_itemsize; /* For allocation */
@@ -1624,6 +1622,8 @@
 	nullptr, //     PyObject *tp_subclasses;
 	nullptr, //     PyObject *tp_weaklist;
 	nullptr, //     destructor tp_del;
+	0, //	 unsigned int tp_version_tag;
+	0, //	 destructor tp_finalize;
 
 #ifdef COUNT_ALLOCS
 	/* these must be last and never explicitly initialized */
Index: scribus/plugins/scriptplugin/objprinter.cpp
===================================================================
--- scribus/plugins/scriptplugin/objprinter.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/objprinter.cpp	(working copy)
@@ -59,7 +59,7 @@
 	Py_XDECREF(self->cmd);
 	Py_XDECREF(self->pages);
 	Py_XDECREF(self->separation);
-	self->ob_type->tp_free((PyObject *)self);
+	Py_TYPE(self)->tp_free((PyObject *)self);
 }
 
 static PyObject * Printer_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
@@ -78,19 +78,19 @@
 			return nullptr;
 		}
 // set printer attribute
-		self->printer = PyString_FromString("");
+		self->printer = PyUnicode_FromString("");
 		if (self->printer == nullptr){
 			Py_DECREF(self);
 			return nullptr;
 		}
 // set file attribute
-		self->file = PyString_FromString("");
+		self->file = PyUnicode_FromString("");
 		if (self->file == nullptr){
 			Py_DECREF(self);
 			return nullptr;
 		}
 // set cmd attribute
-		self->cmd = PyString_FromString("");
+		self->cmd = PyUnicode_FromString("");
 		if (self->cmd == nullptr){
 			Py_DECREF(self);
 			return nullptr;
@@ -102,7 +102,7 @@
 			return nullptr;
 		}
 // set separation attribute
-		self->separation = PyString_FromString("No");
+		self->separation = PyUnicode_FromString("No");
 		if (self->separation == nullptr){
 			Py_DECREF(self);
 			return nullptr;
@@ -143,18 +143,18 @@
 		QString prn = printers[i];
 		if (prn.isEmpty())
 			continue;
-		PyObject *tmppr = PyString_FromString(prn.toLocal8Bit().constData());
+		PyObject *tmppr = PyUnicode_FromString(prn.toUtf8().constData());
 		if (tmppr){
 			PyList_Append(self->allPrinters, tmppr);
 			Py_DECREF(tmppr);
 		}
 	}
-	PyObject *tmp2 = PyString_FromString("File");
+	PyObject *tmp2 = PyUnicode_FromString("File");
 	PyList_Append(self->allPrinters, tmp2);
 	Py_DECREF(tmp2);
 // as defaut set to print into file
 	PyObject *printer = nullptr;
-	printer = PyString_FromString("File");
+	printer = PyUnicode_FromString("File");
 	if (printer){
 		Py_DECREF(self->printer);
 		self->printer = printer;
@@ -166,7 +166,7 @@
 		tf = fi.path()+"/"+fi.baseName()+".pdf";
 	}
 	PyObject *file = nullptr;
-	file = PyString_FromString(tf.toLatin1());
+	file = PyUnicode_FromString(tf.toUtf8());
 	if (file){
 		Py_DECREF(self->file);
 		self->file = file;
@@ -176,7 +176,7 @@
 	}
 // alternative printer commands default to ""
 	PyObject *cmd = nullptr;
-	cmd = PyString_FromString("");
+	cmd = PyUnicode_FromString("");
 	if (cmd){
 		Py_DECREF(self->cmd);
 		self->cmd = cmd;
@@ -192,13 +192,13 @@
 	}
 	for (int i = 0; i<num; i++) {
 		PyObject *tmp=nullptr;
-		tmp = PyInt_FromLong((long)i+1L); // instead of 1 put here first page number
+		tmp = PyLong_FromLong((long)i+1L); // instead of 1 put here first page number
 		if (tmp)
 			PyList_SetItem(self->pages, i, tmp);
 	}
 // do not print separation
 	PyObject *separation = nullptr;
-	separation = PyString_FromString("No");
+	separation = PyUnicode_FromString("No");
 	if (separation){
 		Py_DECREF(self->separation);
 		self->separation = separation;
@@ -257,7 +257,7 @@
 		PyErr_SetString(PyExc_TypeError, "Cannot delete 'printer' attribute.");
 		return -1;
 	}
-	if (!PyString_Check(value)) {
+	if (!PyUnicode_Check(value)) {
 		PyErr_SetString(PyExc_TypeError, "The 'printer' attribute value must be string.");
 		return -1;
 	}
@@ -288,7 +288,7 @@
 		PyErr_SetString(PyExc_TypeError, "Cannot delete 'file' attribute.");
 		return -1;
 	}
-	if (!PyString_Check(value)) {
+	if (!PyUnicode_Check(value)) {
 		PyErr_SetString(PyExc_TypeError, "The 'file' attribute value must be string.");
 		return -1;
 	}
@@ -310,7 +310,7 @@
 		PyErr_SetString(PyExc_TypeError, "Cannot delete 'cmd' attribute.");
 		return -1;
 	}
-	if (!PyString_Check(value)) {
+	if (!PyUnicode_Check(value)) {
 		PyErr_SetString(PyExc_TypeError, "The 'cmd' attribute value must be string.");
 		return -1;
 	}
@@ -339,11 +339,11 @@
 	int len = PyList_Size(value);
 	for (int i = 0; i<len; i++){
 		PyObject *tmp = PyList_GetItem(value, i);
-		if (!PyInt_Check(tmp)){
+		if (!PyLong_Check(tmp)){
 			PyErr_SetString(PyExc_TypeError, "'pages' attribute must be list containing only integers.");
 			return -1;
 		}
-		if (PyInt_AsLong(tmp) > static_cast<int>(ScCore->primaryMainWindow()->doc->Pages->count()) || PyInt_AsLong(tmp) < 1) {
+		if (PyLong_AsLong(tmp) > static_cast<int>(ScCore->primaryMainWindow()->doc->Pages->count()) || PyLong_AsLong(tmp) < 1) {
 			PyErr_SetString(PyExc_ValueError, "'pages' value out of range.");
 			return -1;
 		}
@@ -366,7 +366,7 @@
 		PyErr_SetString(PyExc_TypeError, "Cannot delete 'separation' attribute.");
 		return -1;
 	}
-	if (!PyString_Check(value)) {
+	if (!PyUnicode_Check(value)) {
 		PyErr_SetString(PyExc_TypeError, "The 'separation' attribute value must be string.");
 		return -1;
 	}
@@ -400,16 +400,16 @@
 	PSfile = false;
 
 //    ReOrderText(ScCore->primaryMainWindow()->doc, ScCore->primaryMainWindow()->view);
-	prn = QString(PyString_AsString(self->printer));
-	fna = QString(PyString_AsString(self->file));
-	fil = QString(PyString_AsString(self->printer)) == QString("File");
+	prn = PyUnicode_asQString(self->printer);
+	fna = PyUnicode_asQString(self->file);
+	fil = PyUnicode_asQString(self->printer) == QString("File");
 	std::vector<int> pageNs;
 	PrintOptions options;
 	for (int i = 0; i < PyList_Size(self->pages); ++i) {
-		options.pageNumbers.push_back((int)PyInt_AsLong(PyList_GetItem(self->pages, i)));
+		options.pageNumbers.push_back((int) PyLong_AsLong(PyList_GetItem(self->pages, i)));
 	}
 	int copyCount = (self->copies < 1) ? 1 : self->copies;
-	SepName = QString(PyString_AsString(self->separation));
+	SepName = PyUnicode_asQString(self->separation);
 	options.printer   = prn;
 	options.prnEngine = (PrintEngine) self->pslevel;
 	options.toFile    = fil;
@@ -427,7 +427,7 @@
 	options.bleeds.set(0, 0, 0, 0);
 	if (!PrinterUtil::checkPrintEngineSupport(options.printer, options.prnEngine, options.toFile))
 		options.prnEngine = PrinterUtil::getDefaultPrintEngine(options.printer, options.toFile);
-	printcomm = QString(PyString_AsString(self->cmd));
+	printcomm = PyUnicode_asQString(self->cmd);
 	QMap<QString, QMap<uint, FPointArray> > ReallyUsed;
 	ReallyUsed.clear();
 	ScCore->primaryMainWindow()->doc->getUsedFonts(ReallyUsed);
@@ -509,8 +509,7 @@
 };
 
 PyTypeObject Printer_Type = {
-	PyObject_HEAD_INIT(nullptr)   // PyObject_VAR_HEAD
-	0,			 //
+	PyVarObject_HEAD_INIT(nullptr, 0)   // PyObject_VAR_HEAD	 //
 	const_cast<char*>("scribus.Printer"), // char *tp_name; /* For printing, in format "<module>.<name>" */
 	sizeof(Printer),   // int tp_basicsize, /* For allocation */
 	0,		       // int tp_itemsize; /* For allocation */
@@ -585,6 +584,8 @@
 	nullptr, //     PyObject *tp_subclasses;
 	nullptr, //     PyObject *tp_weaklist;
 	nullptr, //     destructor tp_del;
+	0, //	 unsigned int tp_version_tag;
+	0, //	 destructor tp_finalize;
 
 #ifdef COUNT_ALLOCS
 	/* these must be last and never explicitly initialized */
Index: scribus/plugins/scriptplugin/scriptercore.cpp
===================================================================
--- scribus/plugins/scriptplugin/scriptercore.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/scriptercore.cpp	(working copy)
@@ -17,6 +17,7 @@
 #include <QPixmap>
 #include <cstdlib>
 
+#include "cmdutil.h"
 #include "runscriptdialog.h"
 #include "ui/helpbrowser.h"
 #include "ui/marksmanager.h"
@@ -256,7 +257,7 @@
 		global_state = PyThreadState_Get();
 		state = Py_NewInterpreter();
 		// Init the scripter module in the sub-interpreter
-		initscribus(ScCore->primaryMainWindow());
+		//initscribus(ScCore->primaryMainWindow());
 	}
 
 	// Make sure sys.argv[0] is the path to the script
@@ -263,13 +264,13 @@
 	arguments.prepend(na.data());
 	//convert arguments (QListString) to char** for Python bridge
 	/* typically arguments == ['path/to/script.py','--argument1','valueforarg1','--flag']*/
-	char **comm = new char*[arguments.size()];
+	wchar_t **comm = new wchar_t*[arguments.size()];
 	for (int i = 0; i < arguments.size(); i++)
 	{
-		QByteArray localStr = arguments.at(i).toLocal8Bit();
-		comm[i] = new char[localStr.size() + 1]; //+1 to allow adding '\0'. may be useless, don't know how to check.
-		comm[i][localStr.size()] = 0;
-		strncpy(comm[i], localStr.data(), localStr.size());
+		const QString& argStr = arguments.at(i);
+		comm[i] = new wchar_t[argStr.size() + 1]; //+1 to allow adding '\0'. may be useless, don't know how to check.
+		comm[i][argStr.size()] = 0;
+		argStr.toWCharArray(comm[i]);
 	}
 	PySys_SetArgv(arguments.size(), comm);
 
@@ -291,7 +292,7 @@
 		// Build the Python code to run the script
 		//QString cm = QString("from __future__ import division\n"); removed due #5252 PV
 		QString cm = QString("import sys\n");
-		cm        += QString("import cStringIO\n");
+		cm        += QString("import io\n");
 		/* Implementation of the help() in pydoc.py reads some OS variables
 		 * for output settings. I use ugly hack to stop freezing calling help()
 		 * in script. pv. */
@@ -299,7 +300,7 @@
 		cm        += QString("sys.path[0] = \"%1\"\n").arg(escapedAbsPath);
 		// Replace sys.stdin with a dummy StringIO that always returns
 		// "" for read
-		cm        += QString("sys.stdin = cStringIO.StringIO()\n");
+		cm        += QString("sys.stdin = io.StringIO()\n");
 		// tell the script if it's running in the main intepreter or a subinterpreter
 		cm        += QString("import scribus\n");
 		if (inMainInterpreter)
@@ -307,7 +308,7 @@
 		else
 			cm+= QString("scribus.mainInterpreter = False\n");
 		cm        += QString("try:\n");
-		cm        += QString("    execfile(\"%1\")\n").arg(escapedFileName);
+		cm        += QString("    exec(open(\"%1\", \"rb\").read())\n").arg(escapedFileName);
 		cm        += QString("except SystemExit:\n");
 		cm        += QString("    pass\n");
 		// Capture the text of any other exception that's raised by the interpreter
@@ -341,7 +342,7 @@
 			}
 			else if (ScCore->usingGUI())
 			{
-				QString errorMsg = PyString_AsString(errorMsgPyStr);
+				QString errorMsg = PyUnicode_asQString(errorMsgPyStr);
 				// Display a dialog to the user with the exception
 				QClipboard *cp = QApplication::clipboard();
 				cp->setText(errorMsg);
@@ -399,7 +400,7 @@
 	cm = "# -*- coding: utf8 -*- \n";
 	if (PyThreadState_Get() != nullptr)
 	{
-		initscribus(ScCore->primaryMainWindow());
+		//initscribus(ScCore->primaryMainWindow());
 		/* HACK: following loop handles all input line by line.
 		It *should* use I.C. because of docstrings etc. I.I. cannot
 		handle docstrings right.
@@ -408,8 +409,8 @@
 		works fine in plain Python. Not here. WTF? */
 		cm += (
 				"try:\n"
-				"    import cStringIO\n"
-				"    scribus._bu = cStringIO.StringIO()\n"
+				"    import io\n"
+				"    scribus._bu = io.StringIO()\n"
 				"    sys.stdout = scribus._bu\n"
 				"    sys.stderr = scribus._bu\n"
 				"    sys.argv = ['scribus']\n" // this is the PySys_SetArgv replacement
@@ -420,9 +421,9 @@
 				"    sys.stdout = sys.__stdout__\n"
 				"    sys.stderr = sys.__stderr__\n"
 				"except SystemExit:\n"
-				"    print 'Catched SystemExit - it is not good for Scribus'\n"
+				"    print ('Catched SystemExit - it is not good for Scribus')\n"
 				"except KeyboardInterrupt:\n"
-				"    print 'Catched KeyboardInterrupt - it is not good for Scribus'\n"
+				"    print ('Catched KeyboardInterrupt - it is not good for Scribus')\n"
 			  );
 	}
 	// Set up sys.argv
@@ -599,8 +600,8 @@
 		"import sys\n"
 		"import code\n"
 		"sys.path.insert(0, \"%1\")\n"
-		"import cStringIO\n"
-		"sys.stdin = cStringIO.StringIO()\n"
+		"import io\n"
+		"sys.stdin = io.StringIO()\n"
 		"scribus._ia = code.InteractiveConsole(globals())\n"
 		).arg(ScPaths::instance().scriptDir());
 	if (m_importAllNames)
Index: scribus/plugins/scriptplugin/scriptplugin.cpp
===================================================================
--- scribus/plugins/scriptplugin/scriptplugin.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/scriptplugin.cpp	(working copy)
@@ -166,20 +166,20 @@
 	if (QDir(pyHome).exists())
 	{
 		QString ph = QDir::toNativeSeparators(pyHome);
-		pythonHome = ph.toLocal8Bit();
-		Py_SetPythonHome(pythonHome.data());
+		pythonHome.resize(2 * ph.length() + 2);
+		memcpy(pythonHome.data(), ph.utf16(), 2 * ph.length() + 2);
+		Py_SetPythonHome((const wchar_t*) pythonHome.constData());
 	}
 #endif
-	Py_Initialize();
-	if (PyUnicode_SetDefaultEncoding("utf-8"))
-	{
-		qDebug("Failed to set default encoding to utf-8.\n");
-		PyErr_Clear();
-	}
 
 	scripterCore = new ScripterCore(ScCore->primaryMainWindow());
 	Q_CHECK_PTR(scripterCore);
-	initscribus(ScCore->primaryMainWindow());
+
+	PyImport_AppendInittab("scribus", &PyInit_scribus);
+	Py_Initialize();
+
+	//initscribus(ScCore->primaryMainWindow());
+	
 #ifdef HAVE_SCRIPTER2
 	scripter2_init();
 #endif
@@ -228,7 +228,7 @@
 /*static */PyObject *scribus_retval(PyObject* /*self*/, PyObject* args)
 {
 	char *Name = nullptr;
-	if (!PyArg_ParseTuple(args, (char*)"s", &Name))
+	if (!PyArg_ParseTuple(args, (char*) "s", &Name))
 		return nullptr;
 	// Because sysdefaultencoding is not utf-8, Python is returning utf-8 encoded
 	// 8-bit char* strings. Make sure Qt understands that the input is utf-8 not
@@ -236,12 +236,12 @@
 	/*RetString = QString::fromUtf8(Name);
 	RetVal = retV;*/
 	scripterCore->returnString = QString::fromUtf8(Name);
-	return PyInt_FromLong(0L);
+	return PyLong_FromLong(0L);
 }
 
 /*static */PyObject *scribus_getval(PyObject* /*self*/)
 {
-	return PyString_FromString(scripterCore->inValue.toUtf8().data());
+	return PyUnicode_FromString(scripterCore->inValue.toUtf8().data());
 }
 
 /*! \brief Translate a docstring. Small helper function for use with the
@@ -307,8 +307,8 @@
 	{const_cast<char*>("createRect"), scribus_newrect, METH_VARARGS, tr(scribus_newrect__doc__)},
 	{const_cast<char*>("createText"), scribus_newtext, METH_VARARGS, tr(scribus_newtext__doc__)},
 	{const_cast<char*>("createTable"), scribus_newtable, METH_VARARGS, tr(scribus_newtable__doc__)},
-	{const_cast<char*>("createParagraphStyle"), (PyCFunction)scribus_createparagraphstyle, METH_KEYWORDS, tr(scribus_createparagraphstyle__doc__)},
-	{const_cast<char*>("createCharStyle"), (PyCFunction)scribus_createcharstyle, METH_KEYWORDS, tr(scribus_createcharstyle__doc__)},
+	{const_cast<char*>("createParagraphStyle"), (PyCFunction)scribus_createparagraphstyle, METH_VARARGS|METH_KEYWORDS, tr(scribus_createparagraphstyle__doc__)},
+	{const_cast<char*>("createCharStyle"), (PyCFunction)scribus_createcharstyle, METH_VARARGS|METH_KEYWORDS, tr(scribus_createcharstyle__doc__)},
 	{const_cast<char*>("createCustomLineStyle"), scribus_createcustomlinestyle, METH_VARARGS, tr(scribus_createcustomlinestyle__doc__)},
 	{const_cast<char*>("currentPage"), (PyCFunction)scribus_actualpage, METH_NOARGS, tr(scribus_actualpage__doc__)},
 	{const_cast<char*>("defineColor"), scribus_newcolor, METH_VARARGS, tr(scribus_newcolor__doc__)},
@@ -453,7 +453,7 @@
 	{const_cast<char*>("redrawAll"), (PyCFunction)scribus_redraw, METH_NOARGS, tr(scribus_redraw__doc__)},
 	{const_cast<char*>("removeTableRows"), scribus_removetablerows, METH_VARARGS, tr(scribus_removetablerows__doc__)},
 	{const_cast<char*>("removeTableColumns"), scribus_removetablecolumns, METH_VARARGS, tr(scribus_removetablecolumns__doc__)},
-	{const_cast<char*>("renderFont"), (PyCFunction)scribus_renderfont, METH_KEYWORDS, tr(scribus_renderfont__doc__)},
+	{const_cast<char*>("renderFont"), (PyCFunction)scribus_renderfont, METH_VARARGS|METH_KEYWORDS, tr(scribus_renderfont__doc__)},
 	{const_cast<char*>("replaceColor"), scribus_replcolor, METH_VARARGS, tr(scribus_replcolor__doc__)},
 	{const_cast<char*>("resizeTableColumn"), scribus_resizetablecolumn, METH_VARARGS, tr(scribus_resizetablecolumn__doc__)},
 	{const_cast<char*>("resizeTableRow"), scribus_resizetablerow, METH_VARARGS, tr(scribus_resizetablerow__doc__)},
@@ -535,7 +535,7 @@
 	{const_cast<char*>("dehyphenateText"), scribus_dehyphenatetext, METH_VARARGS, tr(scribus_dehyphenatetext__doc__)},
 	{const_cast<char*>("scrollDocument"), scribus_scrolldocument, METH_VARARGS, tr(scribus_scrolldocument__doc__) },
 	{const_cast<char*>("setScaleFrameToImage"), (PyCFunction)scribus_setscaleframetoimage, METH_VARARGS, tr(scribus_setscaleframetoimage__doc__)},
-	{const_cast<char*>("setScaleImageToFrame"), (PyCFunction)scribus_setscaleimagetoframe, METH_KEYWORDS, tr(scribus_setscaleimagetoframe__doc__)},
+	{const_cast<char*>("setScaleImageToFrame"), (PyCFunction)scribus_setscaleimagetoframe, METH_VARARGS|METH_KEYWORDS, tr(scribus_setscaleimagetoframe__doc__)},
 	{const_cast<char*>("setStyle"), scribus_setstyle, METH_VARARGS, tr(scribus_setstyle__doc__)},
 	{const_cast<char*>("setCharacterStyle"), scribus_setcharstyle, METH_VARARGS, tr(scribus_setcharstyle__doc__) },
 	{const_cast<char*>("setTableStyle"), scribus_settablestyle, METH_VARARGS, tr(scribus_settablestyle__doc__)},
@@ -558,7 +558,7 @@
 	{const_cast<char*>("sizeObject"), scribus_sizeobjabs, METH_VARARGS, tr(scribus_sizeobjabs__doc__)},
 	{const_cast<char*>("statusMessage"), scribus_messagebartext, METH_VARARGS, tr(scribus_messagebartext__doc__)},
 	{const_cast<char*>("textFlowMode"), scribus_textflow, METH_VARARGS, tr(scribus_textflow__doc__)},
-	{const_cast<char*>("textOverflows"), (PyCFunction)scribus_istextoverflowing, METH_KEYWORDS, tr(scribus_istextoverflowing__doc__) },
+	{const_cast<char*>("textOverflows"), (PyCFunction)scribus_istextoverflowing, METH_VARARGS|METH_KEYWORDS, tr(scribus_istextoverflowing__doc__) },
 	{const_cast<char*>("traceText"), scribus_tracetext, METH_VARARGS, tr(scribus_tracetext__doc__)},
 	{const_cast<char*>("unGroupObject"), scribus_ungroupobj, METH_VARARGS, tr(scribus_ungroupobj__doc__)},
 	{const_cast<char*>("unlinkTextFrames"), scribus_unlinktextframes, METH_VARARGS, tr(scribus_unlinktextframes__doc__)},
@@ -565,12 +565,12 @@
 	{const_cast<char*>("valueDialog"), scribus_valdialog, METH_VARARGS, tr(scribus_valdialog__doc__)},
 	{const_cast<char*>("zoomDocument"), scribus_zoomdocument, METH_VARARGS, tr(scribus_zoomdocument__doc__)},
 	// Property magic
-	{const_cast<char*>("getPropertyCType"), (PyCFunction)scribus_propertyctype, METH_KEYWORDS, tr(scribus_propertyctype__doc__)},
-	{const_cast<char*>("getPropertyNames"), (PyCFunction)scribus_getpropertynames, METH_KEYWORDS, tr(scribus_getpropertynames__doc__)},
-	{const_cast<char*>("getProperty"), (PyCFunction)scribus_getproperty, METH_KEYWORDS, tr(scribus_getproperty__doc__)},
-	{const_cast<char*>("setProperty"), (PyCFunction)scribus_setproperty, METH_KEYWORDS, tr(scribus_setproperty__doc__)},
-// 	{const_cast<char*>("getChildren"), (PyCFunction)scribus_getchildren, METH_KEYWORDS, tr(scribus_getchildren__doc__)},
-// 	{const_cast<char*>("getChild"), (PyCFunction)scribus_getchild, METH_KEYWORDS, tr(scribus_getchild__doc__)},
+	{const_cast<char*>("getPropertyCType"), (PyCFunction)scribus_propertyctype, METH_VARARGS|METH_KEYWORDS, tr(scribus_propertyctype__doc__)},
+	{const_cast<char*>("getPropertyNames"), (PyCFunction)scribus_getpropertynames, METH_VARARGS|METH_KEYWORDS, tr(scribus_getpropertynames__doc__)},
+	{const_cast<char*>("getProperty"), (PyCFunction)scribus_getproperty, METH_VARARGS|METH_KEYWORDS, tr(scribus_getproperty__doc__)},
+	{const_cast<char*>("setProperty"), (PyCFunction)scribus_setproperty, METH_VARARGS|METH_KEYWORDS, tr(scribus_setproperty__doc__)},
+// 	{const_cast<char*>("getChildren"), (PyCFunction)scribus_getchildren, METH_VARARGS|METH_KEYWORDS, tr(scribus_getchildren__doc__)},
+// 	{const_cast<char*>("getChild"), (PyCFunction)scribus_getchild, METH_VARARGS|METH_KEYWORDS, tr(scribus_getchild__doc__)},
 	// by Christian Hausknecht
 	{const_cast<char*>("duplicateObject"), scribus_duplicateobject, METH_VARARGS, tr(scribus_duplicateobject__doc__)},
 	{const_cast<char*>("copyObject"), scribus_copyobject, METH_VARARGS, tr(scribus_copyobject__doc__)},
@@ -591,6 +591,36 @@
 	{nullptr, (PyCFunction)(nullptr), 0, nullptr} /* sentinel */
 };
 
+struct scribus_module_state
+{
+    PyObject *error;
+};
+#define GETSTATE(m) ((struct scribus_module_state*) PyModule_GetState(m))
+
+static int scribus_extension_traverse(PyObject *m, visitproc visit, void *arg)
+{
+	Py_VISIT(GETSTATE(m)->error);
+	return 0;
+}
+
+static int scribus_extension_clear(PyObject *m)
+{
+	Py_CLEAR(GETSTATE(m)->error);
+	return 0;
+}
+
+static struct PyModuleDef scribus_module_def = {
+        PyModuleDef_HEAD_INIT,
+        "scribus",
+        NULL,
+        sizeof(struct scribus_module_state),
+        scribus_methods,
+        NULL,
+        scribus_extension_traverse,
+        scribus_extension_clear,
+        NULL
+};
+
 void initscribus_failed(const char* fileName, int lineNo)
 {
 	qDebug("Scripter setup failed (%s:%i)", fileName, lineNo);
@@ -598,68 +628,78 @@
 		PyErr_Print();
 }
 
-void initscribus(ScribusMainWindow *mainWin)
+PyObject* PyInit_scribus(void)
 {
+	ScribusMainWindow* mainWin = ScCore->primaryMainWindow();
 	if (!scripterCore)
 	{
 		qWarning("scriptplugin: Tried to init scribus module, but no scripter core. Aborting.");
-		return;
+		return nullptr;
 	}
+
+	int result;
 	PyObject *m, *d;
-	PyImport_AddModule((char*)"scribus");
 
 	PyType_Ready(&Printer_Type);
 	PyType_Ready(&PDFfile_Type);
 	PyType_Ready(&ImageExport_Type);
-	m = Py_InitModule((char*)"scribus", scribus_methods);
+
+	m = PyModule_Create(&scribus_module_def);
+
 	Py_INCREF(&Printer_Type);
-	PyModule_AddObject(m, (char*)"Printer", (PyObject *) &Printer_Type);
+	result = PyModule_AddObject(m, (char*) "Printer", (PyObject *) &Printer_Type);
+	if (result != 0)
+		qDebug("scriptplugin: Could not create scribus.Printer module");
 	Py_INCREF(&PDFfile_Type);
-	PyModule_AddObject(m, (char*)"PDFfile", (PyObject *) &PDFfile_Type);
+	result = PyModule_AddObject(m, (char*) "PDFfile", (PyObject *) &PDFfile_Type);
+	if (result != 0)
+		qDebug("scriptplugin: Could not create scribus.PDFfile module");
 	Py_INCREF(&ImageExport_Type);
-	PyModule_AddObject(m, (char*)"ImageExport", (PyObject *) &ImageExport_Type);
+	PyModule_AddObject(m, (char*) "ImageExport", (PyObject *) &ImageExport_Type);
+	if (result != 0)
+		qDebug("scriptplugin: Could not create scribus.ImageExport module");
 	d = PyModule_GetDict(m);
 
 	// Set up the module exceptions
 	// common exc.
-	ScribusException = PyErr_NewException((char*)"scribus.ScribusException", nullptr, nullptr);
+	ScribusException = PyErr_NewException((char*) "scribus.ScribusException", nullptr, nullptr);
 	Py_INCREF(ScribusException);
-	PyModule_AddObject(m, (char*)"ScribusException", ScribusException);
+	PyModule_AddObject(m, (char*) "ScribusException", ScribusException);
 	// no doc open
-	NoDocOpenError = PyErr_NewException((char*)"scribus.NoDocOpenError", ScribusException, nullptr);
+	NoDocOpenError = PyErr_NewException((char*) "scribus.NoDocOpenError", ScribusException, nullptr);
 	Py_INCREF(NoDocOpenError);
-	PyModule_AddObject(m, (char*)"NoDocOpenError", NoDocOpenError);
+	PyModule_AddObject(m, (char*) "NoDocOpenError", NoDocOpenError);
 	// wrong type of frame for operation
-	WrongFrameTypeError = PyErr_NewException((char*)"scribus.WrongFrameTypeError", ScribusException, nullptr);
+	WrongFrameTypeError = PyErr_NewException((char*) "scribus.WrongFrameTypeError", ScribusException, nullptr);
 	Py_INCREF(WrongFrameTypeError);
-	PyModule_AddObject(m, (char*)"WrongFrameTypeError", WrongFrameTypeError);
+	PyModule_AddObject(m, (char*) "WrongFrameTypeError", WrongFrameTypeError);
 	// Couldn't find named object, or no named object and no selection
-	NoValidObjectError = PyErr_NewException((char*)"scribus.NoValidObjectError", ScribusException, nullptr);
+	NoValidObjectError = PyErr_NewException((char*) "scribus.NoValidObjectError", ScribusException, nullptr);
 	Py_INCREF(NoValidObjectError);
-	PyModule_AddObject(m, (char*)"NoValidObjectError", NoValidObjectError);
+	PyModule_AddObject(m, (char*) "NoValidObjectError", NoValidObjectError);
 	// Couldn't find the specified resource - font, color, etc.
-	NotFoundError = PyErr_NewException((char*)"scribus.NotFoundError", ScribusException, nullptr);
+	NotFoundError = PyErr_NewException((char*) "scribus.NotFoundError", ScribusException, nullptr);
 	Py_INCREF(NotFoundError);
-	PyModule_AddObject(m, (char*)"NotFoundError", NotFoundError);
+	PyModule_AddObject(m, (char*) "NotFoundError", NotFoundError);
 	// Tried to create an object with the same name as one that already exists
-	NameExistsError = PyErr_NewException((char*)"scribus.NameExistsError", ScribusException, nullptr);
+	NameExistsError = PyErr_NewException((char*) "scribus.NameExistsError", ScribusException, nullptr);
 	Py_INCREF(NameExistsError);
-	PyModule_AddObject(m, (char*)"NameExistsError", NameExistsError);
+	PyModule_AddObject(m, (char*) "NameExistsError", NameExistsError);
 	// Done with exception setup
 
 	// CONSTANTS
-	PyDict_SetItemString(d, const_cast<char*>("UNIT_POINTS"), PyInt_FromLong(unitIndexFromString("pt")));
-	PyDict_SetItemString(d, const_cast<char*>("UNIT_MILLIMETERS"), PyInt_FromLong(unitIndexFromString("mm")));
-	PyDict_SetItemString(d, const_cast<char*>("UNIT_INCHES"), PyInt_FromLong(unitIndexFromString("in")));
-	PyDict_SetItemString(d, const_cast<char*>("UNIT_PICAS"), PyInt_FromLong(unitIndexFromString("p")));
-	PyDict_SetItemString(d, const_cast<char*>("UNIT_CENTIMETRES"), PyInt_FromLong(unitIndexFromString("cm")));
-	PyDict_SetItemString(d, const_cast<char*>("UNIT_CICERO"), PyInt_FromLong(unitIndexFromString("c")));
-	PyDict_SetItemString(d, const_cast<char*>("UNIT_PT"), PyInt_FromLong(unitIndexFromString("pt")));
-	PyDict_SetItemString(d, const_cast<char*>("UNIT_MM"), PyInt_FromLong(unitIndexFromString("mm")));
-	PyDict_SetItemString(d, const_cast<char*>("UNIT_IN"), PyInt_FromLong(unitIndexFromString("in")));
-	PyDict_SetItemString(d, const_cast<char*>("UNIT_P"), PyInt_FromLong(unitIndexFromString("p")));
-	PyDict_SetItemString(d, const_cast<char*>("UNIT_CM"), PyInt_FromLong(unitIndexFromString("cm")));
-	PyDict_SetItemString(d, const_cast<char*>("UNIT_C"), PyInt_FromLong(unitIndexFromString("c")));
+	PyDict_SetItemString(d, const_cast<char*>("UNIT_POINTS"), PyLong_FromLong(unitIndexFromString("pt")));
+	PyDict_SetItemString(d, const_cast<char*>("UNIT_MILLIMETERS"), PyLong_FromLong(unitIndexFromString("mm")));
+	PyDict_SetItemString(d, const_cast<char*>("UNIT_INCHES"), PyLong_FromLong(unitIndexFromString("in")));
+	PyDict_SetItemString(d, const_cast<char*>("UNIT_PICAS"), PyLong_FromLong(unitIndexFromString("p")));
+	PyDict_SetItemString(d, const_cast<char*>("UNIT_CENTIMETRES"), PyLong_FromLong(unitIndexFromString("cm")));
+	PyDict_SetItemString(d, const_cast<char*>("UNIT_CICERO"), PyLong_FromLong(unitIndexFromString("c")));
+	PyDict_SetItemString(d, const_cast<char*>("UNIT_PT"), PyLong_FromLong(unitIndexFromString("pt")));
+	PyDict_SetItemString(d, const_cast<char*>("UNIT_MM"), PyLong_FromLong(unitIndexFromString("mm")));
+	PyDict_SetItemString(d, const_cast<char*>("UNIT_IN"), PyLong_FromLong(unitIndexFromString("in")));
+	PyDict_SetItemString(d, const_cast<char*>("UNIT_P"), PyLong_FromLong(unitIndexFromString("p")));
+	PyDict_SetItemString(d, const_cast<char*>("UNIT_CM"), PyLong_FromLong(unitIndexFromString("cm")));
+	PyDict_SetItemString(d, const_cast<char*>("UNIT_C"), PyLong_FromLong(unitIndexFromString("c")));
 	PyDict_SetItemString(d, const_cast<char*>("PORTRAIT"), Py_BuildValue(const_cast<char*>("i"), portraitPage));
 	PyDict_SetItemString(d, const_cast<char*>("LANDSCAPE"), Py_BuildValue(const_cast<char*>("i"), landscapePage));
 	PyDict_SetItemString(d, const_cast<char*>("NOFACINGPAGES"), Py_BuildValue(const_cast<char*>("i"), 0));
@@ -799,28 +839,28 @@
 		if (!value)
 		{
 			initscribus_failed(__FILE__, __LINE__);
-			return;
+			return nullptr;
 		}
 		// `in' is a reserved word in Python so we must replace it
 		PyObject* name;
 		if (unitGetUntranslatedStrFromIndex(i) == "in")
-			name = PyString_FromString("inch");
+			name = PyUnicode_FromString("inch");
 		else
-			name = PyString_FromString(unitGetUntranslatedStrFromIndex(i).toLatin1().constData());
+			name = PyUnicode_FromString(unitGetUntranslatedStrFromIndex(i).toUtf8().constData());
 		if (!name)
 		{
 			initscribus_failed(__FILE__, __LINE__);
-			return;
+			return nullptr;
 		}
 		if (PyDict_SetItem(d, name, value))
 		{
 			initscribus_failed(__FILE__, __LINE__);
-			return;
+			return nullptr;
 		}
 	}
 
 	// Export the Scribus version into the module namespace so scripts know what they're running in
-	PyDict_SetItemString(d, const_cast<char*>("scribus_version"), PyString_FromString(const_cast<char*>(VERSION)));
+	PyDict_SetItemString(d, const_cast<char*>("scribus_version"), PyUnicode_FromString(const_cast<char*>(VERSION)));
 	// Now build a version tuple like that provided by Python in sys.version_info
 	// The tuple is of the form (major, minor, patchlevel, extraversion, reserved)
 	QRegExp version_re("(\\d+)\\.(\\d+)\\.(\\d+)(.*)");
@@ -848,28 +888,20 @@
 	// the generated Python functions from inside the `scribus' module's context.
 	// This code makes it possible to extend the `scribus' module by running Python code
 	// from C in other ways too.
-	PyObject* builtinModule = PyImport_ImportModuleEx(const_cast<char*>("__builtin__"),
+	PyObject* builtinModule = PyImport_ImportModuleEx(const_cast<char*>("builtins"),
 			d, d, Py_BuildValue(const_cast<char*>("[]")));
 	if (builtinModule == nullptr)
 	{
-		qDebug("Failed to import __builtin__ module. Something is probably broken with your Python.");
-		return;
+		qDebug("Failed to import builtins module. Something is probably broken with your Python.");
+		return nullptr;
 	}
-	PyDict_SetItemString(d, const_cast<char*>("__builtin__"), builtinModule);
-	PyObject* exceptionsModule = PyImport_ImportModuleEx(const_cast<char*>("exceptions"),
-			d, d, Py_BuildValue(const_cast<char*>("[]")));
-	if (exceptionsModule == nullptr)
-	{
-		qDebug("Failed to import exceptions module. Something is probably broken with your Python.");
-		return;
-	}
-	PyDict_SetItemString(d, const_cast<char*>("exceptions"), exceptionsModule);
+	PyDict_SetItemString(d, const_cast<char*>("builtins"), builtinModule);
 	PyObject* warningsModule = PyImport_ImportModuleEx(const_cast<char*>("warnings"),
 			d, d, Py_BuildValue(const_cast<char*>("[]")));
 	if (warningsModule == nullptr)
 	{
 		qDebug("Failed to import warnings module. Something is probably broken with your Python.");
-		return;
+		return nullptr;
 	}
 	PyDict_SetItemString(d, const_cast<char*>("warnings"), warningsModule);
 	// Create the module-level docstring. This can be a proper unicode string, unlike
@@ -907,21 +939,11 @@
 is not exhaustive due to exceptions from called functions.\n\
 ");
 
-	PyObject* docStr = PyString_FromString(docstring.toUtf8().data());
+	PyObject* docStr = PyUnicode_FromString(docstring.toUtf8().data());
 	if (!docStr)
 		qDebug("Failed to create module-level docstring (couldn't make str)");
 	else
-	{
-		PyObject* uniDocStr = PyUnicode_FromEncodedObject(docStr, "utf-8", nullptr);
-		Py_DECREF(docStr);
-		docStr = nullptr;
-		if (!uniDocStr)
-			qDebug("Failed to create module-level docstring object (couldn't make unicode)");
-		else
-			PyDict_SetItemString(d, const_cast<char*>("__doc__"), uniDocStr);
-		Py_DECREF(uniDocStr);
-		uniDocStr = nullptr;
-	}
+		PyDict_SetItemString(d, const_cast<char*>("__doc__"), docStr);
 
 	// Wrap up pointers to the the QApp and main window and push them out
 	// to Python.
@@ -946,6 +968,8 @@
 	PyDict_SetItemString(d, const_cast<char*>("mainWindow"), wrappedMainWindow);
 	Py_DECREF(wrappedMainWindow);
 	wrappedMainWindow = nullptr;
+
+	return m;
 }
 
 /*! HACK: this removes "warning: 'blah' defined but not used" compiler warnings
Index: scribus/plugins/scriptplugin/scripts/Align_image_in_frame.py
===================================================================
--- scribus/plugins/scriptplugin/scripts/Align_image_in_frame.py	(revision 23269)
+++ scribus/plugins/scriptplugin/scripts/Align_image_in_frame.py	(working copy)
@@ -22,10 +22,9 @@
 import scribus
  
 try:
-    from Tkinter import *
-    from tkFont import Font
+    from tkinter import *
 except ImportError:
-    print "This script requires Python's Tkinter properly installed."
+    print ("This script requires Python's Tkinter properly installed.")
     scribus.messageBox('Script failed',
                'This script requires Python\'s Tkinter properly installed.',
                scribus.ICON_CRITICAL)
@@ -83,8 +82,8 @@
  
     def alignImage(self):
         if scribus.haveDoc():
-	    restore_units = scribus.getUnit()   # since there is an issue with units other than points,
-	    scribus.setUnit(0)			# we switch to points then restore later.
+            restore_units = scribus.getUnit()   # since there is an issue with units other than points,
+            scribus.setUnit(0)			# we switch to points then restore later.
             nbrSelected = scribus.selectionCount()
             objList = []
             for i in range(nbrSelected):
@@ -124,9 +123,9 @@
                     scribus.deselectAll()
                 except:
                     nothing = "nothing"
-	    scribus.setUnit(restore_units)
-	    
-	    self.master.destroy()
+            scribus.setUnit(restore_units)
+            
+            self.master.destroy()
  
  
 def main():
Index: scribus/plugins/scriptplugin/scripts/CalendarWizard.py
===================================================================
--- scribus/plugins/scriptplugin/scripts/CalendarWizard.py	(revision 23269)
+++ scribus/plugins/scriptplugin/scripts/CalendarWizard.py	(working copy)
@@ -54,16 +54,16 @@
 try:
     from scribus import *
 except ImportError:
-    print "This Python script is written for the Scribus scripting interface."
-    print "It can only be run from within Scribus."
+    print ("This Python script is written for the Scribus scripting interface.")
+    print ("It can only be run from within Scribus.")
     sys.exit(1)
 
 try:
     # I wish PyQt installed everywhere :-/
-    from Tkinter import *
-    from tkFont import Font
+    from tkinter import *
+    from tkinter import font
 except ImportError:
-    print "This script requires Python's Tkinter properly installed."
+    print ("This script requires Python's Tkinter properly installed.")
     messageBox('Script failed',
                'This script requires Python\'s Tkinter properly installed.',
                ICON_CRITICAL)
@@ -307,14 +307,14 @@
         ScCalendar.__init__(self, year, months, firstDay, drawSauce, sepMonths, lang)
 
     def printMonth(self, cal, month, week):
-	    """ Print the month name(s) """
-	    if week[6].day < 7:
-		    if (week == cal[len(cal)-1]):
-			    self.createHeader(localization[self.lang][0][month] + self.sepMonths + localization[self.lang][0][(month+1)%12])
-		    elif ((month-1) not in self.months):
-			    self.createHeader(localization[self.lang][0][(month-1)%12] + self.sepMonths + localization[self.lang][0][month])
-	    else:
-		    self.createHeader(localization[self.lang][0][month])
+        """ Print the month name(s) """
+        if week[6].day < 7:
+            if (week == cal[len(cal)-1]):
+                self.createHeader(localization[self.lang][0][month] + self.sepMonths + localization[self.lang][0][(month+1)%12])
+            elif ((month-1) not in self.months):
+                self.createHeader(localization[self.lang][0][(month-1)%12] + self.sepMonths + localization[self.lang][0][month])
+        else:
+            self.createHeader(localization[self.lang][0][month])
 
     def createMonthCalendar(self, month, cal):
         """ Draw one week calendar per page """
@@ -325,12 +325,12 @@
             # * If it starts on the first weekday
             # * If the month before it isn't included
             if (week != cal[0]) or (week[0].day == 1) or ((month-1) not in self.months):
-				self.createLayout()
-				self.printMonth(cal, month, week)
-				self.printWeekNo(week)
+                self.createLayout()
+                self.printMonth(cal, month, week)
+                self.printWeekNo(week)
 
-				for day in week:
-				    self.printDay(day)
+                for day in week:
+                    self.printDay(day)
 
 class ScHorizontalEventCalendar(ScEventCalendar):
     """ One day = one row calendar. I suggest LANDSCAPE orientation.\
@@ -445,11 +445,11 @@
                 cel = createText(self.marginl + colCnt * self.colSize,
                                  self.calHeight + rowCnt * self.rowSize,
                                  self.colSize, self.rowSize)
-		setLineColor("Black", cel)  # comment this out if you do not want border to cells
+                setLineColor("Black", cel)  # comment this out if you do not want border to cells
                 colCnt += 1
                 if day.month == month + 1:
-					setText(str(day.day), cel)
-					setStyle(self.pStyleDate, cel)
+                    setText(str(day.day), cel)
+                    setStyle(self.pStyleDate, cel)
             rowCnt += 1
 
 class ScVerticalEventCalendar(ScVerticalCalendar, ScEventCalendar):
@@ -507,7 +507,7 @@
         self.langScrollbar.config(command=self.langListbox.yview)
 
         keys = localization.keys()
-        keys.sort()
+        sorted(keys)
         for i in keys:
             self.langListbox.insert(END, i)
         self.langButton = Button(self, text='Change language', command=self.languageChange)
Index: scribus/plugins/scriptplugin/scripts/Caption.py
===================================================================
--- scribus/plugins/scriptplugin/scripts/Caption.py	(revision 23269)
+++ scribus/plugins/scriptplugin/scripts/Caption.py	(working copy)
@@ -47,8 +47,8 @@
 try:
     import scribus
 except ImportError:
-    print "Unable to import the 'scribus' module. This script will only run within"
-    print "the Python interpreter embedded in Scribus. Try Script->Execute Script."
+    print ("Unable to import the 'scribus' module. This script will only run within")
+    print ("the Python interpreter embedded in Scribus. Try Script->Execute Script.")
     sys.exit(1)
 
 numselect = scribus.selectionCount()
Index: scribus/plugins/scriptplugin/scripts/color2csv.py
===================================================================
--- scribus/plugins/scriptplugin/scripts/color2csv.py	(revision 23269)
+++ scribus/plugins/scriptplugin/scripts/color2csv.py	(working copy)
@@ -46,8 +46,8 @@
     # as commonly used constants.
     import scribus
 except ImportError,err:
-    print "This Python script is written for the Scribus scripting interface."
-    print "It can only be run from within Scribus."
+    print ("This Python script is written for the Scribus scripting interface.")
+    print ("It can only be run from within Scribus.")
     sys.exit(1)
 
 #########################
Index: scribus/plugins/scriptplugin/scripts/ColorChart.py
===================================================================
--- scribus/plugins/scriptplugin/scripts/ColorChart.py	(revision 23269)
+++ scribus/plugins/scriptplugin/scripts/ColorChart.py	(working copy)
@@ -48,8 +48,8 @@
     # as commonly used constants.
     import scribus
 except ImportError,err:
-    print "This Python script is written for the Scribus scripting interface."
-    print "It can only be run from within Scribus."
+    print ("This Python script is written for the Scribus scripting interface.")
+    print ("It can only be run from within Scribus.")
     sys.exit(1)
 
 ####################
Index: scribus/plugins/scriptplugin/scripts/csv2color.py
===================================================================
--- scribus/plugins/scriptplugin/scripts/csv2color.py	(revision 23269)
+++ scribus/plugins/scriptplugin/scripts/csv2color.py	(working copy)
@@ -52,8 +52,8 @@
     # as commonly used constants.
     import scribus
 except ImportError,err:
-    print "This Python script is written for the Scribus scripting interface."
-    print "It can only be run from within Scribus."
+    print ("This Python script is written for the Scribus scripting interface.")
+    print ("It can only be run from within Scribus.")
     sys.exit(1)
 
 #########################
Index: scribus/plugins/scriptplugin/scripts/DirectImageImport.py
===================================================================
--- scribus/plugins/scriptplugin/scripts/DirectImageImport.py	(revision 23269)
+++ scribus/plugins/scriptplugin/scripts/DirectImageImport.py	(working copy)
@@ -54,7 +54,7 @@
     from scribus import *
     
 except ImportError:
-    print "This script only runs from within Scribus."
+    print ("This script only runs from within Scribus.")
     sys.exit(1)
 try:
     from PIL import Image
@@ -77,8 +77,8 @@
 
 # for images taller than they are wide we want to limit height of frame to 80% of page height
     if (Hoehe > pageY * 0.8):
-	Hoehe = pageY * 0.8
-	Breite = Hoehe * xsize/ysize
+        Hoehe = pageY * 0.8
+        Breite = Hoehe * xsize/ysize
 
     ImageFrame = createImage(pageX/2 - Breite/2, pageY/2 - Hoehe/2, Breite, Hoehe)
     loadImage(ImageFileName, ImageFrame)
Index: scribus/plugins/scriptplugin/scripts/FontSample.py
===================================================================
--- scribus/plugins/scriptplugin/scripts/FontSample.py	(revision 23269)
+++ scribus/plugins/scriptplugin/scripts/FontSample.py	(working copy)
@@ -112,7 +112,7 @@
 
 import sys
 import os
-import cPickle
+import pickle
 
 
 showPreviewPanel = 1 # change to 0 to permanently hide the preview
@@ -122,17 +122,17 @@
 
 try:
     import scribus
-except ImportError,err:
-    print 'This Python script is written for the Scribus scripting interface.'
-    print 'It can only be run from within Scribus.'
+except ImportError as err:
+    print ('This Python script is written for the Scribus scripting interface.')
+    print ('It can only be run from within Scribus.')
     sys.exit(1)
 
 
 try:
-    from Tkinter import *
-except ImportError,err:
-    print 'This script will not work without Tkinter'
-    scribus.messageBox('Error','This script will not work without Tkinter\nPlease install and try again',
+    from tkinter import *
+except ImportError as err:
+    print ('This script will not work without tkinter')
+    scribus.messageBox('Error','This script will not work without tkinter\nPlease install and try again',
                     scribus.ICON_WARNING)
     sys.exit(1)
 
@@ -139,43 +139,43 @@
 
 if not os.path.exists(CONFIG_PATH):
     try:
-        print 'Attempting to creating configuration file directory...'
+        print ('Attempting to creating configuration file directory...')
         os.mkdir(CONFIG_PATH)
-        print 'Success, now testing for write access of new directory...'
+        print ('Success, now testing for write access of new directory...')
         if os.access(CONFIG_PATH, os.W_OK):
-            print 'Write access ok.'
+            print ('Write access ok.')
         else:
-            print 'Error, unable to write to .scribus/fontsampler directory.'
+            print ('Error, unable to write to .scribus/fontsampler directory.')
     except:
         CONFIG_PATH = ''
-        print 'Failed to make configuration file directory,'
-        print 'do you have a .scribus directory in your home directory?'
-        print 'font sampler will not be able to save your preferences'
+        print ('Failed to make configuration file directory,')
+        print ('do you have a .scribus directory in your home directory?')
+        print ('font sampler will not be able to save your preferences')
 
 
 try:
     from PIL import Image
-except ImportError,err:
-    print 'You need to install Python Imaging Library (PIL).'
-    print 'If using gentoo then you need to emerge /dev-python/imaging'
-    print 'If using an RPM based linux distribution then you add python-imaging or similar.'
-    print 'Script will continue without the font preview panel.'
+except ImportError as err:
+    print ('You need to install Python Imaging Library (PIL).')
+    print ('If using gentoo then you need to emerge /dev-python/imaging')
+    print ('If using an RPM based linux distribution then you add python-imaging or similar.')
+    print ('Script will continue without the font preview panel.')
     showPreviewPanel = 0
 
 
 try:
     from PIL import ImageTk
-except ImportError,err:
-    print 'Module ImageTk not found, font preview disabled'
+except ImportError as err:
+    print ('Module ImageTk not found, font preview disabled')
     showPreviewPanel = 0
 
 
 if showPreviewPanel:
     if not os.path.exists(TEMP_PATH):
-        print '.scribus folder not found, disabling font preview panel'
+        print ('.scribus folder not found, disabling font preview panel')
         showPreviewPanel = 0
     if not os.access(TEMP_PATH, os.W_OK):
-        print 'Unable to write to .scribus folder, disabling font preview panel'
+        print ('Unable to write to .scribus folder, disabling font preview panel')
         showPreviewPanel = 0
 
 
@@ -369,7 +369,7 @@
         for j in fontList:
             errorList = errorList + j + '\n'
         errorMessage ='No suitable fixed width font found.\nPlease install at least one of these fixed width fonts:\n'+errorList
-        print errorMessage
+        print (errorMessage)
         raise Exception(errorMessage)
 
 
@@ -391,7 +391,7 @@
         for j in fontList:
             errorList = errorList + j + '\n'
         errorMessage = 'No suitable proportional font found.\nPlease install at least one of these proportional fonts:\n'+errorList
-        print errorMessage
+        print (errorMessage)
         raise Exception(errorMessage)
 
 
@@ -406,10 +406,10 @@
                 'a' : defaultPrefs,
                 'b' : userPrefs
             }
-            cPickle.dump(data, file)
+            pickle.dump(data, file)
             file.close()
         except:
-            print 'failed to save data'
+            print ('failed to save data')
 
 
 def restore_user_conf(path):
@@ -416,13 +416,13 @@
     """Restore the data from the save file on the path specified by CONFIG_PATH."""
     try:
         file = open(os.path.join(path,'fontsampler.conf'), 'r')
-        data = cPickle.load(file)
+        data = pickle.load(file)
         file.close()
         defaultPrefs.update(data['a'])
         userPrefs.update(data['b'])
     except:
         userPrefs.update(defaultPrefs)
-        print 'failed to load saved data so using default values defined in the script'
+        print ('failed to load saved data so using default values defined in the script')
 
 
 def set_page_geometry(dD, geometriesList, paperSize, wantBindingOffset):
@@ -464,7 +464,7 @@
         return result
     except:
         errorMessage = 'set_page_geometry() failure: %s' % sys.exc_info()[1]
-        print errorMessage
+        print (errorMessage)
 
 
 def set_odd_even(pageNum):
@@ -1227,10 +1227,10 @@
         """
         available = self.listbox1.size()
         selected = self.listbox2.size()
-        size = FloatType(selected)
+        size = float(selected)
         blocksPerSheet = draw_selection(scribus.getFontNames(), 1)
         value = size / blocksPerSheet
-        pages = IntType(value)                  # Get whole part of number
+        pages = int(value)                  # Get whole part of number
         value = value - pages                   # Remove whole number part
         if value > 0:                           # Test remainder
             pages = pages + 1                   # Had remainder so add a page
@@ -1241,7 +1241,7 @@
         self.statusPaperSize['text'] = 'Paper size: %s   ' % userPrefs['paperSize']
 
     def __listSelectionToRight(self):
-        toMoveRight = ListType(self.listbox1.curselection())
+        toMoveRight = list(self.listbox1.curselection())
         self.listbox1.selection_clear(0,END)
         toMoveRight.reverse()   # reverse list so we delete from bottom of listbox first
         tempList = []
@@ -1255,13 +1255,13 @@
         self.statusbarUpdate()
 
     def __listSelectionToLeft(self):
-        toMoveLeft = ListType(self.listbox2.curselection())
+        toMoveLeft = list(self.listbox2.curselection())
         toMoveLeft.reverse()
         self.listbox2.selection_clear(0,END)
         for i in toMoveLeft:
             self.listbox1.insert(END, self.listbox2.get(i)) # Insert it at the end
             self.listbox2.delete(i)
-        fontList = ListType(self.listbox1.get(0, END))      # Copy contents to a list type
+        fontList = list(self.listbox1.get(0, END))      # Copy contents to a list type
         self.listbox1.delete(0, END)                        # Remove all contents
         fontList.sort()                                     # Use sort method of list
         for j in fontList:
@@ -1508,7 +1508,7 @@
 
 
 def setup_tk():
-    """Create and setup the Tkinter app."""
+    """Create and setup the tkinter app."""
     root = Tk()
     app = Application(root)
     app.master.title(WINDOW_TITLE)
@@ -1540,7 +1540,7 @@
     restore_user_conf(CONFIG_PATH)
     # get and set the initial paper size to match default radiobutton selection...
     dD.update(set_page_geometry(dD, geometriesList, userPrefs['paperSize'], userPrefs['wantBindingOffset']))
-    # Made it this far so its time to create our Tkinter app...
+    # Made it this far so its time to create our tkinter app...
     app = setup_tk()
     # now show the main window and wait for user to do something...
     app.mainloop()
Index: scribus/plugins/scriptplugin/scripts/importcsv2table.py
===================================================================
--- scribus/plugins/scriptplugin/scripts/importcsv2table.py	(revision 23269)
+++ scribus/plugins/scriptplugin/scripts/importcsv2table.py	(working copy)
@@ -73,8 +73,8 @@
     # as commonly used constants.
     import scribus
 except ImportError,err:
-    print "This Python script is written for the Scribus scripting interface."
-    print "It can only be run from within Scribus."
+    print ("This Python script is written for the Scribus scripting interface.")
+    print ("It can only be run from within Scribus.")
     sys.exit(1)
 
 #########################
Index: scribus/plugins/scriptplugin/scripts/InfoBox.py
===================================================================
--- scribus/plugins/scriptplugin/scripts/InfoBox.py	(revision 23269)
+++ scribus/plugins/scriptplugin/scripts/InfoBox.py	(working copy)
@@ -60,8 +60,8 @@
 try:
     import scribus
 except ImportError:
-    print "Unable to import the 'scribus' module. This script will only run within"
-    print "the Python interpreter embedded in Scribus. Try Script->Execute Script."
+    print ("Unable to import the 'scribus' module. This script will only run within")
+    print ("the Python interpreter embedded in Scribus. Try Script->Execute Script.")
     sys.exit(1)
 
 def main(argv):
@@ -116,7 +116,7 @@
                                          str(o_cols) + ')?','1')
             column_pos = int(column_pos) - 1 
     if (o_cols == 1):
-	columns_width = 1
+        columns_width = 1
     new_height = 0
     while (new_height <= 0):
         new_height = scribus.valueDialog('Height','Your frame height is '+ str(o_height) +
Index: win32/msvc2015/scriptplugin/scriptplugin.vcxproj
===================================================================
--- win32/msvc2015/scriptplugin/scriptplugin.vcxproj	(revision 23269)
+++ win32/msvc2015/scriptplugin/scriptplugin.vcxproj	(working copy)
@@ -95,7 +95,7 @@
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <ClCompile>
       <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>..;..\..\..\scribus;..\..\..\scribus\ui;$(QT5_DIR)\include\QtCore;$(QT5_DIR)\include\QtGui;$(QT5_DIR)\include\QtNetwork;$(QT5_DIR)\include\QtWidgets;$(QT5_DIR)\include\QtWebKit;$(QT5_DIR)\include\QtWebKitWidgets;$(QT5_DIR)\include\QtXml;$(QT5_DIR)\include;$(CAIRO_INCLUDE_DIR);$(FREETYPE_INCLUDE_DIR);$(ICU_INCLUDE_DIR);$(LCMS_INCLUDE_DIR);$(LIBJPEG_INCLUDE_DIR);$(LIBTIFF_INCLUDE_DIR);$(PYTHON_INCLUDE_DIR);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>..;..\..\..\scribus;..\..\..\scribus\ui;$(QT5_DIR)\include\QtCore;$(QT5_DIR)\include\QtGui;$(QT5_DIR)\include\QtNetwork;$(QT5_DIR)\include\QtWidgets;$(QT5_DIR)\include\QtWebKit;$(QT5_DIR)\include\QtWebKitWidgets;$(QT5_DIR)\include\QtXml;$(QT5_DIR)\include;$(CAIRO_INCLUDE_DIR);$(FREETYPE_INCLUDE_DIR);$(ICU_INCLUDE_DIR);$(LCMS_INCLUDE_DIR);$(LIBJPEG_INCLUDE_DIR);$(LIBTIFF_INCLUDE_DIR);$(PYTHON3_INCLUDE_DIR);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>WIN32;_DEBUG;_USE_MATH_DEFINES;_USRDLL;_WINDOWS;QT_DLL;QT_GUI_LIB;QT_CORE_LIB;QT_THREAD_SUPPORT;COMPILE_PLUGIN_AS_DLL;AVOID_WIN32_FILEIO;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <MinimalRebuild>true</MinimalRebuild>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
@@ -109,8 +109,8 @@
       <ForcedIncludeFiles>plugins_pch.h;%(ForcedIncludeFiles)</ForcedIncludeFiles>
     </ClCompile>
     <Link>
-      <AdditionalDependencies>$(QT5CORE_LIB);$(QT5GUI_LIB);$(QT5WIDGETS_LIB);$(QT5XML_LIB);$(FREETYPE_LIB);$(LIBJPEG_LIB);$(LIBTIFF_LIB);$(LCMS_LIB);$(PYTHON_LIB);scribus-api.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(LCMS_LIB_DIR);$(FREETYPE_LIB_DIR);$(LIBJPEG_LIB_DIR);$(LIBTIFF_LIB_DIR);$(PYTHON_LIB_DIR)s;$(QT5_DIR)\lib;$(OutDir)..;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalDependencies>$(QT5CORE_LIB);$(QT5GUI_LIB);$(QT5WIDGETS_LIB);$(QT5XML_LIB);$(FREETYPE_LIB);$(LIBJPEG_LIB);$(LIBTIFF_LIB);$(LCMS_LIB);$(PYTHON3_LIB);scribus-api.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalLibraryDirectories>$(LCMS_LIB_DIR);$(FREETYPE_LIB_DIR);$(LIBJPEG_LIB_DIR);$(LIBTIFF_LIB_DIR);$(PYTHON3_LIB_DIR)s;$(QT5_DIR)\lib;$(OutDir)..;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <RandomizedBaseAddress>false</RandomizedBaseAddress>
@@ -121,7 +121,7 @@
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
     <ClCompile>
       <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>..;..\..\..\scribus;..\..\..\scribus\ui;$(QT5_DIR)\include\QtCore;$(QT5_DIR)\include\QtGui;$(QT5_DIR)\include\QtNetwork;$(QT5_DIR)\include\QtWidgets;$(QT5_DIR)\include\QtWebKit;$(QT5_DIR)\include\QtWebKitWidgets;$(QT5_DIR)\include\QtXml;$(QT5_DIR)\include;$(CAIRO_INCLUDE_DIR);$(FREETYPE_INCLUDE_DIR);$(ICU_INCLUDE_DIR);$(LCMS_INCLUDE_DIR);$(LIBJPEG_INCLUDE_DIR);$(LIBTIFF_INCLUDE_DIR);$(PYTHON_INCLUDE_DIR);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>..;..\..\..\scribus;..\..\..\scribus\ui;$(QT5_DIR)\include\QtCore;$(QT5_DIR)\include\QtGui;$(QT5_DIR)\include\QtNetwork;$(QT5_DIR)\include\QtWidgets;$(QT5_DIR)\include\QtWebKit;$(QT5_DIR)\include\QtWebKitWidgets;$(QT5_DIR)\include\QtXml;$(QT5_DIR)\include;$(CAIRO_INCLUDE_DIR);$(FREETYPE_INCLUDE_DIR);$(ICU_INCLUDE_DIR);$(LCMS_INCLUDE_DIR);$(LIBJPEG_INCLUDE_DIR);$(LIBTIFF_INCLUDE_DIR);$(PYTHON3_INCLUDE_DIR);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>WIN32;_DEBUG;_USE_MATH_DEFINES;_USRDLL;_WINDOWS;QT_DLL;QT_GUI_LIB;QT_CORE_LIB;QT_THREAD_SUPPORT;COMPILE_PLUGIN_AS_DLL;AVOID_WIN32_FILEIO;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -134,8 +134,8 @@
       <ForcedIncludeFiles>plugins_pch.h;%(ForcedIncludeFiles)</ForcedIncludeFiles>
     </ClCompile>
     <Link>
-      <AdditionalDependencies>$(QT5CORE_LIB);$(QT5GUI_LIB);$(QT5WIDGETS_LIB);$(QT5XML_LIB);$(FREETYPE_LIB);$(LIBJPEG_LIB);$(LIBTIFF_LIB);$(LCMS_LIB);$(PYTHON_LIB);scribus-api.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(LCMS_LIB_DIR);$(FREETYPE_LIB_DIR);$(LIBJPEG_LIB_DIR);$(LIBTIFF_LIB_DIR);$(PYTHON_LIB_DIR)s;$(QT5_DIR)\lib;$(OutDir)..;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalDependencies>$(QT5CORE_LIB);$(QT5GUI_LIB);$(QT5WIDGETS_LIB);$(QT5XML_LIB);$(FREETYPE_LIB);$(LIBJPEG_LIB);$(LIBTIFF_LIB);$(LCMS_LIB);$(PYTHON3_LIB);scribus-api.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalLibraryDirectories>$(LCMS_LIB_DIR);$(FREETYPE_LIB_DIR);$(LIBJPEG_LIB_DIR);$(LIBTIFF_LIB_DIR);$(PYTHON3_LIB_DIR)s;$(QT5_DIR)\lib;$(OutDir)..;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <RandomizedBaseAddress>false</RandomizedBaseAddress>
@@ -148,7 +148,7 @@
       <Optimization>MinSpace</Optimization>
       <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
       <OmitFramePointers>true</OmitFramePointers>
-      <AdditionalIncludeDirectories>..;..\..\..\scribus;..\..\..\scribus\ui;$(QT5_DIR)\include\QtCore;$(QT5_DIR)\include\QtGui;$(QT5_DIR)\include\QtNetwork;$(QT5_DIR)\include\QtWidgets;$(QT5_DIR)\include\QtWebKit;$(QT5_DIR)\include\QtWebKitWidgets;$(QT5_DIR)\include\QtXml;$(QT5_DIR)\include;$(CAIRO_INCLUDE_DIR);$(FREETYPE_INCLUDE_DIR);$(ICU_INCLUDE_DIR);$(LCMS_INCLUDE_DIR);$(LIBJPEG_INCLUDE_DIR);$(LIBTIFF_INCLUDE_DIR);$(PYTHON_INCLUDE_DIR);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>..;..\..\..\scribus;..\..\..\scribus\ui;$(QT5_DIR)\include\QtCore;$(QT5_DIR)\include\QtGui;$(QT5_DIR)\include\QtNetwork;$(QT5_DIR)\include\QtWidgets;$(QT5_DIR)\include\QtWebKit;$(QT5_DIR)\include\QtWebKitWidgets;$(QT5_DIR)\include\QtXml;$(QT5_DIR)\include;$(CAIRO_INCLUDE_DIR);$(FREETYPE_INCLUDE_DIR);$(ICU_INCLUDE_DIR);$(LCMS_INCLUDE_DIR);$(LIBJPEG_INCLUDE_DIR);$(LIBTIFF_INCLUDE_DIR);$(PYTHON3_INCLUDE_DIR);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>WIN32;NDEBUG;_USE_MATH_DEFINES;_USRDLL;_WINDOWS;QT_DLL;QT_GUI_LIB;QT_CORE_LIB;QT_THREAD_SUPPORT;COMPILE_PLUGIN_AS_DLL;AVOID_WIN32_FILEIO;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>true</StringPooling>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
@@ -162,8 +162,8 @@
       <ForcedIncludeFiles>plugins_pch.h;%(ForcedIncludeFiles)</ForcedIncludeFiles>
     </ClCompile>
     <Link>
-      <AdditionalDependencies>$(QT5CORE_LIB);$(QT5GUI_LIB);$(QT5WIDGETS_LIB);$(QT5XML_LIB);$(FREETYPE_LIB);$(LIBJPEG_LIB);$(LIBTIFF_LIB);$(LCMS_LIB);$(PYTHON_LIB);scribus-api.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(LCMS_LIB_DIR);$(FREETYPE_LIB_DIR);$(LIBJPEG_LIB_DIR);$(LIBTIFF_LIB_DIR);$(PYTHON_LIB_DIR)s;$(QT5_DIR)\lib;$(OutDir)..;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalDependencies>$(QT5CORE_LIB);$(QT5GUI_LIB);$(QT5WIDGETS_LIB);$(QT5XML_LIB);$(FREETYPE_LIB);$(LIBJPEG_LIB);$(LIBTIFF_LIB);$(LCMS_LIB);$(PYTHON3_LIB);scribus-api.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalLibraryDirectories>$(LCMS_LIB_DIR);$(FREETYPE_LIB_DIR);$(LIBJPEG_LIB_DIR);$(LIBTIFF_LIB_DIR);$(PYTHON3_LIB_DIR)s;$(QT5_DIR)\lib;$(OutDir)..;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
@@ -178,7 +178,7 @@
       <Optimization>MinSpace</Optimization>
       <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
       <OmitFramePointers>true</OmitFramePointers>
-      <AdditionalIncludeDirectories>..;..\..\..\scribus;..\..\..\scribus\ui;$(QT5_DIR)\include\QtCore;$(QT5_DIR)\include\QtGui;$(QT5_DIR)\include\QtNetwork;$(QT5_DIR)\include\QtWidgets;$(QT5_DIR)\include\QtWebKit;$(QT5_DIR)\include\QtWebKitWidgets;$(QT5_DIR)\include\QtXml;$(QT5_DIR)\include;$(CAIRO_INCLUDE_DIR);$(FREETYPE_INCLUDE_DIR);$(ICU_INCLUDE_DIR);$(LCMS_INCLUDE_DIR);$(LIBJPEG_INCLUDE_DIR);$(LIBTIFF_INCLUDE_DIR);$(PYTHON_INCLUDE_DIR);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>..;..\..\..\scribus;..\..\..\scribus\ui;$(QT5_DIR)\include\QtCore;$(QT5_DIR)\include\QtGui;$(QT5_DIR)\include\QtNetwork;$(QT5_DIR)\include\QtWidgets;$(QT5_DIR)\include\QtWebKit;$(QT5_DIR)\include\QtWebKitWidgets;$(QT5_DIR)\include\QtXml;$(QT5_DIR)\include;$(CAIRO_INCLUDE_DIR);$(FREETYPE_INCLUDE_DIR);$(ICU_INCLUDE_DIR);$(LCMS_INCLUDE_DIR);$(LIBJPEG_INCLUDE_DIR);$(LIBTIFF_INCLUDE_DIR);$(PYTHON3_INCLUDE_DIR);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>WIN32;NDEBUG;_USE_MATH_DEFINES;_USRDLL;_WINDOWS;QT_DLL;QT_GUI_LIB;QT_CORE_LIB;QT_THREAD_SUPPORT;COMPILE_PLUGIN_AS_DLL;AVOID_WIN32_FILEIO;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>true</StringPooling>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
@@ -192,8 +192,8 @@
       <ForcedIncludeFiles>plugins_pch.h;%(ForcedIncludeFiles)</ForcedIncludeFiles>
     </ClCompile>
     <Link>
-      <AdditionalDependencies>$(QT5CORE_LIB);$(QT5GUI_LIB);$(QT5WIDGETS_LIB);$(QT5XML_LIB);$(FREETYPE_LIB);$(LIBJPEG_LIB);$(LIBTIFF_LIB);$(LCMS_LIB);$(PYTHON_LIB);scribus-api.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(LCMS_LIB_DIR);$(FREETYPE_LIB_DIR);$(LIBJPEG_LIB_DIR);$(LIBTIFF_LIB_DIR);$(PYTHON_LIB_DIR)s;$(QT5_DIR)\lib;$(OutDir)..;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalDependencies>$(QT5CORE_LIB);$(QT5GUI_LIB);$(QT5WIDGETS_LIB);$(QT5XML_LIB);$(FREETYPE_LIB);$(LIBJPEG_LIB);$(LIBTIFF_LIB);$(LCMS_LIB);$(PYTHON3_LIB);scribus-api.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalLibraryDirectories>$(LCMS_LIB_DIR);$(FREETYPE_LIB_DIR);$(LIBJPEG_LIB_DIR);$(LIBTIFF_LIB_DIR);$(PYTHON3_LIB_DIR)s;$(QT5_DIR)\lib;$(OutDir)..;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
15030_python3_jghali.patch (140,567 bytes)   

cbradney

2019-10-23 17:02

administrator   ~0046842

@jghali.. my changes were done to make it easier

find_package (Python2 REQUIRED COMPONENTS Interpreter Development)
if (Python2_Development_FOUND)
    message("Python Library Found OK")
    set(HAVE_PYTHON ON)
    set(COMPILE_PYTHON ON)
endif()

should become:

find_package (Python3 REQUIRED COMPONENTS Interpreter Development)
if (Python3_Development_FOUND)
    message("Python 3.x Library Found OK")
    set(HAVE_PYTHON ON)
    set(COMPILE_PYTHON ON)
endif()

I think that will be it then.

william

2019-10-23 19:53

updater   ~0046844

Thanks for working on the python3 port. I will try to build it soon. I am starting a new project, and I will try making it python3. With python2 going EOL in 2 months, continuing python2 support is not as important as when the patches were first submitted two years ago. The python2 support made the original patches larger and more complicated, and maybe that was part of the problem that I had with the initialization where the scribus object wasn't visible to scripts run from the command line.
For anyone on older versions of CentOS or RHEL, I have built recent versions of some C++ applications using the updated g++ in devtoolset-8 https://www.softwarecollections.org/en/scls/rhscl/devtoolset-8/ It is a RedHat supported project that contains a gcc build that is compatible with the ABI and API of the old C++ compiler distributed with CentOS so you can use new C++ features (required by Scribus and some of its dependencies) while still linking to the shared libraries that came with the distribution.

jghali

2019-10-24 13:44

administrator   ~0046852

Here is an updated patch which fixes the scripts in the scriptplugins/scripts directory. I have also started fixing the scripts in the scriptplugins/samples directory.
15030_python3_jghali-2.patch (156,550 bytes)   
Index: CMakeLists_Dependencies.cmake
===================================================================
--- CMakeLists_Dependencies.cmake	(revision 23269)
+++ CMakeLists_Dependencies.cmake	(working copy)
@@ -144,9 +144,9 @@
 #	set(COMPILE_PYTHON ON)
 #endif()
 #
-find_package (Python2 REQUIRED COMPONENTS Interpreter Development)
-if (Python2_Development_FOUND)
-	message("Python Library Found OK")
+find_package (Python3 REQUIRED COMPONENTS Interpreter Development)
+if (Python3_Development_FOUND)
+	message("Python 3.x Library Found OK")
 	set(HAVE_PYTHON ON)
 	set(COMPILE_PYTHON ON)
 endif()
Index: scribus/main_win32.cpp
===================================================================
--- scribus/main_win32.cpp	(revision 23269)
+++ scribus/main_win32.cpp	(working copy)
@@ -153,11 +153,13 @@
 	QString pythonHome = appPath + "/python";
 	if (!QDir(pythonHome).exists())
 		return; //assume a custom python
+	pythonHome = QFileInfo(pythonHome).canonicalFilePath();
 
 	QString tmp = "PYTHONHOME=" + QDir::toNativeSeparators(pythonHome);
 	_wputenv((const wchar_t*) tmp.utf16());
 
-	QString nativePath = QDir::toNativeSeparators(appPath);
+	QString nativePath = QFileInfo(appPath).canonicalFilePath();
+	nativePath = QDir::toNativeSeparators(nativePath);
 	tmp = "PYTHONPATH=";
 	tmp += nativePath;
 	tmp += "\\python;";
Index: scribus/plugins/scriptplugin/cmdannotations.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdannotations.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/cmdannotations.cpp	(working copy)
@@ -169,7 +169,7 @@
 		break;
 	}
 
-	PyObject *rstr = PyString_FromString(rv.toUtf8());
+	PyObject *rstr = PyUnicode_FromString(rv.toUtf8());
 	return rstr;
 }
 
@@ -211,8 +211,8 @@
 
 			getLinkData(drv, a.Ziel(), a.Action());
 			const char path[] = "path";
-			PyObject *pathkey = PyString_FromString(path);
-			PyObject *pathvalue = PyString_FromString(a.Extern().toUtf8());
+			PyObject *pathkey = PyUnicode_FromString(path);
+			PyObject *pathvalue = PyUnicode_FromString(a.Extern().toUtf8());
 			PyDict_SetItem(drv, pathkey, pathvalue);
 			add_text_to_dict(drv, item);
 			PyObject *rv = Py_BuildValue("(sO)", name3, drv);
@@ -221,8 +221,8 @@
 		if (atype == Annotation::Link && actype == Annotation::Action_URI)
 		{
 			const char uri[] = "uri";
-			PyObject *ukey = PyString_FromString(uri);
-			PyObject *uval = PyString_FromString(a.Extern().toUtf8());
+			PyObject *ukey = PyUnicode_FromString(uri);
+			PyObject *uval = PyUnicode_FromString(a.Extern().toUtf8());
 			PyDict_SetItem(drv, ukey, uval);
 			add_text_to_dict(drv, item);
 			char *name4= const_cast<char*>("Link URI");
@@ -295,12 +295,12 @@
 			};
 			if (icon >= 0 && icon < 9)
 			{
-				PyObject *iconkey = PyString_FromString("icon");
-				PyObject *iconvalue = PyString_FromString(icons[icon]);
+				PyObject *iconkey = PyUnicode_FromString("icon");
+				PyObject *iconvalue = PyUnicode_FromString(icons[icon]);
 				PyDict_SetItem(drv, iconkey, iconvalue);
 			}
 
-			PyObject *openkey = PyString_FromString("open");
+			PyObject *openkey = PyUnicode_FromString("open");
 			PyObject *open = Py_False;
 			if (a.IsAnOpen())
 				open = Py_True;
@@ -585,7 +585,7 @@
 			break;
 	}
 	
-	return PyString_FromString(m_doc->Items->at(i)->itemName().toUtf8());
+	return PyUnicode_FromString(m_doc->Items->at(i)->itemName().toUtf8());
 }
 
 
@@ -613,8 +613,8 @@
 	int x, y;
 
 	const char pagenum[] = "page";
-	PyObject *pagekey = PyString_FromString(pagenum);
-	PyObject *pagevalue = PyInt_FromLong((long)page);
+	PyObject *pagekey = PyUnicode_FromString(pagenum);
+	PyObject *pagevalue = PyLong_FromLong((long)page);
 	PyDict_SetItem(rv, pagekey, pagevalue);
 	
 	QStringList qsl = action.split(" ", QString::SkipEmptyParts);
@@ -621,15 +621,15 @@
 
 	x = qsl[0].toInt();
 	const char x2[] = "x";
-	PyObject *xkey = PyString_FromString(x2);
-	PyObject *xvalue = PyInt_FromLong((long)x);
+	PyObject *xkey = PyUnicode_FromString(x2);
+	PyObject *xvalue = PyLong_FromLong((long)x);
 	PyDict_SetItem(rv, xkey, xvalue);
 
 	int height =ScCore->primaryMainWindow()->doc->pageHeight();
 	y = height - qsl[1].toInt();
 	const char y2[] = "y";
-	PyObject *ykey = PyString_FromString(y2);
-	PyObject *yvalue = PyInt_FromLong((long)y);
+	PyObject *ykey = PyUnicode_FromString(y2);
+	PyObject *yvalue = PyLong_FromLong((long)y);
 	PyDict_SetItem(rv, ykey, yvalue);
 
 	return rv;
@@ -670,9 +670,9 @@
 static void add_text_to_dict(PyObject *drv, PageItem * item)
 {
 	const char text[] = "text";
-	PyObject *textkey = PyString_FromString(text);
+	PyObject *textkey = PyUnicode_FromString(text);
 	QString txt = item->itemText.text(0, item->itemText.length());
-	PyObject *textvalue = PyString_FromString(txt.toUtf8());
+	PyObject *textvalue = PyUnicode_FromString(txt.toUtf8());
 	PyDict_SetItem(drv, textkey, textvalue);
 
 	Annotation &a = item->annotation();
@@ -681,8 +681,8 @@
 	if (actype == Annotation::Action_JavaScript)
 	{
 		const char text[] = "javascript";
-		PyObject *jskey = PyString_FromString(text);
-		PyObject *jsvalue = PyString_FromString(item->annotation().Action().toUtf8());
+		PyObject *jskey = PyUnicode_FromString(text);
+		PyObject *jsvalue = PyUnicode_FromString(item->annotation().Action().toUtf8());
 		PyDict_SetItem(drv, jskey, jsvalue);
 	}
 
@@ -694,10 +694,10 @@
 						"Named", nullptr };
 
 	const char action[] = "action";
-	PyObject *akey = PyString_FromString(action);
+	PyObject *akey = PyUnicode_FromString(action);
 	if (actype > 10)
 		actype = 6;
-	PyObject *avalue = PyString_FromString(aactions[actype]);
+	PyObject *avalue = PyUnicode_FromString(aactions[actype]);
 	PyDict_SetItem(drv, akey, avalue);
 
 	int atype = a.Type();
@@ -704,7 +704,7 @@
 	if (atype == Annotation::Checkbox || atype == Annotation::RadioButton)
 	{
 		const char checked[] = "checked";
-		PyObject *checkkey = PyString_FromString(checked);
+		PyObject *checkkey = PyUnicode_FromString(checked);
 		PyObject *checkvalue = Py_False;
 		if (a.IsChk())
 			checkvalue = Py_True;
@@ -714,7 +714,7 @@
 	if (atype == Annotation::Combobox || atype == Annotation::Listbox)
 	{
 		const char editable[] = "editable";
-		PyObject *ekey = PyString_FromString(editable);
+		PyObject *ekey = PyUnicode_FromString(editable);
 
 		PyObject *edit = Py_False;
 		int result = Annotation::Flag_Edit & a.Flag();
Index: scribus/plugins/scriptplugin/cmdcell.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdcell.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/cmdcell.cpp	(working copy)
@@ -61,7 +61,7 @@
 		PyErr_SetString(PyExc_ValueError, QObject::tr("The cell %1,%2 does not exist in table", "python error").arg(row).arg(column).toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyString_FromString(table->cellAt(row, column).styleName().toUtf8());
+	return PyUnicode_FromString(table->cellAt(row, column).styleName().toUtf8());
 }
 
 PyObject *scribus_setcellstyle(PyObject* /* self */, PyObject* args)
@@ -108,7 +108,7 @@
 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get cell row span from non-table item.","python error").toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyInt_FromLong(static_cast<long>(table->cellAt(row, column).rowSpan()));
+	return PyLong_FromLong(static_cast<long>(table->cellAt(row, column).rowSpan()));
 }
 
 PyObject *scribus_getcellcolumnspan(PyObject* /* self */, PyObject* args)
@@ -128,7 +128,7 @@
 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get cell column span from non-table item.","python error").toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyInt_FromLong(static_cast<long>(table->cellAt(row, column).columnSpan()));
+	return PyLong_FromLong(static_cast<long>(table->cellAt(row, column).columnSpan()));
 }
 
 PyObject *scribus_getcellfillcolor(PyObject* /* self */, PyObject* args)
@@ -153,7 +153,7 @@
 		PyErr_SetString(PyExc_ValueError, QObject::tr("The cell %1,%2 does not exist in table", "python error").arg(row).arg(column).toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyString_FromString(table->cellAt(row, column).fillColor().toUtf8());
+	return PyUnicode_FromString(table->cellAt(row, column).fillColor().toUtf8());
 }
 
 PyObject *scribus_setcellfillcolor(PyObject* /* self */, PyObject* args)
Index: scribus/plugins/scriptplugin/cmdcolor.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdcolor.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/cmdcolor.cpp	(working copy)
@@ -22,7 +22,7 @@
 	l = PyList_New(edc.count());
 	for (it = edc.begin(); it != edc.end(); ++it)
 	{
-		PyList_SetItem(l, cc, PyString_FromString(it.key().toUtf8()));
+		PyList_SetItem(l, cc, PyUnicode_FromString(it.key().toUtf8()));
 		cc++;
 	}
 	return l;
Index: scribus/plugins/scriptplugin/cmddialog.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmddialog.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/cmddialog.cpp	(working copy)
@@ -21,7 +21,7 @@
 	QApplication::changeOverrideCursor(QCursor(Qt::ArrowCursor));
 	bool ret = ScCore->primaryMainWindow()->slotFileNew();
 	QApplication::changeOverrideCursor(Qt::ArrowCursor);
-	return PyInt_FromLong(static_cast<long>(ret));
+	return PyLong_FromLong(static_cast<long>(ret));
 }
 
 PyObject *scribus_filedia(PyObject* /* self */, PyObject* args, PyObject* kw)
@@ -68,7 +68,7 @@
 										);
 //	QApplication::restoreOverrideCursor();
 	// FIXME: filename return unicode OK?
-	return PyString_FromString(fName.toUtf8());
+	return PyUnicode_FromString(fName.toUtf8());
 }
 
 PyObject *scribus_messdia(PyObject* /* self */, PyObject* args, PyObject* kw)
@@ -103,7 +103,7 @@
 	}
 	result = mb.exec();
 //	QApplication::restoreOverrideCursor();
-	return PyInt_FromLong(static_cast<long>(result));
+	return PyLong_FromLong(static_cast<long>(result));
 }
 
 PyObject *scribus_valdialog(PyObject* /* self */, PyObject* args)
@@ -120,7 +120,7 @@
 										QLineEdit::Normal,
 										QString::fromUtf8(value));
 //	QApplication::restoreOverrideCursor();
-	return PyString_FromString(txt.toUtf8());
+	return PyUnicode_FromString(txt.toUtf8());
 }
 
 PyObject *scribus_newstyledialog(PyObject*, PyObject* args)
@@ -143,7 +143,7 @@
 		st.create(p);
 		d->redefineStyles(st, false);
 		ScCore->primaryMainWindow()->styleMgr()->setDoc(d);
-		return PyString_FromString(s.toUtf8());
+		return PyUnicode_FromString(s.toUtf8());
 	}
 	Py_RETURN_NONE;
 }
Index: scribus/plugins/scriptplugin/cmddoc.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmddoc.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/cmddoc.cpp	(working copy)
@@ -74,7 +74,7 @@
 								orientation, firstPageNr, "Custom", true, numPages);
 	ScCore->primaryMainWindow()->doc->setPageSetFirstPage(pagesType, firstPageOrder);
 
-	return PyInt_FromLong(static_cast<long>(ret));
+	return PyLong_FromLong(static_cast<long>(ret));
 }
 
 PyObject *scribus_newdoc(PyObject* /* self */, PyObject* args)
@@ -109,7 +109,7 @@
 	btr = value2pts(btr, unit);
 	bool ret = ScCore->primaryMainWindow()->doFileNew(b, h, tpr, lr, rr, btr, 0, 1, false, ds, unit, fsl, ori, fNr, "Custom", true);
 	//	qApp->processEvents();
-	return PyInt_FromLong(static_cast<long>(ret));
+	return PyLong_FromLong(static_cast<long>(ret));
 }
 
 PyObject *scribus_setmargins(PyObject* /* self */, PyObject* args)
@@ -160,12 +160,12 @@
 	ScCore->primaryMainWindow()->doc->setModified(false);
 	bool ret = ScCore->primaryMainWindow()->slotFileClose();
 	qApp->processEvents();
-	return PyInt_FromLong(static_cast<long>(ret));
+	return PyLong_FromLong(static_cast<long>(ret));
 }
 
 PyObject *scribus_havedoc(PyObject* /* self */)
 {
-	return PyInt_FromLong(static_cast<long>(ScCore->primaryMainWindow()->HaveDoc));
+	return PyLong_FromLong(static_cast<long>(ScCore->primaryMainWindow()->HaveDoc));
 }
 
 PyObject *scribus_opendoc(PyObject* /* self */, PyObject* args)
@@ -199,9 +199,9 @@
 		return nullptr;
 	if (! ScCore->primaryMainWindow()->doc->hasName)
 	{
-		return PyString_FromString("");
+		return PyUnicode_FromString("");
 	}
-	return PyString_FromString(ScCore->primaryMainWindow()->doc->documentFileName().toUtf8());
+	return PyUnicode_FromString(ScCore->primaryMainWindow()->doc->documentFileName().toUtf8());
 }
 
 PyObject *scribus_savedocas(PyObject* /* self */, PyObject* args)
@@ -265,7 +265,7 @@
 {
 	if (!checkHaveDocument())
 		return nullptr;
-	return PyInt_FromLong(static_cast<long>(ScCore->primaryMainWindow()->doc->unitIndex()));
+	return PyLong_FromLong(static_cast<long>(ScCore->primaryMainWindow()->doc->unitIndex()));
 }
 
 PyObject *scribus_loadstylesfromfile(PyObject* /* self */, PyObject *args)
@@ -323,7 +323,7 @@
 	int n = 0;
 	for ( ; it != itEnd; ++it )
 	{
-		PyList_SET_ITEM(names, n++, PyString_FromString(it.key().toUtf8().data()) );
+		PyList_SET_ITEM(names, n++, PyUnicode_FromString(it.key().toUtf8().data()) );
 	}
 	return names;
 }
@@ -411,7 +411,7 @@
 		PyErr_SetString(PyExc_IndexError, QObject::tr("Page number out of range: '%1'.","python error").arg(e+1).toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyString_FromString(currentDoc->DocPages.at(e)->masterPageName().toUtf8());
+	return PyUnicode_FromString(currentDoc->DocPages.at(e)->masterPageName().toUtf8());
 }
 
 PyObject* scribus_applymasterpage(PyObject* /* self */, PyObject* args)
Index: scribus/plugins/scriptplugin/cmdgetprop.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdgetprop.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/cmdgetprop.cpp	(working copy)
@@ -44,7 +44,7 @@
 		result = "Multiple";
 	}
 
-	return PyString_FromString(result.toUtf8());
+	return PyUnicode_FromString(result.toUtf8());
 }
 
 PyObject *scribus_getfillcolor(PyObject* /* self */, PyObject* args)
@@ -57,7 +57,7 @@
 	PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
 	if (item == nullptr)
 		return nullptr;
-	return PyString_FromString(item->fillColor().toUtf8());
+	return PyUnicode_FromString(item->fillColor().toUtf8());
 }
 
 PyObject *scribus_getfilltrans(PyObject* /* self */, PyObject* args)
@@ -83,7 +83,7 @@
 	PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
 	if (item == nullptr)
 		return nullptr;
-	return PyInt_FromLong(static_cast<long>(item->fillBlendmode()));
+	return PyLong_FromLong(static_cast<long>(item->fillBlendmode()));
 }
 
 PyObject *scribus_getcustomlinestyle(PyObject* /* self */, PyObject* args)
@@ -96,7 +96,7 @@
 	PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
 	if (item == nullptr)
 		return nullptr;
-	return PyString_FromString(item->customLineStyle().toUtf8());
+	return PyUnicode_FromString(item->customLineStyle().toUtf8());
 }
 
 PyObject *scribus_getlinecolor(PyObject* /* self */, PyObject* args)
@@ -109,7 +109,7 @@
 	PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
 	if (item == nullptr)
 		return nullptr;
-	return PyString_FromString(item->lineColor().toUtf8());
+	return PyUnicode_FromString(item->lineColor().toUtf8());
 }
 
 PyObject *scribus_getlinetrans(PyObject* /* self */, PyObject* args)
@@ -135,7 +135,7 @@
 	PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
 	if (item == nullptr)
 		return nullptr;
-	return PyInt_FromLong(static_cast<long>(item->lineBlendmode()));
+	return PyLong_FromLong(static_cast<long>(item->lineBlendmode()));
 }
 
 PyObject *scribus_getlinewidth(PyObject* /* self */, PyObject* args)
@@ -161,7 +161,7 @@
 	PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
 	if (item == nullptr)
 		return nullptr;
-	return PyInt_FromLong(static_cast<long>(item->lineShade()));
+	return PyLong_FromLong(static_cast<long>(item->lineShade()));
 }
 
 PyObject *scribus_getlinejoin(PyObject* /* self */, PyObject* args)
@@ -174,7 +174,7 @@
 	PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
 	if (item == nullptr)
 		return nullptr;
-	return PyInt_FromLong(static_cast<long>(item->PLineJoin));
+	return PyLong_FromLong(static_cast<long>(item->PLineJoin));
 }
 
 PyObject *scribus_getlinecap(PyObject* /* self */, PyObject* args)
@@ -187,7 +187,7 @@
 	PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
 	if (item == nullptr)
 		return nullptr;
-	return PyInt_FromLong(static_cast<long>(item->PLineEnd));
+	return PyLong_FromLong(static_cast<long>(item->PLineEnd));
 }
 
 PyObject *scribus_getlinestyle(PyObject* /* self */, PyObject* args)
@@ -200,7 +200,7 @@
 	PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
 	if (item == nullptr)
 		return nullptr;
-	return PyInt_FromLong(static_cast<long>(item->PLineArt));
+	return PyLong_FromLong(static_cast<long>(item->PLineArt));
 }
 
 PyObject *scribus_getfillshade(PyObject* /* self */, PyObject* args)
@@ -213,7 +213,7 @@
 	PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
 	if (item == nullptr)
 		return nullptr;
-	return PyInt_FromLong(static_cast<long>(item->fillShade()));
+	return PyLong_FromLong(static_cast<long>(item->fillShade()));
 }
 
 PyObject *scribus_getcornerrad(PyObject* /* self */, PyObject* args)
@@ -226,7 +226,7 @@
 	PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
 	if (item == nullptr)
 		return nullptr;
-	return PyInt_FromLong(static_cast<long>(item->cornerRadius()));
+	return PyLong_FromLong(static_cast<long>(item->cornerRadius()));
 }
 
 PyObject *scribus_getimgoffset(PyObject* /* self */, PyObject* args)
@@ -265,7 +265,7 @@
 	PageItem *item = GetUniqueItem(QString::fromUtf8(Name));
 	if (item == nullptr)
 		return nullptr;
-	return PyString_FromString(item->Pfile.toUtf8());
+	return PyUnicode_FromString(item->Pfile.toUtf8());
 }
 
 PyObject *scribus_getposi(PyObject* /* self */, PyObject* args)
@@ -358,13 +358,13 @@
 			{
 				if (currentDoc->Items->at(lam)->itemType() == typ)
 				{
-					PyList_SetItem(l, counter2, PyString_FromString(currentDoc->Items->at(lam)->itemName().toUtf8()));
+					PyList_SetItem(l, counter2, PyUnicode_FromString(currentDoc->Items->at(lam)->itemName().toUtf8()));
 					counter2++;
 				}
 			}
 			else
 			{
-				PyList_SetItem(l, counter2, PyString_FromString(currentDoc->Items->at(lam)->itemName().toUtf8()));
+				PyList_SetItem(l, counter2, PyUnicode_FromString(currentDoc->Items->at(lam)->itemName().toUtf8()));
 				counter2++;
 			}
 		}
@@ -431,7 +431,7 @@
 
 	const ScImage& pixm = item->pixm;
 	if (pixm.width() == 0 || pixm.height() == 0)
-		return PyInt_FromLong(static_cast<long>(-1));
+		return PyLong_FromLong(static_cast<long>(-1));
 
 	const ImageInfoRecord& iir = pixm.imgInfo;
 	int cspace = iir.colorspace;
@@ -442,7 +442,7 @@
 	Duotone = 3,
 	Monochrome = 4
 	*/
-	return PyInt_FromLong(static_cast<long>(cspace));
+	return PyLong_FromLong(static_cast<long>(cspace));
 }
 
 
Index: scribus/plugins/scriptplugin/cmdgetsetprop.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdgetsetprop.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/cmdgetsetprop.cpp	(working copy)
@@ -15,16 +15,16 @@
 
 QObject* getQObjectFromPyArg(PyObject* arg)
 {
-	if (PyString_Check(arg))
+	if (PyUnicode_Check(arg))
 		// It's a string. Look for a pageItem by that name. Do NOT accept a
 		// selection.
-		return getPageItemByName(QString::fromUtf8(PyString_AsString(arg)));
-	if (PyCObject_Check(arg))
+		return getPageItemByName(PyUnicode_asQString(arg));
+	if (PyCapsule_CheckExact(arg))
 	{
 		// It's a PyCObject, ie a wrapped pointer. Check it's not nullptr
 		// and return it.
 		// FIXME: Try to check that its a pointer to a QObject instance
-		QObject* tempObject = (QObject*)PyCObject_AsVoidPtr(arg);
+		QObject* tempObject = (QObject*) PyCapsule_GetPointer(arg, nullptr);
 		if (!tempObject)
 		{
 			PyErr_SetString(PyExc_TypeError, "INTERNAL: Passed nullptr PyCObject");
@@ -40,7 +40,7 @@
 
 PyObject* wrapQObject(QObject* obj)
 {
-	return PyCObject_FromVoidPtr((void*)obj, nullptr);
+	return PyCapsule_New((void*) obj, nullptr, nullptr);
 }
 
 
@@ -78,13 +78,13 @@
 	objArg = nullptr; // no need to decref, it's borrowed
 
 	// Look up the property and retrive its type information
-	const char* type = getpropertytype( (QObject*)obj, propertyname, includesuper);
+	const char* type = getpropertytype( (QObject*) obj, propertyname, includesuper);
 	if (type == nullptr)
 	{
 		PyErr_SetString(PyExc_KeyError, QObject::tr("Property not found").toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyString_FromString(type);
+	return PyUnicode_FromString(type);
 }
 
 PyObject* convert_QStringList_to_PyListObject(QStringList& origlist)
@@ -94,7 +94,7 @@
 		return nullptr;
 
 	for ( QStringList::Iterator it = origlist.begin(); it != origlist.end(); ++it )
-		if (PyList_Append(resultList, PyString_FromString((*it).toUtf8().data())) == -1)
+		if (PyList_Append(resultList, PyUnicode_FromString((*it).toUtf8().data())) == -1)
 			return nullptr;
 
 	return resultList;
@@ -283,9 +283,12 @@
 		resultobj = PyBool_FromLong(prop.toBool());
 	// STRING TYPES
 	else if (prop.type() == QVariant::ByteArray)
-		resultobj = PyString_FromString(prop.toByteArray().data());
+	{
+		QByteArray ba = prop.toByteArray();
+		resultobj = PyBytes_FromStringAndSize(ba.data(), ba.size());
+	}
 	else if (prop.type() == QVariant::String)
-		resultobj = PyString_FromString(prop.toString().toUtf8().data());
+		resultobj = PyUnicode_FromString(prop.toString().toUtf8().data());
 	// HIGHER ORDER TYPES
 	else if (prop.type() == QVariant::Point)
 	{
@@ -372,10 +375,10 @@
 			success = obj->setProperty(propertyName, 0);
 		else if (PyObject_IsTrue(objValue) == 1)
 			success = obj->setProperty(propertyName, 1);
-		else if (PyInt_Check(objValue))
-			success = obj->setProperty(propertyName, PyInt_AsLong(objValue) == 0);
 		else if (PyLong_Check(objValue))
 			success = obj->setProperty(propertyName, PyLong_AsLong(objValue) == 0);
+		else if (PyLong_Check(objValue))
+			success = obj->setProperty(propertyName, PyLong_AsLong(objValue) == 0);
 		else
 			matched = false;
 	}
@@ -382,10 +385,10 @@
 	else if (propertyType == "int")
 	{
 		matched = true;
-		if (PyInt_Check(objValue))
-			success = obj->setProperty(propertyName, (int)PyInt_AsLong(objValue));
+		if (PyLong_Check(objValue))
+			success = obj->setProperty(propertyName, (int) PyLong_AsLong(objValue));
 		else if (PyLong_Check(objValue))
-			success = obj->setProperty(propertyName, (int)PyLong_AsLong(objValue));
+			success = obj->setProperty(propertyName, (int) PyLong_AsLong(objValue));
 		else
 			matched = false;
 	}
@@ -402,8 +405,8 @@
 	else if (propertyType == "QString")
 	{
 		matched = true;
-		if (PyString_Check(objValue))
-			success = obj->setProperty(propertyName, QString::fromUtf8(PyString_AsString(objValue)));
+		if (PyBytes_Check(objValue))
+			success = obj->setProperty(propertyName, QString::fromUtf8(PyBytes_AsString(objValue)));
 		else if (PyUnicode_Check(objValue))
 		{
 			// Get a pointer to the internal buffer of the Py_Unicode object, which is UCS2 formatted
@@ -417,11 +420,11 @@
 	else if (propertyType == "QCString")
 	{
 		matched = true;
-		if (PyString_Check(objValue))
+		if (PyBytes_Check(objValue))
 		{
 			// FIXME: should raise an exception instead of mangling the string when
 			// out of charset chars present.
-			QString utfString = QString::fromUtf8(PyString_AsString(objValue));
+			QString utfString = QString::fromUtf8(PyBytes_AsString(objValue));
 			success = obj->setProperty(propertyName, utfString.toLatin1());
 		}
 		else if (PyUnicode_Check(objValue))
@@ -454,7 +457,7 @@
 		if (!objRepr)
 			return nullptr;
 		// Extract the repr() string
-		QString reprString = QString::fromUtf8(PyString_AsString(objRepr));
+		QString reprString = PyUnicode_asQString(objRepr);
 		Py_DECREF(objRepr);
 
 		// And return an error
Index: scribus/plugins/scriptplugin/cmdmani.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdmani.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/cmdmani.cpp	(working copy)
@@ -350,7 +350,7 @@
 
 PyObject *scribus_groupobj(PyObject* /* self */, PyObject* args)
 {
-	char *Name = const_cast<char*>("");
+	const char *Name = const_cast<char*>("");
 	PyObject *il = nullptr;
 	if (!PyArg_ParseTuple(args, "|O", &il))
 		return nullptr;
@@ -361,8 +361,8 @@
 		PyErr_SetString(PyExc_TypeError, QObject::tr("Need selection or argument list of items to group", "python error").toLocal8Bit().constData());
 		return nullptr;
 	}
-	Selection *tempSelection=nullptr;
-	Selection *finalSelection=nullptr;
+	Selection *tempSelection = nullptr;
+	Selection *finalSelection = nullptr;
 	//uint ap = ScCore->primaryMainWindow()->doc->currentPage()->pageNr();
 	// If we were passed a list of items to group...
 	if (il != nullptr)
@@ -374,7 +374,7 @@
 			// FIXME: We might need to explicitly get this string as utf8
 			// but as sysdefaultencoding is utf8 it should be a no-op to do
 			// so anyway.
-			Name = PyString_AsString(PyList_GetItem(il, i));
+			Name = PyUnicode_AsUTF8(PyList_GetItem(il, i));
 			PageItem *ic = GetUniqueItem(QString::fromUtf8(Name));
 			if (ic == nullptr)
 			{
@@ -383,10 +383,10 @@
 			}
 			tempSelection->addItem (ic, true);
 		}
-		finalSelection=tempSelection;
+		finalSelection = tempSelection;
 	}
 	else
-		finalSelection=ScCore->primaryMainWindow()->doc->m_Selection;
+		finalSelection = ScCore->primaryMainWindow()->doc->m_Selection;
 	if (finalSelection->count() < 2)
 	{
 		// We can't very well group only one item
@@ -400,7 +400,7 @@
 	finalSelection=nullptr;
 	delete tempSelection;
 	
-	return (group ? PyString_FromString(group->itemName().toUtf8()) : nullptr);
+	return (group ? PyUnicode_FromString(group->itemName().toUtf8()) : nullptr);
 }
 
 PyObject *scribus_ungroupobj(PyObject* /* self */, PyObject* args)
@@ -460,10 +460,11 @@
 		return nullptr;
 	if (!checkHaveDocument())
 		return nullptr;
-	if ((i < static_cast<int>(ScCore->primaryMainWindow()->doc->m_Selection->count())) && (i > -1))
-		return PyString_FromString(ScCore->primaryMainWindow()->doc->m_Selection->itemAt(i)->itemName().toUtf8());
+	Selection * selection = ScCore->primaryMainWindow()->doc->m_Selection;
+	if ((i < selection->count()) && (i > -1))
+		return PyUnicode_FromString(selection->itemAt(i)->itemName().toUtf8());
 	// FIXME: Should probably return None if no selection?
-	return PyString_FromString("");
+	return PyUnicode_FromString("");
 }
 
 PyObject *scribus_selcount(PyObject* /* self */)
@@ -470,7 +471,7 @@
 {
 	if (!checkHaveDocument())
 		return nullptr;
-	return PyInt_FromLong(static_cast<long>(ScCore->primaryMainWindow()->doc->m_Selection->count()));
+	return PyLong_FromLong(static_cast<long>(ScCore->primaryMainWindow()->doc->m_Selection->count()));
 }
 
 PyObject *scribus_selectobj(PyObject* /* self */, PyObject* args)
@@ -507,8 +508,8 @@
 		return nullptr;
 	item->toggleLock();
 	if (item->locked())
-		return PyInt_FromLong(1);
-	return PyInt_FromLong(0);
+		return PyLong_FromLong(1);
+	return PyLong_FromLong(0);
 }
 
 PyObject *scribus_islocked(PyObject* /* self */, PyObject* args)
Index: scribus/plugins/scriptplugin/cmdmisc.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdmisc.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/cmdmisc.cpp	(working copy)
@@ -47,7 +47,7 @@
 	{
 		if (it.current().usable())
 		{
-			PyList_SetItem(l, cc, PyString_FromString(it.currentKey().toUtf8()));
+			PyList_SetItem(l, cc, PyUnicode_FromString(it.currentKey().toUtf8()));
 			cc++;
 		}
 	}
@@ -110,8 +110,7 @@
 		// User specified no format, so use the historical default of PPM format.
 		format =  const_cast<char*>("PPM");
 	QPixmap pm = FontSample(PrefsManager::instance().appPrefs.fontPrefs.AvailFonts[QString::fromUtf8(Name)], Size, ts, Qt::white);
-	// If the user specified an empty filename, return the image data as
-	// a string. Otherwise, save it to disk.
+	// If the user specified an empty filename, return the image data as bytes. Otherwise, save it to disk.
 	if (QString::fromUtf8(FileName).isEmpty())
 	{
 		QByteArray buffer_string = "";
@@ -126,7 +125,7 @@
 		int bufferSize = buffer.size();
 		buffer.close();
 		// Now make a Python string from the data we generated
-		PyObject* stringPython = PyString_FromStringAndSize(buffer_string,bufferSize);
+		PyObject* stringPython = PyBytes_FromStringAndSize(buffer_string, bufferSize);
 		// Return even if the result is nullptr (error) since an exception will have been
 		// set in that case.
 		return stringPython;
@@ -150,10 +149,10 @@
 {
 	if (!checkHaveDocument())
 		return nullptr;
-	PyObject *l;
-	l = PyList_New(ScCore->primaryMainWindow()->doc->Layers.count());
-	for (int lam=0; lam < ScCore->primaryMainWindow()->doc->Layers.count(); lam++)
-		PyList_SetItem(l, lam, PyString_FromString(ScCore->primaryMainWindow()->doc->Layers[lam].Name.toUtf8()));
+	ScribusDoc* doc = ScCore->primaryMainWindow()->doc;
+	PyObject *l = PyList_New(doc->Layers.count());
+	for (int i = 0; i < doc->Layers.count(); i++)
+		PyList_SetItem(l, i, PyUnicode_FromString(doc->Layers[i].Name.toUtf8()));
 	return l;
 }
 
@@ -184,7 +183,7 @@
 {
 	if (!checkHaveDocument())
 		return nullptr;
-	return PyString_FromString(ScCore->primaryMainWindow()->doc->activeLayerName().toUtf8());
+	return PyUnicode_FromString(ScCore->primaryMainWindow()->doc->activeLayerName().toUtf8());
 }
 
 PyObject *scribus_senttolayer(PyObject* /* self */, PyObject* args)
@@ -474,7 +473,7 @@
 		PyErr_SetString(NotFoundError, QObject::tr("Layer not found.","python error").toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyInt_FromLong(static_cast<long>(i));
+	return PyLong_FromLong(static_cast<long>(i));
 }
 
 PyObject *scribus_glayerprint(PyObject* /* self */, PyObject* args)
@@ -505,7 +504,7 @@
 		PyErr_SetString(NotFoundError, QObject::tr("Layer not found.","python error").toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyInt_FromLong(static_cast<long>(i));
+	return PyLong_FromLong(static_cast<long>(i));
 }
 
 PyObject *scribus_glayerlock(PyObject* /* self */, PyObject* args)
@@ -536,7 +535,7 @@
 		PyErr_SetString(NotFoundError, QObject::tr("Layer not found.","python error").toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyInt_FromLong(static_cast<long>(i));
+	return PyLong_FromLong(static_cast<long>(i));
 }
 
 PyObject *scribus_glayeroutline(PyObject* /* self */, PyObject* args)
@@ -567,7 +566,7 @@
 		PyErr_SetString(NotFoundError, QObject::tr("Layer not found.","python error").toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyInt_FromLong(static_cast<long>(i));
+	return PyLong_FromLong(static_cast<long>(i));
 }
 
 PyObject *scribus_glayerflow(PyObject* /* self */, PyObject* args)
@@ -598,7 +597,7 @@
 		PyErr_SetString(NotFoundError, QObject::tr("Layer not found.","python error").toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyInt_FromLong(static_cast<long>(i));
+	return PyLong_FromLong(static_cast<long>(i));
 }
 
 PyObject *scribus_glayerblend(PyObject* /* self */, PyObject* args)
@@ -629,7 +628,7 @@
 		PyErr_SetString(NotFoundError, QObject::tr("Layer not found.","python error").toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyInt_FromLong(static_cast<long>(i));
+	return PyLong_FromLong(static_cast<long>(i));
 }
 
 PyObject *scribus_glayertrans(PyObject* /* self */, PyObject* args)
@@ -735,7 +734,7 @@
 
 PyObject *scribus_getlanguage(PyObject* /* self */)
 {
-	return PyString_FromString(ScCore->getGuiLanguage().toUtf8());
+	return PyUnicode_FromString(ScCore->getGuiLanguage().toUtf8());
 }
 
 /*! 04.01.2007 : Joachim Neu : Moves item selection to front. */
Index: scribus/plugins/scriptplugin/cmdobj.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdobj.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/cmdobj.cpp	(working copy)
@@ -31,19 +31,20 @@
 //		PyErr_SetString(NameExistsError, QObject::tr("An object with the requested name already exists.","python error"));
 //		return nullptr;
 //	}
-	int i = ScCore->primaryMainWindow()->doc->itemAdd(PageItem::Polygon, PageItem::Rectangle,
-								pageUnitXToDocX(x), pageUnitYToDocY(y),
-								ValueToPoint(w), ValueToPoint(h),
-								ScCore->primaryMainWindow()->doc->itemToolPrefs().shapeLineWidth,
-								ScCore->primaryMainWindow()->doc->itemToolPrefs().shapeFillColor, ScCore->primaryMainWindow()->doc->itemToolPrefs().shapeLineColor);
+	ScribusDoc* doc = ScCore->primaryMainWindow()->doc;
+	int i = doc->itemAdd(PageItem::Polygon, PageItem::Rectangle,
+						pageUnitXToDocX(x), pageUnitYToDocY(y),
+						ValueToPoint(w), ValueToPoint(h),
+						doc->itemToolPrefs().shapeLineWidth,
+						doc->itemToolPrefs().shapeFillColor, doc->itemToolPrefs().shapeLineColor);
 //	ScCore->primaryMainWindow()->doc->setRedrawBounding(ScCore->primaryMainWindow()->doc->Items->at(i));
 	if (strlen(Name) > 0)
 	{
 		QString objName = QString::fromUtf8(Name);
 		if (!ItemExists(objName))
-			ScCore->primaryMainWindow()->doc->Items->at(i)->setItemName(objName);
+			doc->Items->at(i)->setItemName(objName);
 	}
-	return PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
+	return PyUnicode_FromString(doc->Items->at(i)->itemName().toUtf8());
 }
 
 
@@ -69,7 +70,7 @@
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(i)->setItemName(objName);
 	}
-	return PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
+	return PyUnicode_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
 }
 
 
@@ -94,7 +95,7 @@
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(i)->setItemName(objName);
 	}
-	return PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
+	return PyUnicode_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
 }
 
 
@@ -119,7 +120,7 @@
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(i)->setItemName(objName);
 	}
-	return PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
+	return PyUnicode_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
 }
 
 PyObject *scribus_newtable(PyObject* /* self */, PyObject* args)
@@ -155,7 +156,7 @@
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(i)->setItemName(objName);
 	}
-	return PyString_FromString(table->itemName().toUtf8());
+	return PyUnicode_FromString(table->itemName().toUtf8());
 }
 
 PyObject *scribus_newline(PyObject* /* self */, PyObject* args)
@@ -215,7 +216,7 @@
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(i)->setItemName(objName);
 	}
-	return PyString_FromString(it->itemName().toUtf8());
+	return PyUnicode_FromString(it->itemName().toUtf8());
 }
 
 
@@ -292,7 +293,7 @@
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(ic)->setItemName(objName);
 	}
-	return PyString_FromString(it->itemName().toUtf8());
+	return PyUnicode_FromString(it->itemName().toUtf8());
 }
 
 
@@ -374,7 +375,7 @@
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(ic)->setItemName(objName);
 	}
-	return PyString_FromString(it->itemName().toUtf8());
+	return PyUnicode_FromString(it->itemName().toUtf8());
 }
 
 PyObject *scribus_bezierline(PyObject* /* self */, PyObject* args)
@@ -465,7 +466,7 @@
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(ic)->setItemName(objName);
 	}
-	return PyString_FromString(it->itemName().toUtf8());
+	return PyUnicode_FromString(it->itemName().toUtf8());
 }
 
 
@@ -506,7 +507,7 @@
 		if (!ItemExists(objName))
 			i->setItemName(objName);
 	}
-	return PyString_FromString(i->itemName().toUtf8());
+	return PyUnicode_FromString(i->itemName().toUtf8());
 }
 
 
@@ -605,13 +606,13 @@
 		int selectionStart = item->itemText.startOfSelection();
 		const ParagraphStyle& currentStyle = item->itemText.paragraphStyle(selectionStart);
 		if (currentStyle.hasParent())
-			return PyString_FromString(currentStyle.parentStyle()->name().toUtf8());
+			return PyUnicode_FromString(currentStyle.parentStyle()->name().toUtf8());
 	}
 	else
 	{
 		const ParagraphStyle& itemDefaultStyle = item->itemText.defaultStyle();
 		if (itemDefaultStyle.hasParent())
-			return PyString_FromString(itemDefaultStyle.parentStyle()->name().toUtf8());
+			return PyUnicode_FromString(itemDefaultStyle.parentStyle()->name().toUtf8());
 	}
 	Py_RETURN_NONE;
 };
@@ -798,7 +799,7 @@
 	styleList = PyList_New(0);
 	for (int i = 0; i < paragraphStyles.count(); ++i)
 	{
-		if (PyList_Append(styleList, PyString_FromString(paragraphStyles[i].name().toUtf8())))
+		if (PyList_Append(styleList, PyUnicode_FromString(paragraphStyles[i].name().toUtf8())))
 		{
 			// An exception will have already been set by PyList_Append apparently.
 			return nullptr;
@@ -817,7 +818,7 @@
 	charStyleList = PyList_New(0);
 	for (int i = 0; i < charStyles.count(); ++i)
 	{
-		if (PyList_Append(charStyleList, PyString_FromString(charStyles[i].name().toUtf8())))
+		if (PyList_Append(charStyleList, PyUnicode_FromString(charStyles[i].name().toUtf8())))
 		{
 			// An exception will have already been set by PyList_Append apparently.
 			return nullptr;
Index: scribus/plugins/scriptplugin/cmdpage.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdpage.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/cmdpage.cpp	(working copy)
@@ -18,7 +18,7 @@
 {
 	if (!checkHaveDocument())
 		return nullptr;
-	return PyInt_FromLong(static_cast<long>(ScCore->primaryMainWindow()->doc->currentPageNumber() + 1));
+	return PyLong_FromLong(static_cast<long>(ScCore->primaryMainWindow()->doc->currentPageNumber() + 1));
 }
 
 PyObject *scribus_redraw(PyObject* /* self */)
@@ -45,7 +45,7 @@
 		PyErr_SetString(PyExc_IndexError, QObject::tr("Page number out of range.","python error").toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyInt_FromLong(static_cast<long>(ScCore->primaryMainWindow()->doc->locationOfPage(e)));
+	return PyLong_FromLong(static_cast<long>(ScCore->primaryMainWindow()->doc->locationOfPage(e)));
 }
 
 PyObject *scribus_savepageeps(PyObject* /* self */, PyObject* args)
@@ -167,7 +167,7 @@
 {
 	if (!checkHaveDocument())
 		return nullptr;
-	return PyInt_FromLong(static_cast<long>(ScCore->primaryMainWindow()->doc->Pages->count()));
+	return PyLong_FromLong(static_cast<long>(ScCore->primaryMainWindow()->doc->Pages->count()));
 }
 
 PyObject *scribus_pagedimension(PyObject* /* self */)
Index: scribus/plugins/scriptplugin/cmdsetprop.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdsetprop.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/cmdsetprop.cpp	(working copy)
@@ -447,7 +447,7 @@
 		}
 		ObjectAttribute blank;
 		PyObject *val;
-		char* data;
+		const char* data;
 
 		val = PyDict_GetItemString(tmp, "Name");
 		if (!val) {
@@ -454,10 +454,10 @@
 			PyErr_SetString(PyExc_TypeError, "attribute does not have 'Name' key.");
 			return nullptr;
 		}
-		data = PyString_AsString(val);
+		data = PyUnicode_AsUTF8(val);
 		if (!data)
 			return nullptr;
-		blank.name = QString(data);
+		blank.name = QString::fromUtf8(data);
 
 		val = PyDict_GetItemString(tmp, "Type");
 		if (!val) {
@@ -464,10 +464,10 @@
 			PyErr_SetString(PyExc_TypeError, "attribute does not have 'Type' key.");
 			return nullptr;
 		}
-		data = PyString_AsString(val);
+		data = PyUnicode_AsUTF8(val);
 		if (!data)
 			return nullptr;
-		blank.type = QString(data);
+		blank.type = QString::fromUtf8(data);
 
 		val = PyDict_GetItemString(tmp, "Value");
 		if (!val) {
@@ -474,10 +474,10 @@
 			PyErr_SetString(PyExc_TypeError, "attribute does not have 'Value' key.");
 			return nullptr;
 		}
-		data = PyString_AsString(val);
+		data = PyUnicode_AsUTF8(val);
 		if (!data)
 			return nullptr;
-		blank.value = QString(data);
+		blank.value = QString::fromUtf8(data);
 
 		val = PyDict_GetItemString(tmp, "Parameter");
 		if (!val) {
@@ -484,10 +484,10 @@
 			PyErr_SetString(PyExc_TypeError, "attribute does not have 'Parameter' key.");
 			return nullptr;
 		}
-		data = PyString_AsString(val);
+		data = PyUnicode_AsUTF8(val);
 		if (!data)
 			return nullptr;
-		blank.parameter = QString(data);
+		blank.parameter = QString::fromUtf8(data);
 
 		val = PyDict_GetItemString(tmp, "Relationship");
 		if (!val) {
@@ -494,10 +494,10 @@
 			PyErr_SetString(PyExc_TypeError, "attribute does not have 'Relationship' key.");
 			return nullptr;
 		}
-		data = PyString_AsString(val);
+		data = PyUnicode_AsUTF8(val);
 		if (!data)
 			return nullptr;
-		blank.relationship = QString(data);
+		blank.relationship = QString::fromUtf8(data);
 
 		val = PyDict_GetItemString(tmp, "RelationshipTo");
 		if (!val) {
@@ -504,10 +504,10 @@
 			PyErr_SetString(PyExc_TypeError, "attribute does not have 'RelationshipTo' key.");
 			return nullptr;
 		}
-		data = PyString_AsString(val);
+		data = PyUnicode_AsUTF8(val);
 		if (!data)
 			return nullptr;
-		blank.relationshipto = QString(data);
+		blank.relationshipto = QString::fromUtf8(data);
 
 		val = PyDict_GetItemString(tmp, "AutoAddTo");
 		if (!val) {
@@ -514,10 +514,10 @@
 			PyErr_SetString(PyExc_TypeError, "attribute does not have 'AutoAddTo' key.");
 			return nullptr;
 		}
-		data = PyString_AsString(val);
+		data = PyUnicode_AsUTF8(val);
 		if (!data)
 			return nullptr;
-		blank.autoaddto = QString(data);
+		blank.autoaddto = QString::fromUtf8(data);
 
 		attributes.append(blank);
 	}
Index: scribus/plugins/scriptplugin/cmdstyle.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdstyle.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/cmdstyle.cpp	(working copy)
@@ -344,31 +344,31 @@
 
 		val = PyDict_GetItemString(line, "Color");
 		if (val)
-			sl.Color = PyString_AsString(val);
+			sl.Color = PyUnicode_asQString(val);
 		else 
 			sl.Color = currentDoc->itemToolPrefs().lineColor;
 
 		val = PyDict_GetItemString(line, "Dash");
 		if (val)
-			sl.Dash = PyInt_AsLong(val);
+			sl.Dash = PyLong_AsLong(val);
 		else 
 			sl.Dash = Qt::SolidLine;
 
 		val = PyDict_GetItemString(line, "LineEnd");
 		if (val)
-			sl.LineEnd = PyInt_AsLong(val);
+			sl.LineEnd = PyLong_AsLong(val);
 		else 
 			sl.LineEnd = Qt::FlatCap;
 
 		val = PyDict_GetItemString(line, "LineJoin");
 		if (val)
-			sl.LineJoin = PyInt_AsLong(val);
+			sl.LineJoin = PyLong_AsLong(val);
 		else 
 			sl.LineJoin = Qt::MiterJoin;
 
 		val = PyDict_GetItemString(line, "Shade");
 		if (val)
-			sl.Shade = PyInt_AsLong(val);
+			sl.Shade = PyLong_AsLong(val);
 		else 
 			sl.Shade = currentDoc->itemToolPrefs().lineColorShade;
 
@@ -380,7 +380,7 @@
 
 		val = PyDict_GetItemString(line, "Shortcut");
 		if (val)
-			ml.shortcut = PyString_AsString(val);
+			ml.shortcut = PyUnicode_asQString(val);
 		else 
 			ml.shortcut = "";
 
Index: scribus/plugins/scriptplugin/cmdtable.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdtable.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/cmdtable.cpp	(working copy)
@@ -28,7 +28,7 @@
 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get table row count of non-table item.","python error").toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyInt_FromLong(static_cast<long>(table->rows()));
+	return PyLong_FromLong(static_cast<long>(table->rows()));
 }
 
 PyObject *scribus_gettablecolumns(PyObject* /* self */, PyObject* args)
@@ -48,7 +48,7 @@
 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get table column count of non-table item.","python error").toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyInt_FromLong(static_cast<long>(table->columns()));
+	return PyLong_FromLong(static_cast<long>(table->columns()));
 }
 
 PyObject *scribus_inserttablerows(PyObject* /* self */, PyObject* args)
@@ -338,7 +338,7 @@
 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get table style on a non-table item.","python error").toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyString_FromString(table->styleName().toUtf8());
+	return PyUnicode_FromString(table->styleName().toUtf8());
 }
 
 PyObject *scribus_settablestyle(PyObject* /* self */, PyObject* args)
@@ -378,7 +378,7 @@
 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get table fill color on a non-table item.","python error").toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyString_FromString(table->fillColor().toUtf8());
+	return PyUnicode_FromString(table->fillColor().toUtf8());
 }
 
 PyObject *scribus_settablefillcolor(PyObject* /* self */, PyObject* args)
Index: scribus/plugins/scriptplugin/cmdtext.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdtext.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/cmdtext.cpp	(working copy)
@@ -92,10 +92,10 @@
 	{
 		for (int i = 0; i < item->itemText.length(); i++)
 			if (item->itemText.selected(i))
-				return PyString_FromString(item->itemText.charStyle(i).font().scName().toUtf8());
+				return PyUnicode_FromString(item->itemText.charStyle(i).font().scName().toUtf8());
 		return nullptr;
 	}
-	return PyString_FromString(item->currentCharStyle().font().scName().toUtf8());
+	return PyUnicode_FromString(item->currentCharStyle().font().scName().toUtf8());
 }
 
 PyObject *scribus_gettextcolor(PyObject* /* self */, PyObject* args)
@@ -118,11 +118,11 @@
 		for (int i = 0; i < item->itemText.length(); ++i)
 		{
 			if (item->itemText.selected(i))
-				return PyString_FromString(item->itemText.charStyle(i).fillColor().toUtf8());
+				return PyUnicode_FromString(item->itemText.charStyle(i).fillColor().toUtf8());
 		}
         return nullptr;
 	}
-    return PyString_FromString(item->currentCharStyle().fillColor().toUtf8());
+    return PyUnicode_FromString(item->currentCharStyle().fillColor().toUtf8());
 }
 
 PyObject *scribus_gettextshade(PyObject* /* self */, PyObject* args)
@@ -145,11 +145,11 @@
 		for (int i = 0; i < item->itemText.length(); ++i)
 		{
 			if (item->itemText.selected(i))
-				return PyInt_FromLong(item->itemText.charStyle(i).fillShade());
+				return PyLong_FromLong(item->itemText.charStyle(i).fillShade());
 		}
 		return nullptr;
 	}
-	return PyInt_FromLong(item->currentCharStyle().fillShade());
+	return PyLong_FromLong(item->currentCharStyle().fillShade());
 }
 
 PyObject *scribus_gettextsize(PyObject* /* self */, PyObject* args)
@@ -167,7 +167,7 @@
 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get text size of non-text frame.","python error").toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyInt_FromLong(static_cast<long>(item->itemText.length()));
+	return PyLong_FromLong(static_cast<long>(item->itemText.length()));
 }
 
 PyObject *scribus_gettextlines(PyObject* /* self */, PyObject* args)
@@ -185,7 +185,7 @@
 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get number of lines of non-text frame.","python error").toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyInt_FromLong(static_cast<long>(item->textLayout.lines()));
+	return PyLong_FromLong(static_cast<long>(item->textLayout.lines()));
 }
 
 PyObject *scribus_gettextverticalalignment(PyObject* /* self */, PyObject* args)
@@ -203,7 +203,7 @@
 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get vertical alignment of non-text frame.", "python error").toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyInt_FromLong(static_cast<long>(item->verticalAlignment()));
+	return PyLong_FromLong(static_cast<long>(item->verticalAlignment()));
 }
 
 PyObject *scribus_getcolumns(PyObject* /* self */, PyObject* args)
@@ -221,7 +221,7 @@
 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get column count of non-text frame.","python error").toLocal8Bit().constData());
 		return nullptr;
 	}
-	return PyInt_FromLong(static_cast<long>(item->m_columns));
+	return PyLong_FromLong(static_cast<long>(item->m_columns));
 }
 
 PyObject *scribus_getcolumngap(PyObject* /* self */, PyObject* args)
@@ -261,10 +261,10 @@
 	{
 		for (int i = 0; i < item->itemText.length(); i++)
 			if (item->itemText.selected(i))
-				return PyString_FromString(item->itemText.charStyle(i).fontFeatures().toUtf8());
+				return PyUnicode_FromString(item->itemText.charStyle(i).fontFeatures().toUtf8());
 		return nullptr;
 	}
-	return PyString_FromString(item->currentCharStyle().fontFeatures().toUtf8());
+	return PyUnicode_FromString(item->currentCharStyle().fontFeatures().toUtf8());
 }
 
 PyObject *scribus_getlinespace(PyObject* /* self */, PyObject* args)
@@ -335,7 +335,7 @@
 			text += item->itemText.text(i);
 		}
 	}
-	return PyString_FromString(text.toUtf8());
+	return PyUnicode_FromString(text.toUtf8());
 }
 
 PyObject *scribus_gettext(PyObject* /* self */, PyObject* args)
@@ -368,7 +368,7 @@
 			text += item->itemText.text(i);
 		}
 	} // for
-	return PyString_FromString(text.toUtf8());
+	return PyUnicode_FromString(text.toUtf8());
 }
 
 PyObject *scribus_setboxtext(PyObject* /* self */, PyObject* args)
@@ -1235,17 +1235,17 @@
 	}
 	// no overrun
 	if (nolinks)
-		return PyInt_FromLong(maxchars - firstFrame);
+		return PyLong_FromLong(maxchars - firstFrame);
 
 	if (maxchars > chars)
-		return PyInt_FromLong(0);
+		return PyLong_FromLong(0);
 	// number of overrunning letters
-	return PyInt_FromLong(static_cast<long>(chars - maxchars));
+	return PyLong_FromLong(static_cast<long>(chars - maxchars));
 	 */
 	// refresh overflow information
 	item->invalidateLayout();
 	item->layout();
-	return PyInt_FromLong(static_cast<long>(item->frameOverflows()));
+	return PyLong_FromLong(static_cast<long>(item->frameOverflows()));
 }
 
 /*
Index: scribus/plugins/scriptplugin/cmdutil.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdutil.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/cmdutil.cpp	(working copy)
@@ -241,3 +241,11 @@
 	return border;
 }
 
+QString PyUnicode_asQString(PyObject* arg)
+{
+	const char* utf8Str = PyUnicode_AsUTF8(arg);
+	if (!utf8Str)
+		return QString();
+	return QString::fromUtf8(utf8Str);
+}
+
Index: scribus/plugins/scriptplugin/cmdutil.h
===================================================================
--- scribus/plugins/scriptplugin/cmdutil.h	(revision 23269)
+++ scribus/plugins/scriptplugin/cmdutil.h	(working copy)
@@ -29,6 +29,7 @@
 
 PageItem *GetItem(const QString& Name);
 void ReplaceColor(const QString& col, const QString& rep);
+
 /*!
  * @brief Returns named PageItem, or selection if name '', or exception and NULL if no item.
  *
@@ -60,6 +61,7 @@
  * @brief Returns a list of the names of all selected PageItems
  */
 QStringList getSelectedItemsByName();
+
 /*!
  * @brief Replaces the current selection by selecting all the items named in the passed QStringList
  *
@@ -68,8 +70,14 @@
  */
 bool setSelectedItemsByName(QStringList& itemNames);
 
-/// Helper method to parse a border from a list of tuples.
+/*!
+ * @brief Helper method to parse a border from a list of tuples.
+ */
 TableBorder parseBorder(PyObject* borderLines, bool* ok);
 
+/*!
+ * @brief Helper method to convert a PyUnicode object to a QString
+ */
+QString PyUnicode_asQString(PyObject* arg);
 
 #endif
Index: scribus/plugins/scriptplugin/cmdvar.h
===================================================================
--- scribus/plugins/scriptplugin/cmdvar.h	(revision 23269)
+++ scribus/plugins/scriptplugin/cmdvar.h	(working copy)
@@ -18,6 +18,11 @@
 	#undef _POSIX_C_SOURCE
 #endif
 
+#if defined(_MSC_VER)
+#pragma push_macro("slots")
+#undef slots
+#endif
+
 #if defined(HAVE_BOOST_PYTHON)
 #include <boost/python.hpp>
 #else
@@ -24,6 +29,10 @@
 #include <Python.h>
 #endif
 
+#if defined(_MSC_VER)
+#pragma pop_macro("slots")
+#endif
+
 #ifndef Py_RETURN_NONE
 	#define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
 #endif
@@ -52,6 +61,8 @@
 /** @brief Initialize the 'scribus' Python module in the currently active interpreter */
 extern "C" void initscribus(ScribusMainWindow *pl);
 
+extern "C" PyObject* PyInit_scribus(void);
+
 /* Exceptions */
 /*! Common scribus Exception */
 extern PyObject* ScribusException;
Index: scribus/plugins/scriptplugin/objimageexport.cpp
===================================================================
--- scribus/plugins/scriptplugin/objimageexport.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/objimageexport.cpp	(working copy)
@@ -34,7 +34,7 @@
 	Py_XDECREF(self->name);
 	Py_XDECREF(self->type);
 	Py_XDECREF(self->allTypes);
-	self->ob_type->tp_free((PyObject *)self);
+	Py_TYPE(self)->tp_free((PyObject *)self);
 }
 
 static PyObject * ImageExport_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
@@ -45,8 +45,8 @@
 	ImageExport *self;
 	self = (ImageExport *)type->tp_alloc(type, 0);
 	if (self != nullptr) {
-		self->name = PyString_FromString("ImageExport.png");
-		self->type = PyString_FromString("PNG");
+		self->name = PyUnicode_FromString("ImageExport.png");
+		self->type = PyUnicode_FromString("PNG");
 		self->allTypes = PyList_New(0);
 		self->dpi = 72;
 		self->scale = 100;
@@ -77,11 +77,11 @@
 
 static int ImageExport_setName(ImageExport *self, PyObject *value, void * /*closure*/)
 {
-	if (!PyString_Check(value)) {
+	if (!PyUnicode_Check(value)) {
 		PyErr_SetString(PyExc_TypeError, QObject::tr("The filename must be a string.", "python error").toLocal8Bit().constData());
 		return -1;
 	}
-	if (PyString_Size(value) < 1)
+	if (PyUnicode_GET_LENGTH(value) < 1)
 	{
 		PyErr_SetString(PyExc_TypeError, QObject::tr("The filename should not be empty string.", "python error").toLocal8Bit().constData());
 		return -1;
@@ -104,7 +104,7 @@
 		PyErr_SetString(PyExc_TypeError, QObject::tr("Cannot delete image type settings.", "python error").toLocal8Bit().constData());
 		return -1;
 	}
-	if (!PyString_Check(value)) {
+	if (!PyUnicode_Check(value)) {
 		PyErr_SetString(PyExc_TypeError, QObject::tr("The image type must be a string.", "python error").toLocal8Bit().constData());
 		return -1;
 	}
@@ -122,7 +122,7 @@
 	l = PyList_New(list.count());
 	for (QList<QByteArray>::Iterator it = list.begin(); it != list.end(); ++it)
 	{
-		PyList_SetItem(l, pos, PyString_FromString(QString((*it)).toLatin1().constData()));
+		PyList_SetItem(l, pos, PyUnicode_FromString(QString((*it)).toLatin1().constData()));
 		++pos;
 	}
 	return l;
@@ -160,7 +160,9 @@
 	int dpi = qRound(100.0 / 2.54 * self->dpi);
 	im.setDotsPerMeterY(dpi);
 	im.setDotsPerMeterX(dpi);
-	if (!im.save(PyString_AsString(self->name), PyString_AsString(self->type)))
+
+	QString imgFileName = PyUnicode_asQString(self->name);
+	if (!im.save(imgFileName, PyUnicode_AsUTF8(self->type)))
 	{
 		PyErr_SetString(ScribusException, QObject::tr("Failed to export image", "python error").toLocal8Bit().constData());
 		return nullptr;
@@ -194,7 +196,9 @@
 	int dpi = qRound(100.0 / 2.54 * self->dpi);
 	im.setDotsPerMeterY(dpi);
 	im.setDotsPerMeterX(dpi);
-	if (!im.save(value, PyString_AsString(self->type)))
+
+	QString outputFileName = QString::fromUtf8(value);
+	if (!im.save(outputFileName, PyUnicode_AsUTF8(self->type)))
 	{
 		PyErr_SetString(ScribusException, QObject::tr("Failed to export image", "python error").toLocal8Bit().constData());
 		return nullptr;
@@ -212,8 +216,7 @@
 };
 
 PyTypeObject ImageExport_Type = {
-	PyObject_HEAD_INIT(nullptr)   // PyObject_VAR_HEAD
-	0,
+	PyVarObject_HEAD_INIT(nullptr, 0)   // PyObject_VAR_HEAD
 	const_cast<char*>("scribus.ImageExport"), // char *tp_name; /* For printing, in format "<module>.<name>" */
 	sizeof(ImageExport),   // int tp_basicsize, /* For allocation */
 	0,  // int tp_itemsize; /* For allocation */
@@ -259,6 +262,8 @@
 	nullptr, //	 PyObject *tp_subclasses;
 	nullptr, //	 PyObject *tp_weaklist;
 	nullptr, //	 destructor tp_del;
+	0, //	 unsigned int tp_version_tag;
+	0, //	 destructor tp_finalize;
 
 #ifdef COUNT_ALLOCS
 	/* these must be last and never explicitly initialized */
Index: scribus/plugins/scriptplugin/objpdffile.cpp
===================================================================
--- scribus/plugins/scriptplugin/objpdffile.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/objpdffile.cpp	(working copy)
@@ -135,7 +135,7 @@
 	Py_XDECREF(self->info);
 	Py_XDECREF(self->rotateDeg);
 	Py_XDECREF(self->openAction);
-	self->ob_type->tp_free((PyObject *)self);
+	Py_TYPE(self)->tp_free((PyObject *)self);
 }
 
 static PyObject * PDFfile_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
@@ -150,13 +150,13 @@
 	self = (PDFfile *)type->tp_alloc(type, 0);
 	if (self) {
 // set file attribute
-		self->file = PyString_FromString("");
+		self->file = PyUnicode_FromString("");
 		if (!self->file) {
 			Py_DECREF(self);
 			return nullptr;
 		}
 // set font embedding mode attribute
-		self->fontEmbedding = PyInt_FromLong(0);
+		self->fontEmbedding = PyLong_FromLong(0);
 		if (!self->fontEmbedding) {
 			Py_DECREF(self);
 			return nullptr;
@@ -201,13 +201,13 @@
 // set quality attribute
 		self->quality = 0;
 // set resolution attribute
-		self->resolution = PyInt_FromLong(300);
+		self->resolution = PyLong_FromLong(300);
 		if (!self->resolution){
 			Py_DECREF(self);
 			return nullptr;
 		}
 // set downsample attribute
-		self->downsample = PyInt_FromLong(0);
+		self->downsample = PyLong_FromLong(0);
 		if (!self->downsample){
 			Py_DECREF(self);
 			return nullptr;
@@ -239,13 +239,13 @@
 			return nullptr;
 		}
 // set owner attribute
-		self->owner = PyString_FromString("");
+		self->owner = PyUnicode_FromString("");
 		if (!self->owner){
 			Py_DECREF(self);
 			return nullptr;
 		}
 // set user attribute
-		self->user = PyString_FromString("");
+		self->user = PyUnicode_FromString("");
 		if (!self->user){
 			Py_DECREF(self);
 			return nullptr;
@@ -269,22 +269,22 @@
 		self->intents = 0; // int - 0 - ?
 		self->intenti = 0; // int - 0 - ?
 		self->noembicc = 0; // bool
-		self->solidpr = PyString_FromString("");
+		self->solidpr = PyUnicode_FromString("");
 		if (!self->solidpr){
 			Py_DECREF(self);
 			return nullptr;
 		}
-		self->imagepr = PyString_FromString("");
+		self->imagepr = PyUnicode_FromString("");
 		if (!self->imagepr){
 			Py_DECREF(self);
 			return nullptr;
 		}
-		self->printprofc = PyString_FromString("");
+		self->printprofc = PyUnicode_FromString("");
 		if (!self->printprofc){
 			Py_DECREF(self);
 			return nullptr;
 		}
-		self->info = PyString_FromString("");
+		self->info = PyUnicode_FromString("");
 		if (!self->info){
 			Py_DECREF(self);
 			return nullptr;
@@ -299,7 +299,7 @@
 		self->mirrorH = 0;
 		self->mirrorV = 0;
 		self->doClip = 0;
-		self->rotateDeg = PyInt_FromLong(0);
+		self->rotateDeg = PyLong_FromLong(0);
 		if (!self->rotateDeg){
 			Py_DECREF(self);
 			return nullptr;
@@ -313,7 +313,7 @@
 		self->hideToolBar = 0;
 		self->hideMenuBar = 0;
 		self->fitWindow = 0;
-		self->openAction = PyString_FromString("");
+		self->openAction = PyUnicode_FromString("");
 		if (!self->openAction){
 			Py_DECREF(self);
 			return nullptr;
@@ -336,10 +336,10 @@
 	QString tf = pdfOptions.fileName;
 	if (tf.isEmpty()) {
 		QFileInfo fi = QFileInfo(currentDoc->documentFileName());
-		tf = fi.path()+"/"+fi.baseName()+".pdf";
+		tf = fi.path() + "/" + fi.baseName() + ".pdf";
 	}
 	PyObject *file = nullptr;
-	file = PyString_FromString(tf.toLatin1());
+	file = PyUnicode_FromString(tf.toUtf8());
 	if (file){
 		Py_DECREF(self->file);
 		self->file = file;
@@ -349,7 +349,7 @@
 	}
 // font embedding mode
 	PyObject *embeddingMode = nullptr;
-	embeddingMode = PyInt_FromLong(pdfOptions.FontEmbedding);
+	embeddingMode = PyLong_FromLong(pdfOptions.FontEmbedding);
 	if (embeddingMode){
 		Py_DECREF(self->fontEmbedding);
 		self->fontEmbedding = embeddingMode;
@@ -375,7 +375,7 @@
 	{
 		const QString& fontName = tmpEm.at(i);
 		PyObject *tmp= nullptr;
-		tmp = PyString_FromString(fontName.toLatin1());
+		tmp = PyUnicode_FromString(fontName.toUtf8());
 		if (tmp) {
 			PyList_Append(self->fonts, tmp);
 // do i need Py_DECREF(tmp) here?
@@ -401,7 +401,7 @@
 	for (int fe = 0; fe < pdfOptions.SubsetList.count(); ++fe)
 	{
 		PyObject *tmp= nullptr;
-		tmp = PyString_FromString(pdfOptions.SubsetList[fe].toLatin1().data());
+		tmp = PyUnicode_FromString(pdfOptions.SubsetList[fe].toUtf8().data());
 		if (tmp) {
 			PyList_Append(self->subsetList, tmp);
 			Py_DECREF(tmp);
@@ -425,7 +425,7 @@
 	}
 	for (i = 0; i<num; ++i) {
 		PyObject *tmp;
-		tmp = PyInt_FromLong((long)i+1L);
+		tmp = PyLong_FromLong((long)i+1L);
 		if (tmp)
 			PyList_SetItem(pages, i, tmp);
 		else {
@@ -458,7 +458,7 @@
 	self->quality = pdfOptions.Quality;
 // default resolution
 	PyObject *resolution = nullptr;
-	resolution = PyInt_FromLong(300);
+	resolution = PyLong_FromLong(300);
 	if (resolution){
 		Py_DECREF(self->resolution);
 		self->resolution = resolution;
@@ -469,7 +469,7 @@
 // do not downsample images
 	int down = pdfOptions.RecalcPic ? pdfOptions.PicRes : 0;
 	PyObject *downsample = nullptr;
-	downsample = PyInt_FromLong(down);
+	downsample = PyLong_FromLong(down);
 	if (downsample){
 		Py_DECREF(self->downsample);
 		self->downsample = downsample;
@@ -549,7 +549,7 @@
 	self->lpival = lpival;
 // set owner's password
 	PyObject *owner = nullptr;
-	owner = PyString_FromString(pdfOptions.PassOwner.toLatin1());
+	owner = PyUnicode_FromString(pdfOptions.PassOwner.toUtf8());
 	if (owner){
 		Py_DECREF(self->owner);
 		self->owner = owner;
@@ -559,7 +559,7 @@
 	}
 // set user'a password
 	PyObject *user = nullptr;
-	user = PyString_FromString(pdfOptions.PassUser.toLatin1());
+	user = PyUnicode_FromString(pdfOptions.PassUser.toUtf8());
 	if (user){
 		Py_DECREF(self->user);
 		self->user = user;
@@ -589,7 +589,7 @@
 	if (!ScCore->InputProfiles.contains(tp))
 		tp = currentDoc->cmsSettings().DefaultSolidColorRGBProfile;
 	PyObject *solidpr = nullptr;
-	solidpr = PyString_FromString(tp.toLatin1());
+	solidpr = PyUnicode_FromString(tp.toUtf8());
 	if (solidpr){
 		Py_DECREF(self->solidpr);
 		self->solidpr = solidpr;
@@ -601,7 +601,7 @@
 	if (!ScCore->InputProfiles.contains(tp2))
 		tp2 = currentDoc->cmsSettings().DefaultSolidColorRGBProfile;
 	PyObject *imagepr = nullptr;
-	imagepr = PyString_FromString(tp2.toLatin1());
+	imagepr = PyUnicode_FromString(tp2.toUtf8());
 	if (imagepr){
 		Py_DECREF(self->imagepr);
 		self->imagepr = imagepr;
@@ -613,7 +613,7 @@
 	if (!ScCore->PDFXProfiles.contains(tp3))
 		tp3 = currentDoc->cmsSettings().DefaultPrinterProfile;
 	PyObject *printprofc = nullptr;
-	printprofc = PyString_FromString(tp3.toLatin1());
+	printprofc = PyUnicode_FromString(tp3.toUtf8());
 	if (printprofc){
 		Py_DECREF(self->printprofc);
 		self->printprofc = printprofc;
@@ -623,7 +623,7 @@
 	}
 	QString tinfo = pdfOptions.Info;
 	PyObject *info = nullptr;
-	info = PyString_FromString(tinfo.toLatin1());
+	info = PyUnicode_FromString(tinfo.toUtf8());
 	if (info){
 		Py_DECREF(self->info);
 		self->info = info;
@@ -642,7 +642,7 @@
 	self->mirrorV = pdfOptions.MirrorV; // bool
 	self->doClip = pdfOptions.doClip; // bool
 	PyObject *rotateDeg = nullptr;
-	rotateDeg = PyInt_FromLong(0);
+	rotateDeg = PyLong_FromLong(0);
 	if (rotateDeg){
 		Py_DECREF(self->rotateDeg);
 		self->rotateDeg = rotateDeg;
@@ -661,7 +661,7 @@
 	self->fitWindow = pdfOptions.fitWindow; // bool
 
 	PyObject *openAction = nullptr;
-	openAction = PyString_FromString(pdfOptions.openAction.toLatin1().data());
+	openAction = PyUnicode_FromString(pdfOptions.openAction.toUtf8().data());
 	if (openAction){
 		Py_DECREF(self->openAction);
 		self->openAction = openAction;
@@ -751,7 +751,7 @@
 		PyErr_SetString(PyExc_TypeError, "Cannot delete 'file' attribute.");
 		return -1;
 	}
-	if (!PyString_Check(value)) {
+	if (!PyUnicode_Check(value)) {
 		PyErr_SetString(PyExc_TypeError, "The 'file' attribute value must be string.");
 		return -1;
 	}
@@ -773,11 +773,11 @@
 		PyErr_SetString(PyExc_TypeError, "Cannot delete 'fontEmbedding' attribute.");
 		return -1;
 	}
-	if (!PyInt_Check(value)) {
+	if (!PyLong_Check(value)) {
 		PyErr_SetString(PyExc_TypeError, "'fontEmbedding' attribute value must be integer.");
 		return -1;
 	}
-	int n = PyInt_AsLong(value);
+	int n = PyLong_AsLong(value);
 	if (n < 0 || n > 2) {
 		PyErr_SetString(PyExc_ValueError, "'fontEmbedding' value must be an integer between 0 and 2");
 		return -1;
@@ -807,7 +807,7 @@
 	int n;
 	n = PyList_Size(value);
 	for (int i=0; i<n; ++i)
-		if (!PyString_Check(PyList_GetItem(value, i))) {
+		if (!PyUnicode_Check(PyList_GetItem(value, i))) {
 			PyErr_SetString(PyExc_TypeError, "The 'fonts' list must contain only strings.");
 			return -1;
 		}
@@ -840,7 +840,7 @@
 	int n;
 	n = PyList_Size(value);
 	for (int i=0; i<n; ++i)
-		if (!PyString_Check(PyList_GetItem(value, i))) {
+		if (!PyUnicode_Check(PyList_GetItem(value, i))) {
 			PyErr_SetString(PyExc_TypeError, "The 'subsetList' list must contain only strings.");
 			return -1;
 		}
@@ -873,11 +873,11 @@
 		// I did not check if tmp is nullptr
 		// how can PyList_GetItem fail in this case (my guess: short of available memory?)
 		// Also do I need Py_INCREF or Py_DECREF here?
-		if (!PyInt_Check(tmp)){
+		if (!PyLong_Check(tmp)){
 			PyErr_SetString(PyExc_TypeError, "'pages' list must contain only integers.");
 			return -1;
 		}
-		if (PyInt_AsLong(tmp) > static_cast<int>(ScCore->primaryMainWindow()->doc->Pages->count()) || PyInt_AsLong(tmp) < 1) {
+		if (PyLong_AsLong(tmp) > static_cast<int>(ScCore->primaryMainWindow()->doc->Pages->count()) || PyLong_AsLong(tmp) < 1) {
 			PyErr_SetString(PyExc_ValueError, "'pages' value out of range.");
 			return -1;
 		}
@@ -901,11 +901,11 @@
 		PyErr_SetString(PyExc_TypeError, "Cannot delete 'resolution' attribute.");
 		return -1;
 	}
-	if (!PyInt_Check(value)) {
+	if (!PyLong_Check(value)) {
 		PyErr_SetString(PyExc_TypeError, "'resolution' attribute value must be integer.");
 		return -1;
 	}
-	int n = PyInt_AsLong(value);
+	int n = PyLong_AsLong(value);
 	if (n<35 || n>4000) {
 		PyErr_SetString(PyExc_ValueError, "'resolution' value must be in interval from 35 to 4000");
 		return -1;
@@ -928,12 +928,12 @@
 		PyErr_SetString(PyExc_TypeError, "Cannot delete 'downsample' attribute.");
 		return -1;
 	}
-	if (!PyInt_Check(value)) {
+	if (!PyLong_Check(value)) {
 		PyErr_SetString(PyExc_TypeError, "'downsample' attribute value must be integer.");
 		return -1;
 	}
-	int n = PyInt_AsLong(value);
-	if (n!=0 && (n<35 || n>PyInt_AsLong(self->resolution))) {
+	int n = PyLong_AsLong(value);
+	if (n!=0 && (n < 35 || n > PyLong_AsLong(self->resolution))) {
 		PyErr_SetString(PyExc_TypeError, "'downsample' value must be 0 or in interval from 35 to value of 'resolution'");
 		return -1;
 	}
@@ -972,7 +972,7 @@
 			return -1;
 		}
 		for ( --j; j > -1; --j) {
-			if (!PyInt_Check(PyList_GetItem(tmp, j))) {
+			if (!PyLong_Check(PyList_GetItem(tmp, j))) {
 				PyErr_SetString(PyExc_TypeError, "innermost element of 'effval' must be integers.");
 				return -1;
 			}
@@ -1005,21 +1005,21 @@
 	for (int i=0; i<n; ++i) {
 		PyObject *tmp = PyList_GetItem(value, i);
 		if (!PyList_Check(tmp)) {
-			PyErr_SetString(PyExc_TypeError, "elemets of 'lpival' must be list of five integers.");
+			PyErr_SetString(PyExc_TypeError, "elements of 'lpival' must be list of five integers.");
 			return -1;
 		}
 		int j = PyList_Size(tmp);
 		if (j != 4) {
-			PyErr_SetString(PyExc_TypeError, "elemets of 'lpival' must have exactly four members.");
+			PyErr_SetString(PyExc_TypeError, "elements of 'lpival' must have exactly four members.");
 			return -1;
 		}
 		for ( --j; j > 0; --j) {
-			if (!PyInt_Check(PyList_GetItem(tmp, j))) {
+			if (!PyLong_Check(PyList_GetItem(tmp, j))) {
 				PyErr_SetString(PyExc_TypeError, "'lpival'elements must have structure [siii]");
 				return -1;
 			}
 		}
-		if (!PyString_Check(PyList_GetItem(tmp, 0))) {
+		if (!PyUnicode_Check(PyList_GetItem(tmp, 0))) {
 			PyErr_SetString(PyExc_TypeError, "'lpival'elements must have structure [siii]");
 			return -1;
 		}
@@ -1042,7 +1042,7 @@
 		PyErr_SetString(PyExc_TypeError, "Cannot delete 'owner' attribute.");
 		return -1;
 	}
-	if (!PyString_Check(value)) {
+	if (!PyUnicode_Check(value)) {
 		PyErr_SetString(PyExc_TypeError, "'owner' attribute value must be string.");
 		return -1;
 	}
@@ -1064,7 +1064,7 @@
 		PyErr_SetString(PyExc_TypeError, "Cannot delete 'user' attribute.");
 		return -1;
 	}
-	if (!PyString_Check(value)) {
+	if (!PyUnicode_Check(value)) {
 		PyErr_SetString(PyExc_TypeError, "'user' attribute value must be string.");
 		return -1;
 	}
@@ -1086,7 +1086,7 @@
 		PyErr_SetString(PyExc_TypeError, "Cannot delete 'solidpr' attribute.");
 		return -1;
 	}
-	if (!PyString_Check(value)) {
+	if (!PyUnicode_Check(value)) {
 		PyErr_SetString(PyExc_TypeError, "The 'solidpr' attribute value must be string.");
 		return -1;
 	}
@@ -1108,7 +1108,7 @@
 		PyErr_SetString(PyExc_TypeError, "Cannot delete 'imagepr' attribute.");
 		return -1;
 	}
-	if (!PyString_Check(value)) {
+	if (!PyUnicode_Check(value)) {
 		PyErr_SetString(PyExc_TypeError, "The 'imagepr' attribute value must be string.");
 		return -1;
 	}
@@ -1130,7 +1130,7 @@
 		PyErr_SetString(PyExc_TypeError, "Cannot delete 'printprofc' attribute.");
 		return -1;
 	}
-	if (!PyString_Check(value)) {
+	if (!PyUnicode_Check(value)) {
 		PyErr_SetString(PyExc_TypeError, "The 'printprofc' attribute value must be string.");
 		return -1;
 	}
@@ -1152,7 +1152,7 @@
 		PyErr_SetString(PyExc_TypeError, "Cannot delete 'info' attribute.");
 		return -1;
 	}
-	if (!PyString_Check(value)) {
+	if (!PyUnicode_Check(value)) {
 		PyErr_SetString(PyExc_TypeError, "The 'info' attribute value must be string.");
 		return -1;
 	}
@@ -1174,11 +1174,11 @@
 		PyErr_SetString(PyExc_TypeError, "Cannot delete 'rotateDeg' attribute.");
 		return -1;
 	}
-	if (!PyInt_Check(value)) {
+	if (!PyLong_Check(value)) {
 		PyErr_SetString(PyExc_TypeError, "'rotateDeg' attribute value must be integer.");
 		return -1;
 	}
-	int n = PyInt_AsLong(value);
+	int n = PyLong_AsLong(value);
 	if (n!=0 && n!=90 && n!=180 && n!=270) {
 		PyErr_SetString(PyExc_TypeError, "'rotateDeg' value must be 0 or 90 or 180 or 270");
 		return -1;
@@ -1201,7 +1201,7 @@
 		PyErr_SetString(PyExc_TypeError, "Cannot delete 'openAction' attribute.");
 		return -1;
 	}
-	if (!PyString_Check(value)) {
+	if (!PyUnicode_Check(value)) {
 		PyErr_SetString(PyExc_TypeError, "'openAction' attribute value must be string.");
 		return -1;
 	}
@@ -1275,10 +1275,10 @@
 // apply fonts attribute
 	pdfOptions.EmbedList.clear();
 	int n = PyList_Size(self->fonts);
-	for ( int i=0; i<n; ++i)
+	for (int i = 0; i < n; ++i)
 	{
 		QString tmpFon;
-		tmpFon = QString(PyString_AsString(PyList_GetItem(self->fonts, i)));
+		tmpFon = PyUnicode_asQString(PyList_GetItem(self->fonts, i));
 		pdfOptions.EmbedList.append(tmpFon);
 	}
 // apply SubsetList attribute
@@ -1287,11 +1287,11 @@
 	for (int i = 0; i < n; ++i)
 	{
 		QString tmpFon;
-		tmpFon = QString(PyString_AsString(PyList_GetItem(self->subsetList, i)));
+		tmpFon = PyUnicode_asQString(PyList_GetItem(self->subsetList, i));
 		pdfOptions.SubsetList.append(tmpFon);
 	}
 // apply font embedding mode
-	pdfOptions.FontEmbedding = (PDFOptions::PDFFontEmbedding) PyInt_AsLong(self->fontEmbedding);
+	pdfOptions.FontEmbedding = (PDFOptions::PDFFontEmbedding) PyLong_AsLong(self->fontEmbedding);
 	if (pdfOptions.Version == PDFOptions::PDFVersion_X1a ||
 	    pdfOptions.Version == PDFOptions::PDFVersion_X3 ||
 	    pdfOptions.Version == PDFOptions::PDFVersion_X4)
@@ -1326,13 +1326,13 @@
 	}
 // apply file attribute
 	QString fn;
-	fn = QString(PyString_AsString(self->file));
+	fn = PyUnicode_asQString(self->file);
 	pdfOptions.fileName = fn;
 // apply pages attribute
 	std::vector<int> pageNs;
-	int nn=PyList_Size(self->pages);
+	int nn = PyList_Size(self->pages);
 	for (int i = 0; i < nn; ++i) {
-		pageNs.push_back((int)PyInt_AsLong(PyList_GetItem(self->pages, i)));
+		pageNs.push_back((int) PyLong_AsLong(PyList_GetItem(self->pages, i)));
 	}
 // apply thumbnails attribute
 	pdfOptions.Thumbnails = self->thumbnails;
@@ -1358,11 +1358,11 @@
 	self->quality = minmaxi(self->quality, 0, 4);
 	pdfOptions.Quality = self->quality;
 // apply resolusion attribute
-	pdfOptions.Resolution = PyInt_AsLong(self->resolution);
+	pdfOptions.Resolution = PyLong_AsLong(self->resolution);
 // apply downsample attribute
-	pdfOptions.RecalcPic = PyInt_AsLong(self->downsample);
+	pdfOptions.RecalcPic = PyLong_AsLong(self->downsample);
 	if (pdfOptions.RecalcPic)
-		pdfOptions.PicRes = PyInt_AsLong(self->downsample);
+		pdfOptions.PicRes = PyLong_AsLong(self->downsample);
 	else
 		pdfOptions.PicRes = pdfOptions.Resolution;
 // apply bookmarks attribute
@@ -1379,13 +1379,13 @@
 		PyObject *ti = PyList_GetItem(self->effval, i);
 		if (!ti)
 			continue;
-		// Do I Need to check if every PyInt_AsLong and PyList_GetItem funtion succeed???
-		t.pageEffectDuration = PyInt_AsLong(PyList_GetItem(ti, 0));
-		t.pageViewDuration = PyInt_AsLong(PyList_GetItem(ti, 1));
-		t.effectType = PyInt_AsLong(PyList_GetItem(ti, 2));
-		t.Dm = PyInt_AsLong(PyList_GetItem(ti, 3));
-		t.M = PyInt_AsLong(PyList_GetItem(ti, 4));
-		t.Di = PyInt_AsLong(PyList_GetItem(ti, 5));
+		// Do I Need to check if every PyLong_AsLong and PyList_GetItem funtion succeed???
+		t.pageEffectDuration = PyLong_AsLong(PyList_GetItem(ti, 0));
+		t.pageViewDuration = PyLong_AsLong(PyList_GetItem(ti, 1));
+		t.effectType = PyLong_AsLong(PyList_GetItem(ti, 2));
+		t.Dm = PyLong_AsLong(PyList_GetItem(ti, 3));
+		t.M = PyLong_AsLong(PyList_GetItem(ti, 4));
+		t.Di = PyLong_AsLong(PyList_GetItem(ti, 5));
 		//	PresentVals.append(t);
 	}
 
@@ -1404,11 +1404,10 @@
 //			return nullptr;
 //		}
 //		pdfOptions.LPISettings[QString(s)]=lpi;
-		QString st;
-		st = QString(PyString_AsString(PyList_GetItem(t,0)));
-		lpi.Frequency = PyInt_AsLong(PyList_GetItem(t, 1));
-		lpi.Angle = PyInt_AsLong(PyList_GetItem(t, 2));
-		lpi.SpotFunc = PyInt_AsLong(PyList_GetItem(t, 3));
+		QString st = PyUnicode_asQString(PyList_GetItem(t, 0));
+		lpi.Frequency = PyLong_AsLong(PyList_GetItem(t, 1));
+		lpi.Angle = PyLong_AsLong(PyList_GetItem(t, 2));
+		lpi.SpotFunc = PyLong_AsLong(PyList_GetItem(t, 3));
 		pdfOptions.LPISettings[st] = lpi;
 	}
 
@@ -1432,8 +1431,8 @@
 		if (self->allowAnnots)
 			Perm += 32;
 		pdfOptions.Permissions = Perm;
-		pdfOptions.PassOwner = QString(PyString_AsString(self->owner));
-		pdfOptions.PassUser = QString(PyString_AsString(self->user));
+		pdfOptions.PassOwner = PyUnicode_asQString(self->owner);
+		pdfOptions.PassUser = PyUnicode_asQString(self->user);
 	}
 	if (self->outdst == 0)
 	{
@@ -1453,9 +1452,9 @@
 			self->intenti = minmaxi(self->intenti, 0, 3);
 			pdfOptions.Intent2 = self->intenti;
 			pdfOptions.EmbeddedI = self->noembicc;
-			pdfOptions.SolidProf = PyString_AsString(self->solidpr);
-			pdfOptions.ImageProf = PyString_AsString(self->imagepr);
-			pdfOptions.PrintProf = PyString_AsString(self->printprofc);
+			pdfOptions.SolidProf = PyUnicode_asQString(self->solidpr);
+			pdfOptions.ImageProf = PyUnicode_asQString(self->imagepr);
+			pdfOptions.PrintProf = PyUnicode_asQString(self->printprofc);
 			if (pdfOptions.Version == PDFOptions::PDFVersion_X1a ||
 				pdfOptions.Version == PDFOptions::PDFVersion_X3 ||
 				pdfOptions.Version == PDFOptions::PDFVersion_X4)
@@ -1469,7 +1468,7 @@
 					Components = 4;
 				if (profile.colorSpace() == ColorSpace_Cmy)
 					Components = 3;
-				pdfOptions.Info = PyString_AsString(self->info);
+				pdfOptions.Info = PyUnicode_asQString(self->info);
 				pdfOptions.Encrypt = false;
 				pdfOptions.PresentMode = false;
 			}
@@ -1512,7 +1511,7 @@
 	pdfOptions.MirrorH = self->mirrorH;
 	pdfOptions.MirrorV = self->mirrorV;
 	pdfOptions.doClip = self->doClip;
-	pdfOptions.RotateDeg = PyInt_AsLong(self->rotateDeg);
+	pdfOptions.RotateDeg = PyLong_AsLong(self->rotateDeg);
 	pdfOptions.isGrayscale = self->isGrayscale;
 	pdfOptions.PageLayout = minmaxi(self->pageLayout, 0, 3);
 	pdfOptions.displayBookmarks = self->displayBookmarks;
@@ -1522,7 +1521,7 @@
 	pdfOptions.hideToolBar = self->hideToolBar;
 	pdfOptions.hideMenuBar = self->hideMenuBar;
 	pdfOptions.fitWindow = self->fitWindow;
-	pdfOptions.openAction = QString(PyString_AsString(self->openAction));
+	pdfOptions.openAction = PyUnicode_asQString(self->openAction);
 	pdfOptions.firstUse = false;
 
 	QString errorMessage;
@@ -1548,8 +1547,7 @@
 };
 
 PyTypeObject PDFfile_Type = {
-	PyObject_HEAD_INIT(nullptr) // PyObject_VAR_HEAD
-	0,		      //
+	PyVarObject_HEAD_INIT(nullptr, 0) // PyObject_VAR_HEAD	      //
 	const_cast<char*>("scribus.PDFfile"), // char *tp_name; /* For printing, in format "<module>.<name>" */
 	sizeof(PDFfile),     // int tp_basicsize, /* For allocation */
 	0,		    // int tp_itemsize; /* For allocation */
@@ -1624,6 +1622,8 @@
 	nullptr, //     PyObject *tp_subclasses;
 	nullptr, //     PyObject *tp_weaklist;
 	nullptr, //     destructor tp_del;
+	0, //	 unsigned int tp_version_tag;
+	0, //	 destructor tp_finalize;
 
 #ifdef COUNT_ALLOCS
 	/* these must be last and never explicitly initialized */
Index: scribus/plugins/scriptplugin/objprinter.cpp
===================================================================
--- scribus/plugins/scriptplugin/objprinter.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/objprinter.cpp	(working copy)
@@ -59,7 +59,7 @@
 	Py_XDECREF(self->cmd);
 	Py_XDECREF(self->pages);
 	Py_XDECREF(self->separation);
-	self->ob_type->tp_free((PyObject *)self);
+	Py_TYPE(self)->tp_free((PyObject *)self);
 }
 
 static PyObject * Printer_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
@@ -78,19 +78,19 @@
 			return nullptr;
 		}
 // set printer attribute
-		self->printer = PyString_FromString("");
+		self->printer = PyUnicode_FromString("");
 		if (self->printer == nullptr){
 			Py_DECREF(self);
 			return nullptr;
 		}
 // set file attribute
-		self->file = PyString_FromString("");
+		self->file = PyUnicode_FromString("");
 		if (self->file == nullptr){
 			Py_DECREF(self);
 			return nullptr;
 		}
 // set cmd attribute
-		self->cmd = PyString_FromString("");
+		self->cmd = PyUnicode_FromString("");
 		if (self->cmd == nullptr){
 			Py_DECREF(self);
 			return nullptr;
@@ -102,7 +102,7 @@
 			return nullptr;
 		}
 // set separation attribute
-		self->separation = PyString_FromString("No");
+		self->separation = PyUnicode_FromString("No");
 		if (self->separation == nullptr){
 			Py_DECREF(self);
 			return nullptr;
@@ -143,18 +143,18 @@
 		QString prn = printers[i];
 		if (prn.isEmpty())
 			continue;
-		PyObject *tmppr = PyString_FromString(prn.toLocal8Bit().constData());
+		PyObject *tmppr = PyUnicode_FromString(prn.toUtf8().constData());
 		if (tmppr){
 			PyList_Append(self->allPrinters, tmppr);
 			Py_DECREF(tmppr);
 		}
 	}
-	PyObject *tmp2 = PyString_FromString("File");
+	PyObject *tmp2 = PyUnicode_FromString("File");
 	PyList_Append(self->allPrinters, tmp2);
 	Py_DECREF(tmp2);
 // as defaut set to print into file
 	PyObject *printer = nullptr;
-	printer = PyString_FromString("File");
+	printer = PyUnicode_FromString("File");
 	if (printer){
 		Py_DECREF(self->printer);
 		self->printer = printer;
@@ -166,7 +166,7 @@
 		tf = fi.path()+"/"+fi.baseName()+".pdf";
 	}
 	PyObject *file = nullptr;
-	file = PyString_FromString(tf.toLatin1());
+	file = PyUnicode_FromString(tf.toUtf8());
 	if (file){
 		Py_DECREF(self->file);
 		self->file = file;
@@ -176,7 +176,7 @@
 	}
 // alternative printer commands default to ""
 	PyObject *cmd = nullptr;
-	cmd = PyString_FromString("");
+	cmd = PyUnicode_FromString("");
 	if (cmd){
 		Py_DECREF(self->cmd);
 		self->cmd = cmd;
@@ -192,13 +192,13 @@
 	}
 	for (int i = 0; i<num; i++) {
 		PyObject *tmp=nullptr;
-		tmp = PyInt_FromLong((long)i+1L); // instead of 1 put here first page number
+		tmp = PyLong_FromLong((long)i+1L); // instead of 1 put here first page number
 		if (tmp)
 			PyList_SetItem(self->pages, i, tmp);
 	}
 // do not print separation
 	PyObject *separation = nullptr;
-	separation = PyString_FromString("No");
+	separation = PyUnicode_FromString("No");
 	if (separation){
 		Py_DECREF(self->separation);
 		self->separation = separation;
@@ -257,7 +257,7 @@
 		PyErr_SetString(PyExc_TypeError, "Cannot delete 'printer' attribute.");
 		return -1;
 	}
-	if (!PyString_Check(value)) {
+	if (!PyUnicode_Check(value)) {
 		PyErr_SetString(PyExc_TypeError, "The 'printer' attribute value must be string.");
 		return -1;
 	}
@@ -288,7 +288,7 @@
 		PyErr_SetString(PyExc_TypeError, "Cannot delete 'file' attribute.");
 		return -1;
 	}
-	if (!PyString_Check(value)) {
+	if (!PyUnicode_Check(value)) {
 		PyErr_SetString(PyExc_TypeError, "The 'file' attribute value must be string.");
 		return -1;
 	}
@@ -310,7 +310,7 @@
 		PyErr_SetString(PyExc_TypeError, "Cannot delete 'cmd' attribute.");
 		return -1;
 	}
-	if (!PyString_Check(value)) {
+	if (!PyUnicode_Check(value)) {
 		PyErr_SetString(PyExc_TypeError, "The 'cmd' attribute value must be string.");
 		return -1;
 	}
@@ -339,11 +339,11 @@
 	int len = PyList_Size(value);
 	for (int i = 0; i<len; i++){
 		PyObject *tmp = PyList_GetItem(value, i);
-		if (!PyInt_Check(tmp)){
+		if (!PyLong_Check(tmp)){
 			PyErr_SetString(PyExc_TypeError, "'pages' attribute must be list containing only integers.");
 			return -1;
 		}
-		if (PyInt_AsLong(tmp) > static_cast<int>(ScCore->primaryMainWindow()->doc->Pages->count()) || PyInt_AsLong(tmp) < 1) {
+		if (PyLong_AsLong(tmp) > static_cast<int>(ScCore->primaryMainWindow()->doc->Pages->count()) || PyLong_AsLong(tmp) < 1) {
 			PyErr_SetString(PyExc_ValueError, "'pages' value out of range.");
 			return -1;
 		}
@@ -366,7 +366,7 @@
 		PyErr_SetString(PyExc_TypeError, "Cannot delete 'separation' attribute.");
 		return -1;
 	}
-	if (!PyString_Check(value)) {
+	if (!PyUnicode_Check(value)) {
 		PyErr_SetString(PyExc_TypeError, "The 'separation' attribute value must be string.");
 		return -1;
 	}
@@ -400,16 +400,16 @@
 	PSfile = false;
 
 //    ReOrderText(ScCore->primaryMainWindow()->doc, ScCore->primaryMainWindow()->view);
-	prn = QString(PyString_AsString(self->printer));
-	fna = QString(PyString_AsString(self->file));
-	fil = QString(PyString_AsString(self->printer)) == QString("File");
+	prn = PyUnicode_asQString(self->printer);
+	fna = PyUnicode_asQString(self->file);
+	fil = PyUnicode_asQString(self->printer) == QString("File");
 	std::vector<int> pageNs;
 	PrintOptions options;
 	for (int i = 0; i < PyList_Size(self->pages); ++i) {
-		options.pageNumbers.push_back((int)PyInt_AsLong(PyList_GetItem(self->pages, i)));
+		options.pageNumbers.push_back((int) PyLong_AsLong(PyList_GetItem(self->pages, i)));
 	}
 	int copyCount = (self->copies < 1) ? 1 : self->copies;
-	SepName = QString(PyString_AsString(self->separation));
+	SepName = PyUnicode_asQString(self->separation);
 	options.printer   = prn;
 	options.prnEngine = (PrintEngine) self->pslevel;
 	options.toFile    = fil;
@@ -427,7 +427,7 @@
 	options.bleeds.set(0, 0, 0, 0);
 	if (!PrinterUtil::checkPrintEngineSupport(options.printer, options.prnEngine, options.toFile))
 		options.prnEngine = PrinterUtil::getDefaultPrintEngine(options.printer, options.toFile);
-	printcomm = QString(PyString_AsString(self->cmd));
+	printcomm = PyUnicode_asQString(self->cmd);
 	QMap<QString, QMap<uint, FPointArray> > ReallyUsed;
 	ReallyUsed.clear();
 	ScCore->primaryMainWindow()->doc->getUsedFonts(ReallyUsed);
@@ -509,8 +509,7 @@
 };
 
 PyTypeObject Printer_Type = {
-	PyObject_HEAD_INIT(nullptr)   // PyObject_VAR_HEAD
-	0,			 //
+	PyVarObject_HEAD_INIT(nullptr, 0)   // PyObject_VAR_HEAD	 //
 	const_cast<char*>("scribus.Printer"), // char *tp_name; /* For printing, in format "<module>.<name>" */
 	sizeof(Printer),   // int tp_basicsize, /* For allocation */
 	0,		       // int tp_itemsize; /* For allocation */
@@ -585,6 +584,8 @@
 	nullptr, //     PyObject *tp_subclasses;
 	nullptr, //     PyObject *tp_weaklist;
 	nullptr, //     destructor tp_del;
+	0, //	 unsigned int tp_version_tag;
+	0, //	 destructor tp_finalize;
 
 #ifdef COUNT_ALLOCS
 	/* these must be last and never explicitly initialized */
Index: scribus/plugins/scriptplugin/samples/3columnA4.py
===================================================================
--- scribus/plugins/scriptplugin/samples/3columnA4.py	(revision 23269)
+++ scribus/plugins/scriptplugin/samples/3columnA4.py	(working copy)
@@ -8,9 +8,9 @@
     # Do so _after_ the 'import scribus' and only import the names you need, such
     # as commonly used constants.
     import scribus
-except ImportError,err:
-    print "This Python script is written for the Scribus scripting interface."
-    print "It can only be run from within Scribus."
+except ImportError as err:
+    print ("This Python script is written for the Scribus scripting interface.")
+    print ("It can only be run from within Scribus.")
     sys.exit(1)
 
 def main(argv):
@@ -26,7 +26,7 @@
 try:
     from scribus import *
 except ImportError:
-    print "This script only runs from within Scribus."
+    print ("This script only runs from within Scribus.")
     sys.exit(1)
 
 margins = (50, 50, 50, 50)
Index: scribus/plugins/scriptplugin/samples/3columnUSLTR.py
===================================================================
--- scribus/plugins/scriptplugin/samples/3columnUSLTR.py	(revision 23269)
+++ scribus/plugins/scriptplugin/samples/3columnUSLTR.py	(working copy)
@@ -8,9 +8,9 @@
     # Do so _after_ the 'import scribus' and only import the names you need, such
     # as commonly used constants.
     import scribus
-except ImportError,err:
-    print "This Python script is written for the Scribus scripting interface."
-    print "It can only be run from within Scribus."
+except ImportErroras err:
+    print ("This Python script is written for the Scribus scripting interface.")
+    print ("It can only be run from within Scribus.")
     sys.exit(1)
 
 def main(argv):
@@ -24,7 +24,7 @@
 try:
     from scribus import *
 except ImportError:
-    print "This script only runs from within Scribus."
+    print ("This script only runs from within Scribus.")
     sys.exit(1)
 
 margins = (50, 50, 50, 50)
Index: scribus/plugins/scriptplugin/samples/boilerplate.py
===================================================================
--- scribus/plugins/scriptplugin/samples/boilerplate.py	(revision 23269)
+++ scribus/plugins/scriptplugin/samples/boilerplate.py	(working copy)
@@ -8,9 +8,9 @@
     # Do so _after_ the 'import scribus' and only import the names you need, such
     # as commonly used constants.
     import scribus
-except ImportError,err:
-    print "This Python script is written for the Scribus scripting interface."
-    print "It can only be run from within Scribus."
+except ImportError as err:
+    print ("This Python script is written for the Scribus scripting interface.")
+    print ("It can only be run from within Scribus.")
     sys.exit(1)
 
 #########################
Index: scribus/plugins/scriptplugin/samples/Calender.py
===================================================================
--- scribus/plugins/scriptplugin/samples/Calender.py	(revision 23269)
+++ scribus/plugins/scriptplugin/samples/Calender.py	(working copy)
@@ -8,7 +8,7 @@
 try:
     from scribus import *
 except ImportError:
-    print "This script only runs from within Scribus."
+    print ("This script only runs from within Scribus.")
     sys.exit(1)
 
 import calendar
Index: scribus/plugins/scriptplugin/samples/ExtractText.py
===================================================================
--- scribus/plugins/scriptplugin/samples/ExtractText.py	(revision 23269)
+++ scribus/plugins/scriptplugin/samples/ExtractText.py	(working copy)
@@ -73,7 +73,7 @@
         if textfile == '':
             raise Exception
         exportText(textfile)
-    except Exception, e:
+    except Exception as e:
         print e
 
 else:
Index: scribus/plugins/scriptplugin/samples/golden-mean.py
===================================================================
--- scribus/plugins/scriptplugin/samples/golden-mean.py	(revision 23269)
+++ scribus/plugins/scriptplugin/samples/golden-mean.py	(working copy)
@@ -44,7 +44,7 @@
 try:
     from scribus import *
 except ImportError:
-    print "This script only runs from within Scribus."
+    print ("This script only runs from within Scribus.")
     sys.exit(1)
 
 from math import sqrt
Index: scribus/plugins/scriptplugin/samples/legende.py
===================================================================
--- scribus/plugins/scriptplugin/samples/legende.py	(revision 23269)
+++ scribus/plugins/scriptplugin/samples/legende.py	(working copy)
@@ -9,7 +9,7 @@
 try:
     from scribus import *
 except ImportError:
-    print "This script only runs from within Scribus."
+    print ("This script only runs from within Scribus.")
     sys.exit(1)
 
 import os
Index: scribus/plugins/scriptplugin/samples/moins_10_pourcent_group.py
===================================================================
--- scribus/plugins/scriptplugin/samples/moins_10_pourcent_group.py	(revision 23269)
+++ scribus/plugins/scriptplugin/samples/moins_10_pourcent_group.py	(working copy)
@@ -8,7 +8,7 @@
 try:
     from scribus import *
 except ImportError:
-    print "This script only runs from within Scribus."
+    print ("This script only runs from within Scribus.")
     sys.exit(1)
 
 if haveDoc() and selectionCount():
Index: scribus/plugins/scriptplugin/samples/plus_10_pourcent_group.py
===================================================================
--- scribus/plugins/scriptplugin/samples/plus_10_pourcent_group.py	(revision 23269)
+++ scribus/plugins/scriptplugin/samples/plus_10_pourcent_group.py	(working copy)
@@ -8,7 +8,7 @@
 try:
     from scribus import *
 except ImportError:
-    print "This script only runs from within Scribus."
+    print ("This script only runs from within Scribus.")
     sys.exit(1)
 
 if haveDoc() and selectionCount():
Index: scribus/plugins/scriptplugin/samples/pochette_cd.py
===================================================================
--- scribus/plugins/scriptplugin/samples/pochette_cd.py	(revision 23269)
+++ scribus/plugins/scriptplugin/samples/pochette_cd.py	(working copy)
@@ -8,7 +8,7 @@
 try:
     from scribus import *
 except ImportError:
-    print "This script only runs from within Scribus."
+    print ("This script only runs from within Scribus.")
     sys.exit(1)
 
 margins = (0, 0, 0, 0)
Index: scribus/plugins/scriptplugin/samples/quote.py
===================================================================
--- scribus/plugins/scriptplugin/samples/quote.py	(revision 23269)
+++ scribus/plugins/scriptplugin/samples/quote.py	(working copy)
@@ -8,7 +8,7 @@
 try:
     from scribus import *
 except ImportError:
-    print "This script only runs from within Scribus."
+    print ("This script only runs from within Scribus.")
     sys.exit(1)
 
 import re
Index: scribus/plugins/scriptplugin/samples/Sample1.py
===================================================================
--- scribus/plugins/scriptplugin/samples/Sample1.py	(revision 23269)
+++ scribus/plugins/scriptplugin/samples/Sample1.py	(working copy)
@@ -8,7 +8,7 @@
 try:
     from scribus import *
 except ImportError:
-    print "This script only runs from within Scribus."
+    print ("This script only runs from within Scribus.")
     sys.exit(1)
 
 margins = (10, 10, 10, 30)
Index: scribus/plugins/scriptplugin/samples/sample_db_usage.py
===================================================================
--- scribus/plugins/scriptplugin/samples/sample_db_usage.py	(revision 23269)
+++ scribus/plugins/scriptplugin/samples/sample_db_usage.py	(working copy)
@@ -47,13 +47,13 @@
 try:
     import scribus
 except ImportError:
-    print "This script only runs from within Scribus."
+    print ("This script only runs from within Scribus.")
     sys.exit(1)
 
 try:
     import MySQLdb
 except ImportError:
-    print "You must have 'MySQLdb' installed."
+    print ("You must have 'MySQLdb' installed.")
     sys.exit(1)
 
 
Index: scribus/plugins/scriptplugin/samples/trait_de_coupe.py
===================================================================
--- scribus/plugins/scriptplugin/samples/trait_de_coupe.py	(revision 23269)
+++ scribus/plugins/scriptplugin/samples/trait_de_coupe.py	(working copy)
@@ -8,7 +8,7 @@
 try:
     from scribus import *
 except ImportError:
-    print "This script only runs from within Scribus."
+    print ("This script only runs from within Scribus.")
     sys.exit(1)
 
 def main():
Index: scribus/plugins/scriptplugin/samples/wordcount.py
===================================================================
--- scribus/plugins/scriptplugin/samples/wordcount.py	(revision 23269)
+++ scribus/plugins/scriptplugin/samples/wordcount.py	(working copy)
@@ -8,7 +8,7 @@
 try:
     from scribus import *
 except ImportError:
-    print "This script only runs from within Scribus."
+    print ("This script only runs from within Scribus.")
     sys.exit(1)
 
 import re
Index: scribus/plugins/scriptplugin/scriptercore.cpp
===================================================================
--- scribus/plugins/scriptplugin/scriptercore.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/scriptercore.cpp	(working copy)
@@ -17,6 +17,7 @@
 #include <QPixmap>
 #include <cstdlib>
 
+#include "cmdutil.h"
 #include "runscriptdialog.h"
 #include "ui/helpbrowser.h"
 #include "ui/marksmanager.h"
@@ -256,7 +257,7 @@
 		global_state = PyThreadState_Get();
 		state = Py_NewInterpreter();
 		// Init the scripter module in the sub-interpreter
-		initscribus(ScCore->primaryMainWindow());
+		//initscribus(ScCore->primaryMainWindow());
 	}
 
 	// Make sure sys.argv[0] is the path to the script
@@ -263,13 +264,13 @@
 	arguments.prepend(na.data());
 	//convert arguments (QListString) to char** for Python bridge
 	/* typically arguments == ['path/to/script.py','--argument1','valueforarg1','--flag']*/
-	char **comm = new char*[arguments.size()];
+	wchar_t **comm = new wchar_t*[arguments.size()];
 	for (int i = 0; i < arguments.size(); i++)
 	{
-		QByteArray localStr = arguments.at(i).toLocal8Bit();
-		comm[i] = new char[localStr.size() + 1]; //+1 to allow adding '\0'. may be useless, don't know how to check.
-		comm[i][localStr.size()] = 0;
-		strncpy(comm[i], localStr.data(), localStr.size());
+		const QString& argStr = arguments.at(i);
+		comm[i] = new wchar_t[argStr.size() + 1]; //+1 to allow adding '\0'. may be useless, don't know how to check.
+		comm[i][argStr.size()] = 0;
+		argStr.toWCharArray(comm[i]);
 	}
 	PySys_SetArgv(arguments.size(), comm);
 
@@ -291,7 +292,7 @@
 		// Build the Python code to run the script
 		//QString cm = QString("from __future__ import division\n"); removed due #5252 PV
 		QString cm = QString("import sys\n");
-		cm        += QString("import cStringIO\n");
+		cm        += QString("import io\n");
 		/* Implementation of the help() in pydoc.py reads some OS variables
 		 * for output settings. I use ugly hack to stop freezing calling help()
 		 * in script. pv. */
@@ -299,7 +300,7 @@
 		cm        += QString("sys.path[0] = \"%1\"\n").arg(escapedAbsPath);
 		// Replace sys.stdin with a dummy StringIO that always returns
 		// "" for read
-		cm        += QString("sys.stdin = cStringIO.StringIO()\n");
+		cm        += QString("sys.stdin = io.StringIO()\n");
 		// tell the script if it's running in the main intepreter or a subinterpreter
 		cm        += QString("import scribus\n");
 		if (inMainInterpreter)
@@ -307,7 +308,7 @@
 		else
 			cm+= QString("scribus.mainInterpreter = False\n");
 		cm        += QString("try:\n");
-		cm        += QString("    execfile(\"%1\")\n").arg(escapedFileName);
+		cm        += QString("    exec(open(\"%1\", \"rb\").read())\n").arg(escapedFileName);
 		cm        += QString("except SystemExit:\n");
 		cm        += QString("    pass\n");
 		// Capture the text of any other exception that's raised by the interpreter
@@ -341,7 +342,7 @@
 			}
 			else if (ScCore->usingGUI())
 			{
-				QString errorMsg = PyString_AsString(errorMsgPyStr);
+				QString errorMsg = PyUnicode_asQString(errorMsgPyStr);
 				// Display a dialog to the user with the exception
 				QClipboard *cp = QApplication::clipboard();
 				cp->setText(errorMsg);
@@ -399,7 +400,7 @@
 	cm = "# -*- coding: utf8 -*- \n";
 	if (PyThreadState_Get() != nullptr)
 	{
-		initscribus(ScCore->primaryMainWindow());
+		//initscribus(ScCore->primaryMainWindow());
 		/* HACK: following loop handles all input line by line.
 		It *should* use I.C. because of docstrings etc. I.I. cannot
 		handle docstrings right.
@@ -408,8 +409,8 @@
 		works fine in plain Python. Not here. WTF? */
 		cm += (
 				"try:\n"
-				"    import cStringIO\n"
-				"    scribus._bu = cStringIO.StringIO()\n"
+				"    import io\n"
+				"    scribus._bu = io.StringIO()\n"
 				"    sys.stdout = scribus._bu\n"
 				"    sys.stderr = scribus._bu\n"
 				"    sys.argv = ['scribus']\n" // this is the PySys_SetArgv replacement
@@ -420,9 +421,9 @@
 				"    sys.stdout = sys.__stdout__\n"
 				"    sys.stderr = sys.__stderr__\n"
 				"except SystemExit:\n"
-				"    print 'Catched SystemExit - it is not good for Scribus'\n"
+				"    print ('Catched SystemExit - it is not good for Scribus')\n"
 				"except KeyboardInterrupt:\n"
-				"    print 'Catched KeyboardInterrupt - it is not good for Scribus'\n"
+				"    print ('Catched KeyboardInterrupt - it is not good for Scribus')\n"
 			  );
 	}
 	// Set up sys.argv
@@ -599,8 +600,8 @@
 		"import sys\n"
 		"import code\n"
 		"sys.path.insert(0, \"%1\")\n"
-		"import cStringIO\n"
-		"sys.stdin = cStringIO.StringIO()\n"
+		"import io\n"
+		"sys.stdin = io.StringIO()\n"
 		"scribus._ia = code.InteractiveConsole(globals())\n"
 		).arg(ScPaths::instance().scriptDir());
 	if (m_importAllNames)
Index: scribus/plugins/scriptplugin/scriptplugin.cpp
===================================================================
--- scribus/plugins/scriptplugin/scriptplugin.cpp	(revision 23269)
+++ scribus/plugins/scriptplugin/scriptplugin.cpp	(working copy)
@@ -166,20 +166,20 @@
 	if (QDir(pyHome).exists())
 	{
 		QString ph = QDir::toNativeSeparators(pyHome);
-		pythonHome = ph.toLocal8Bit();
-		Py_SetPythonHome(pythonHome.data());
+		pythonHome.resize(2 * ph.length() + 2);
+		memcpy(pythonHome.data(), ph.utf16(), 2 * ph.length() + 2);
+		Py_SetPythonHome((const wchar_t*) pythonHome.constData());
 	}
 #endif
-	Py_Initialize();
-	if (PyUnicode_SetDefaultEncoding("utf-8"))
-	{
-		qDebug("Failed to set default encoding to utf-8.\n");
-		PyErr_Clear();
-	}
 
 	scripterCore = new ScripterCore(ScCore->primaryMainWindow());
 	Q_CHECK_PTR(scripterCore);
-	initscribus(ScCore->primaryMainWindow());
+
+	PyImport_AppendInittab("scribus", &PyInit_scribus);
+	Py_Initialize();
+
+	//initscribus(ScCore->primaryMainWindow());
+	
 #ifdef HAVE_SCRIPTER2
 	scripter2_init();
 #endif
@@ -228,7 +228,7 @@
 /*static */PyObject *scribus_retval(PyObject* /*self*/, PyObject* args)
 {
 	char *Name = nullptr;
-	if (!PyArg_ParseTuple(args, (char*)"s", &Name))
+	if (!PyArg_ParseTuple(args, (char*) "s", &Name))
 		return nullptr;
 	// Because sysdefaultencoding is not utf-8, Python is returning utf-8 encoded
 	// 8-bit char* strings. Make sure Qt understands that the input is utf-8 not
@@ -236,12 +236,12 @@
 	/*RetString = QString::fromUtf8(Name);
 	RetVal = retV;*/
 	scripterCore->returnString = QString::fromUtf8(Name);
-	return PyInt_FromLong(0L);
+	return PyLong_FromLong(0L);
 }
 
 /*static */PyObject *scribus_getval(PyObject* /*self*/)
 {
-	return PyString_FromString(scripterCore->inValue.toUtf8().data());
+	return PyUnicode_FromString(scripterCore->inValue.toUtf8().data());
 }
 
 /*! \brief Translate a docstring. Small helper function for use with the
@@ -307,8 +307,8 @@
 	{const_cast<char*>("createRect"), scribus_newrect, METH_VARARGS, tr(scribus_newrect__doc__)},
 	{const_cast<char*>("createText"), scribus_newtext, METH_VARARGS, tr(scribus_newtext__doc__)},
 	{const_cast<char*>("createTable"), scribus_newtable, METH_VARARGS, tr(scribus_newtable__doc__)},
-	{const_cast<char*>("createParagraphStyle"), (PyCFunction)scribus_createparagraphstyle, METH_KEYWORDS, tr(scribus_createparagraphstyle__doc__)},
-	{const_cast<char*>("createCharStyle"), (PyCFunction)scribus_createcharstyle, METH_KEYWORDS, tr(scribus_createcharstyle__doc__)},
+	{const_cast<char*>("createParagraphStyle"), (PyCFunction)scribus_createparagraphstyle, METH_VARARGS|METH_KEYWORDS, tr(scribus_createparagraphstyle__doc__)},
+	{const_cast<char*>("createCharStyle"), (PyCFunction)scribus_createcharstyle, METH_VARARGS|METH_KEYWORDS, tr(scribus_createcharstyle__doc__)},
 	{const_cast<char*>("createCustomLineStyle"), scribus_createcustomlinestyle, METH_VARARGS, tr(scribus_createcustomlinestyle__doc__)},
 	{const_cast<char*>("currentPage"), (PyCFunction)scribus_actualpage, METH_NOARGS, tr(scribus_actualpage__doc__)},
 	{const_cast<char*>("defineColor"), scribus_newcolor, METH_VARARGS, tr(scribus_newcolor__doc__)},
@@ -453,7 +453,7 @@
 	{const_cast<char*>("redrawAll"), (PyCFunction)scribus_redraw, METH_NOARGS, tr(scribus_redraw__doc__)},
 	{const_cast<char*>("removeTableRows"), scribus_removetablerows, METH_VARARGS, tr(scribus_removetablerows__doc__)},
 	{const_cast<char*>("removeTableColumns"), scribus_removetablecolumns, METH_VARARGS, tr(scribus_removetablecolumns__doc__)},
-	{const_cast<char*>("renderFont"), (PyCFunction)scribus_renderfont, METH_KEYWORDS, tr(scribus_renderfont__doc__)},
+	{const_cast<char*>("renderFont"), (PyCFunction)scribus_renderfont, METH_VARARGS|METH_KEYWORDS, tr(scribus_renderfont__doc__)},
 	{const_cast<char*>("replaceColor"), scribus_replcolor, METH_VARARGS, tr(scribus_replcolor__doc__)},
 	{const_cast<char*>("resizeTableColumn"), scribus_resizetablecolumn, METH_VARARGS, tr(scribus_resizetablecolumn__doc__)},
 	{const_cast<char*>("resizeTableRow"), scribus_resizetablerow, METH_VARARGS, tr(scribus_resizetablerow__doc__)},
@@ -535,7 +535,7 @@
 	{const_cast<char*>("dehyphenateText"), scribus_dehyphenatetext, METH_VARARGS, tr(scribus_dehyphenatetext__doc__)},
 	{const_cast<char*>("scrollDocument"), scribus_scrolldocument, METH_VARARGS, tr(scribus_scrolldocument__doc__) },
 	{const_cast<char*>("setScaleFrameToImage"), (PyCFunction)scribus_setscaleframetoimage, METH_VARARGS, tr(scribus_setscaleframetoimage__doc__)},
-	{const_cast<char*>("setScaleImageToFrame"), (PyCFunction)scribus_setscaleimagetoframe, METH_KEYWORDS, tr(scribus_setscaleimagetoframe__doc__)},
+	{const_cast<char*>("setScaleImageToFrame"), (PyCFunction)scribus_setscaleimagetoframe, METH_VARARGS|METH_KEYWORDS, tr(scribus_setscaleimagetoframe__doc__)},
 	{const_cast<char*>("setStyle"), scribus_setstyle, METH_VARARGS, tr(scribus_setstyle__doc__)},
 	{const_cast<char*>("setCharacterStyle"), scribus_setcharstyle, METH_VARARGS, tr(scribus_setcharstyle__doc__) },
 	{const_cast<char*>("setTableStyle"), scribus_settablestyle, METH_VARARGS, tr(scribus_settablestyle__doc__)},
@@ -558,7 +558,7 @@
 	{const_cast<char*>("sizeObject"), scribus_sizeobjabs, METH_VARARGS, tr(scribus_sizeobjabs__doc__)},
 	{const_cast<char*>("statusMessage"), scribus_messagebartext, METH_VARARGS, tr(scribus_messagebartext__doc__)},
 	{const_cast<char*>("textFlowMode"), scribus_textflow, METH_VARARGS, tr(scribus_textflow__doc__)},
-	{const_cast<char*>("textOverflows"), (PyCFunction)scribus_istextoverflowing, METH_KEYWORDS, tr(scribus_istextoverflowing__doc__) },
+	{const_cast<char*>("textOverflows"), (PyCFunction)scribus_istextoverflowing, METH_VARARGS|METH_KEYWORDS, tr(scribus_istextoverflowing__doc__) },
 	{const_cast<char*>("traceText"), scribus_tracetext, METH_VARARGS, tr(scribus_tracetext__doc__)},
 	{const_cast<char*>("unGroupObject"), scribus_ungroupobj, METH_VARARGS, tr(scribus_ungroupobj__doc__)},
 	{const_cast<char*>("unlinkTextFrames"), scribus_unlinktextframes, METH_VARARGS, tr(scribus_unlinktextframes__doc__)},
@@ -565,12 +565,12 @@
 	{const_cast<char*>("valueDialog"), scribus_valdialog, METH_VARARGS, tr(scribus_valdialog__doc__)},
 	{const_cast<char*>("zoomDocument"), scribus_zoomdocument, METH_VARARGS, tr(scribus_zoomdocument__doc__)},
 	// Property magic
-	{const_cast<char*>("getPropertyCType"), (PyCFunction)scribus_propertyctype, METH_KEYWORDS, tr(scribus_propertyctype__doc__)},
-	{const_cast<char*>("getPropertyNames"), (PyCFunction)scribus_getpropertynames, METH_KEYWORDS, tr(scribus_getpropertynames__doc__)},
-	{const_cast<char*>("getProperty"), (PyCFunction)scribus_getproperty, METH_KEYWORDS, tr(scribus_getproperty__doc__)},
-	{const_cast<char*>("setProperty"), (PyCFunction)scribus_setproperty, METH_KEYWORDS, tr(scribus_setproperty__doc__)},
-// 	{const_cast<char*>("getChildren"), (PyCFunction)scribus_getchildren, METH_KEYWORDS, tr(scribus_getchildren__doc__)},
-// 	{const_cast<char*>("getChild"), (PyCFunction)scribus_getchild, METH_KEYWORDS, tr(scribus_getchild__doc__)},
+	{const_cast<char*>("getPropertyCType"), (PyCFunction)scribus_propertyctype, METH_VARARGS|METH_KEYWORDS, tr(scribus_propertyctype__doc__)},
+	{const_cast<char*>("getPropertyNames"), (PyCFunction)scribus_getpropertynames, METH_VARARGS|METH_KEYWORDS, tr(scribus_getpropertynames__doc__)},
+	{const_cast<char*>("getProperty"), (PyCFunction)scribus_getproperty, METH_VARARGS|METH_KEYWORDS, tr(scribus_getproperty__doc__)},
+	{const_cast<char*>("setProperty"), (PyCFunction)scribus_setproperty, METH_VARARGS|METH_KEYWORDS, tr(scribus_setproperty__doc__)},
+// 	{const_cast<char*>("getChildren"), (PyCFunction)scribus_getchildren, METH_VARARGS|METH_KEYWORDS, tr(scribus_getchildren__doc__)},
+// 	{const_cast<char*>("getChild"), (PyCFunction)scribus_getchild, METH_VARARGS|METH_KEYWORDS, tr(scribus_getchild__doc__)},
 	// by Christian Hausknecht
 	{const_cast<char*>("duplicateObject"), scribus_duplicateobject, METH_VARARGS, tr(scribus_duplicateobject__doc__)},
 	{const_cast<char*>("copyObject"), scribus_copyobject, METH_VARARGS, tr(scribus_copyobject__doc__)},
@@ -591,6 +591,36 @@
 	{nullptr, (PyCFunction)(nullptr), 0, nullptr} /* sentinel */
 };
 
+struct scribus_module_state
+{
+    PyObject *error;
+};
+#define GETSTATE(m) ((struct scribus_module_state*) PyModule_GetState(m))
+
+static int scribus_extension_traverse(PyObject *m, visitproc visit, void *arg)
+{
+	Py_VISIT(GETSTATE(m)->error);
+	return 0;
+}
+
+static int scribus_extension_clear(PyObject *m)
+{
+	Py_CLEAR(GETSTATE(m)->error);
+	return 0;
+}
+
+static struct PyModuleDef scribus_module_def = {
+        PyModuleDef_HEAD_INIT,
+        "scribus",
+        NULL,
+        sizeof(struct scribus_module_state),
+        scribus_methods,
+        NULL,
+        scribus_extension_traverse,
+        scribus_extension_clear,
+        NULL
+};
+
 void initscribus_failed(const char* fileName, int lineNo)
 {
 	qDebug("Scripter setup failed (%s:%i)", fileName, lineNo);
@@ -598,68 +628,78 @@
 		PyErr_Print();
 }
 
-void initscribus(ScribusMainWindow *mainWin)
+PyObject* PyInit_scribus(void)
 {
+	ScribusMainWindow* mainWin = ScCore->primaryMainWindow();
 	if (!scripterCore)
 	{
 		qWarning("scriptplugin: Tried to init scribus module, but no scripter core. Aborting.");
-		return;
+		return nullptr;
 	}
+
+	int result;
 	PyObject *m, *d;
-	PyImport_AddModule((char*)"scribus");
 
 	PyType_Ready(&Printer_Type);
 	PyType_Ready(&PDFfile_Type);
 	PyType_Ready(&ImageExport_Type);
-	m = Py_InitModule((char*)"scribus", scribus_methods);
+
+	m = PyModule_Create(&scribus_module_def);
+
 	Py_INCREF(&Printer_Type);
-	PyModule_AddObject(m, (char*)"Printer", (PyObject *) &Printer_Type);
+	result = PyModule_AddObject(m, (char*) "Printer", (PyObject *) &Printer_Type);
+	if (result != 0)
+		qDebug("scriptplugin: Could not create scribus.Printer module");
 	Py_INCREF(&PDFfile_Type);
-	PyModule_AddObject(m, (char*)"PDFfile", (PyObject *) &PDFfile_Type);
+	result = PyModule_AddObject(m, (char*) "PDFfile", (PyObject *) &PDFfile_Type);
+	if (result != 0)
+		qDebug("scriptplugin: Could not create scribus.PDFfile module");
 	Py_INCREF(&ImageExport_Type);
-	PyModule_AddObject(m, (char*)"ImageExport", (PyObject *) &ImageExport_Type);
+	PyModule_AddObject(m, (char*) "ImageExport", (PyObject *) &ImageExport_Type);
+	if (result != 0)
+		qDebug("scriptplugin: Could not create scribus.ImageExport module");
 	d = PyModule_GetDict(m);
 
 	// Set up the module exceptions
 	// common exc.
-	ScribusException = PyErr_NewException((char*)"scribus.ScribusException", nullptr, nullptr);
+	ScribusException = PyErr_NewException((char*) "scribus.ScribusException", nullptr, nullptr);
 	Py_INCREF(ScribusException);
-	PyModule_AddObject(m, (char*)"ScribusException", ScribusException);
+	PyModule_AddObject(m, (char*) "ScribusException", ScribusException);
 	// no doc open
-	NoDocOpenError = PyErr_NewException((char*)"scribus.NoDocOpenError", ScribusException, nullptr);
+	NoDocOpenError = PyErr_NewException((char*) "scribus.NoDocOpenError", ScribusException, nullptr);
 	Py_INCREF(NoDocOpenError);
-	PyModule_AddObject(m, (char*)"NoDocOpenError", NoDocOpenError);
+	PyModule_AddObject(m, (char*) "NoDocOpenError", NoDocOpenError);
 	// wrong type of frame for operation
-	WrongFrameTypeError = PyErr_NewException((char*)"scribus.WrongFrameTypeError", ScribusException, nullptr);
+	WrongFrameTypeError = PyErr_NewException((char*) "scribus.WrongFrameTypeError", ScribusException, nullptr);
 	Py_INCREF(WrongFrameTypeError);
-	PyModule_AddObject(m, (char*)"WrongFrameTypeError", WrongFrameTypeError);
+	PyModule_AddObject(m, (char*) "WrongFrameTypeError", WrongFrameTypeError);
 	// Couldn't find named object, or no named object and no selection
-	NoValidObjectError = PyErr_NewException((char*)"scribus.NoValidObjectError", ScribusException, nullptr);
+	NoValidObjectError = PyErr_NewException((char*) "scribus.NoValidObjectError", ScribusException, nullptr);
 	Py_INCREF(NoValidObjectError);
-	PyModule_AddObject(m, (char*)"NoValidObjectError", NoValidObjectError);
+	PyModule_AddObject(m, (char*) "NoValidObjectError", NoValidObjectError);
 	// Couldn't find the specified resource - font, color, etc.
-	NotFoundError = PyErr_NewException((char*)"scribus.NotFoundError", ScribusException, nullptr);
+	NotFoundError = PyErr_NewException((char*) "scribus.NotFoundError", ScribusException, nullptr);
 	Py_INCREF(NotFoundError);
-	PyModule_AddObject(m, (char*)"NotFoundError", NotFoundError);
+	PyModule_AddObject(m, (char*) "NotFoundError", NotFoundError);
 	// Tried to create an object with the same name as one that already exists
-	NameExistsError = PyErr_NewException((char*)"scribus.NameExistsError", ScribusException, nullptr);
+	NameExistsError = PyErr_NewException((char*) "scribus.NameExistsError", ScribusException, nullptr);
 	Py_INCREF(NameExistsError);
-	PyModule_AddObject(m, (char*)"NameExistsError", NameExistsError);
+	PyModule_AddObject(m, (char*) "NameExistsError", NameExistsError);
 	// Done with exception setup
 
 	// CONSTANTS
-	PyDict_SetItemString(d, const_cast<char*>("UNIT_POINTS"), PyInt_FromLong(unitIndexFromString("pt")));
-	PyDict_SetItemString(d, const_cast<char*>("UNIT_MILLIMETERS"), PyInt_FromLong(unitIndexFromString("mm")));
-	PyDict_SetItemString(d, const_cast<char*>("UNIT_INCHES"), PyInt_FromLong(unitIndexFromString("in")));
-	PyDict_SetItemString(d, const_cast<char*>("UNIT_PICAS"), PyInt_FromLong(unitIndexFromString("p")));
-	PyDict_SetItemString(d, const_cast<char*>("UNIT_CENTIMETRES"), PyInt_FromLong(unitIndexFromString("cm")));
-	PyDict_SetItemString(d, const_cast<char*>("UNIT_CICERO"), PyInt_FromLong(unitIndexFromString("c")));
-	PyDict_SetItemString(d, const_cast<char*>("UNIT_PT"), PyInt_FromLong(unitIndexFromString("pt")));
-	PyDict_SetItemString(d, const_cast<char*>("UNIT_MM"), PyInt_FromLong(unitIndexFromString("mm")));
-	PyDict_SetItemString(d, const_cast<char*>("UNIT_IN"), PyInt_FromLong(unitIndexFromString("in")));
-	PyDict_SetItemString(d, const_cast<char*>("UNIT_P"), PyInt_FromLong(unitIndexFromString("p")));
-	PyDict_SetItemString(d, const_cast<char*>("UNIT_CM"), PyInt_FromLong(unitIndexFromString("cm")));
-	PyDict_SetItemString(d, const_cast<char*>("UNIT_C"), PyInt_FromLong(unitIndexFromString("c")));
+	PyDict_SetItemString(d, const_cast<char*>("UNIT_POINTS"), PyLong_FromLong(unitIndexFromString("pt")));
+	PyDict_SetItemString(d, const_cast<char*>("UNIT_MILLIMETERS"), PyLong_FromLong(unitIndexFromString("mm")));
+	PyDict_SetItemString(d, const_cast<char*>("UNIT_INCHES"), PyLong_FromLong(unitIndexFromString("in")));
+	PyDict_SetItemString(d, const_cast<char*>("UNIT_PICAS"), PyLong_FromLong(unitIndexFromString("p")));
+	PyDict_SetItemString(d, const_cast<char*>("UNIT_CENTIMETRES"), PyLong_FromLong(unitIndexFromString("cm")));
+	PyDict_SetItemString(d, const_cast<char*>("UNIT_CICERO"), PyLong_FromLong(unitIndexFromString("c")));
+	PyDict_SetItemString(d, const_cast<char*>("UNIT_PT"), PyLong_FromLong(unitIndexFromString("pt")));
+	PyDict_SetItemString(d, const_cast<char*>("UNIT_MM"), PyLong_FromLong(unitIndexFromString("mm")));
+	PyDict_SetItemString(d, const_cast<char*>("UNIT_IN"), PyLong_FromLong(unitIndexFromString("in")));
+	PyDict_SetItemString(d, const_cast<char*>("UNIT_P"), PyLong_FromLong(unitIndexFromString("p")));
+	PyDict_SetItemString(d, const_cast<char*>("UNIT_CM"), PyLong_FromLong(unitIndexFromString("cm")));
+	PyDict_SetItemString(d, const_cast<char*>("UNIT_C"), PyLong_FromLong(unitIndexFromString("c")));
 	PyDict_SetItemString(d, const_cast<char*>("PORTRAIT"), Py_BuildValue(const_cast<char*>("i"), portraitPage));
 	PyDict_SetItemString(d, const_cast<char*>("LANDSCAPE"), Py_BuildValue(const_cast<char*>("i"), landscapePage));
 	PyDict_SetItemString(d, const_cast<char*>("NOFACINGPAGES"), Py_BuildValue(const_cast<char*>("i"), 0));
@@ -799,28 +839,28 @@
 		if (!value)
 		{
 			initscribus_failed(__FILE__, __LINE__);
-			return;
+			return nullptr;
 		}
 		// `in' is a reserved word in Python so we must replace it
 		PyObject* name;
 		if (unitGetUntranslatedStrFromIndex(i) == "in")
-			name = PyString_FromString("inch");
+			name = PyUnicode_FromString("inch");
 		else
-			name = PyString_FromString(unitGetUntranslatedStrFromIndex(i).toLatin1().constData());
+			name = PyUnicode_FromString(unitGetUntranslatedStrFromIndex(i).toUtf8().constData());
 		if (!name)
 		{
 			initscribus_failed(__FILE__, __LINE__);
-			return;
+			return nullptr;
 		}
 		if (PyDict_SetItem(d, name, value))
 		{
 			initscribus_failed(__FILE__, __LINE__);
-			return;
+			return nullptr;
 		}
 	}
 
 	// Export the Scribus version into the module namespace so scripts know what they're running in
-	PyDict_SetItemString(d, const_cast<char*>("scribus_version"), PyString_FromString(const_cast<char*>(VERSION)));
+	PyDict_SetItemString(d, const_cast<char*>("scribus_version"), PyUnicode_FromString(const_cast<char*>(VERSION)));
 	// Now build a version tuple like that provided by Python in sys.version_info
 	// The tuple is of the form (major, minor, patchlevel, extraversion, reserved)
 	QRegExp version_re("(\\d+)\\.(\\d+)\\.(\\d+)(.*)");
@@ -848,28 +888,20 @@
 	// the generated Python functions from inside the `scribus' module's context.
 	// This code makes it possible to extend the `scribus' module by running Python code
 	// from C in other ways too.
-	PyObject* builtinModule = PyImport_ImportModuleEx(const_cast<char*>("__builtin__"),
+	PyObject* builtinModule = PyImport_ImportModuleEx(const_cast<char*>("builtins"),
 			d, d, Py_BuildValue(const_cast<char*>("[]")));
 	if (builtinModule == nullptr)
 	{
-		qDebug("Failed to import __builtin__ module. Something is probably broken with your Python.");
-		return;
+		qDebug("Failed to import builtins module. Something is probably broken with your Python.");
+		return nullptr;
 	}
-	PyDict_SetItemString(d, const_cast<char*>("__builtin__"), builtinModule);
-	PyObject* exceptionsModule = PyImport_ImportModuleEx(const_cast<char*>("exceptions"),
-			d, d, Py_BuildValue(const_cast<char*>("[]")));
-	if (exceptionsModule == nullptr)
-	{
-		qDebug("Failed to import exceptions module. Something is probably broken with your Python.");
-		return;
-	}
-	PyDict_SetItemString(d, const_cast<char*>("exceptions"), exceptionsModule);
+	PyDict_SetItemString(d, const_cast<char*>("builtins"), builtinModule);
 	PyObject* warningsModule = PyImport_ImportModuleEx(const_cast<char*>("warnings"),
 			d, d, Py_BuildValue(const_cast<char*>("[]")));
 	if (warningsModule == nullptr)
 	{
 		qDebug("Failed to import warnings module. Something is probably broken with your Python.");
-		return;
+		return nullptr;
 	}
 	PyDict_SetItemString(d, const_cast<char*>("warnings"), warningsModule);
 	// Create the module-level docstring. This can be a proper unicode string, unlike
@@ -907,21 +939,11 @@
 is not exhaustive due to exceptions from called functions.\n\
 ");
 
-	PyObject* docStr = PyString_FromString(docstring.toUtf8().data());
+	PyObject* docStr = PyUnicode_FromString(docstring.toUtf8().data());
 	if (!docStr)
 		qDebug("Failed to create module-level docstring (couldn't make str)");
 	else
-	{
-		PyObject* uniDocStr = PyUnicode_FromEncodedObject(docStr, "utf-8", nullptr);
-		Py_DECREF(docStr);
-		docStr = nullptr;
-		if (!uniDocStr)
-			qDebug("Failed to create module-level docstring object (couldn't make unicode)");
-		else
-			PyDict_SetItemString(d, const_cast<char*>("__doc__"), uniDocStr);
-		Py_DECREF(uniDocStr);
-		uniDocStr = nullptr;
-	}
+		PyDict_SetItemString(d, const_cast<char*>("__doc__"), docStr);
 
 	// Wrap up pointers to the the QApp and main window and push them out
 	// to Python.
@@ -946,6 +968,8 @@
 	PyDict_SetItemString(d, const_cast<char*>("mainWindow"), wrappedMainWindow);
 	Py_DECREF(wrappedMainWindow);
 	wrappedMainWindow = nullptr;
+
+	return m;
 }
 
 /*! HACK: this removes "warning: 'blah' defined but not used" compiler warnings
Index: scribus/plugins/scriptplugin/scripts/Align_image_in_frame.py
===================================================================
--- scribus/plugins/scriptplugin/scripts/Align_image_in_frame.py	(revision 23269)
+++ scribus/plugins/scriptplugin/scripts/Align_image_in_frame.py	(working copy)
@@ -22,10 +22,9 @@
 import scribus
  
 try:
-    from Tkinter import *
-    from tkFont import Font
+    from tkinter import *
 except ImportError:
-    print "This script requires Python's Tkinter properly installed."
+    print ("This script requires Python's Tkinter properly installed.")
     scribus.messageBox('Script failed',
                'This script requires Python\'s Tkinter properly installed.',
                scribus.ICON_CRITICAL)
@@ -83,8 +82,8 @@
  
     def alignImage(self):
         if scribus.haveDoc():
-	    restore_units = scribus.getUnit()   # since there is an issue with units other than points,
-	    scribus.setUnit(0)			# we switch to points then restore later.
+            restore_units = scribus.getUnit()   # since there is an issue with units other than points,
+            scribus.setUnit(0)			# we switch to points then restore later.
             nbrSelected = scribus.selectionCount()
             objList = []
             for i in range(nbrSelected):
@@ -124,9 +123,9 @@
                     scribus.deselectAll()
                 except:
                     nothing = "nothing"
-	    scribus.setUnit(restore_units)
-	    
-	    self.master.destroy()
+            scribus.setUnit(restore_units)
+            
+            self.master.destroy()
  
  
 def main():
Index: scribus/plugins/scriptplugin/scripts/CalendarWizard.py
===================================================================
--- scribus/plugins/scriptplugin/scripts/CalendarWizard.py	(revision 23269)
+++ scribus/plugins/scriptplugin/scripts/CalendarWizard.py	(working copy)
@@ -54,16 +54,16 @@
 try:
     from scribus import *
 except ImportError:
-    print "This Python script is written for the Scribus scripting interface."
-    print "It can only be run from within Scribus."
+    print ("This Python script is written for the Scribus scripting interface.")
+    print ("It can only be run from within Scribus.")
     sys.exit(1)
 
 try:
     # I wish PyQt installed everywhere :-/
-    from Tkinter import *
-    from tkFont import Font
+    from tkinter import *
+    from tkinter import font
 except ImportError:
-    print "This script requires Python's Tkinter properly installed."
+    print ("This script requires Python's Tkinter properly installed.")
     messageBox('Script failed',
                'This script requires Python\'s Tkinter properly installed.',
                ICON_CRITICAL)
@@ -307,14 +307,14 @@
         ScCalendar.__init__(self, year, months, firstDay, drawSauce, sepMonths, lang)
 
     def printMonth(self, cal, month, week):
-	    """ Print the month name(s) """
-	    if week[6].day < 7:
-		    if (week == cal[len(cal)-1]):
-			    self.createHeader(localization[self.lang][0][month] + self.sepMonths + localization[self.lang][0][(month+1)%12])
-		    elif ((month-1) not in self.months):
-			    self.createHeader(localization[self.lang][0][(month-1)%12] + self.sepMonths + localization[self.lang][0][month])
-	    else:
-		    self.createHeader(localization[self.lang][0][month])
+        """ Print the month name(s) """
+        if week[6].day < 7:
+            if (week == cal[len(cal)-1]):
+                self.createHeader(localization[self.lang][0][month] + self.sepMonths + localization[self.lang][0][(month+1)%12])
+            elif ((month-1) not in self.months):
+                self.createHeader(localization[self.lang][0][(month-1)%12] + self.sepMonths + localization[self.lang][0][month])
+        else:
+            self.createHeader(localization[self.lang][0][month])
 
     def createMonthCalendar(self, month, cal):
         """ Draw one week calendar per page """
@@ -325,12 +325,12 @@
             # * If it starts on the first weekday
             # * If the month before it isn't included
             if (week != cal[0]) or (week[0].day == 1) or ((month-1) not in self.months):
-				self.createLayout()
-				self.printMonth(cal, month, week)
-				self.printWeekNo(week)
+                self.createLayout()
+                self.printMonth(cal, month, week)
+                self.printWeekNo(week)
 
-				for day in week:
-				    self.printDay(day)
+                for day in week:
+                    self.printDay(day)
 
 class ScHorizontalEventCalendar(ScEventCalendar):
     """ One day = one row calendar. I suggest LANDSCAPE orientation.\
@@ -445,11 +445,11 @@
                 cel = createText(self.marginl + colCnt * self.colSize,
                                  self.calHeight + rowCnt * self.rowSize,
                                  self.colSize, self.rowSize)
-		setLineColor("Black", cel)  # comment this out if you do not want border to cells
+                setLineColor("Black", cel)  # comment this out if you do not want border to cells
                 colCnt += 1
                 if day.month == month + 1:
-					setText(str(day.day), cel)
-					setStyle(self.pStyleDate, cel)
+                    setText(str(day.day), cel)
+                    setStyle(self.pStyleDate, cel)
             rowCnt += 1
 
 class ScVerticalEventCalendar(ScVerticalCalendar, ScEventCalendar):
@@ -507,7 +507,7 @@
         self.langScrollbar.config(command=self.langListbox.yview)
 
         keys = localization.keys()
-        keys.sort()
+        sorted(keys)
         for i in keys:
             self.langListbox.insert(END, i)
         self.langButton = Button(self, text='Change language', command=self.languageChange)
Index: scribus/plugins/scriptplugin/scripts/Caption.py
===================================================================
--- scribus/plugins/scriptplugin/scripts/Caption.py	(revision 23269)
+++ scribus/plugins/scriptplugin/scripts/Caption.py	(working copy)
@@ -47,8 +47,8 @@
 try:
     import scribus
 except ImportError:
-    print "Unable to import the 'scribus' module. This script will only run within"
-    print "the Python interpreter embedded in Scribus. Try Script->Execute Script."
+    print ("Unable to import the 'scribus' module. This script will only run within")
+    print ("the Python interpreter embedded in Scribus. Try Script->Execute Script.")
     sys.exit(1)
 
 numselect = scribus.selectionCount()
Index: scribus/plugins/scriptplugin/scripts/color2csv.py
===================================================================
--- scribus/plugins/scriptplugin/scripts/color2csv.py	(revision 23269)
+++ scribus/plugins/scriptplugin/scripts/color2csv.py	(working copy)
@@ -45,9 +45,9 @@
     # Do so _after_ the 'import scribus' and only import the names you need, such
     # as commonly used constants.
     import scribus
-except ImportError,err:
-    print "This Python script is written for the Scribus scripting interface."
-    print "It can only be run from within Scribus."
+except ImportError as err:
+    print ("This Python script is written for the Scribus scripting interface.")
+    print ("It can only be run from within Scribus.")
     sys.exit(1)
 
 #########################
@@ -92,7 +92,7 @@
     scribus.progressTotal(len(colorlist))
     i=0
     try:
-        csvwriter=csv.writer(file(filename, "w"), quoting=csv.QUOTE_NONNUMERIC)
+        csvwriter=csv.writer(open(filename, "w"), quoting=csv.QUOTE_NONNUMERIC)
         for line in colorlist:
             csvwriter.writerow(line)
             i=i+1
Index: scribus/plugins/scriptplugin/scripts/ColorChart.py
===================================================================
--- scribus/plugins/scriptplugin/scripts/ColorChart.py	(revision 23269)
+++ scribus/plugins/scriptplugin/scripts/ColorChart.py	(working copy)
@@ -47,9 +47,9 @@
     # Do so _after_ the 'import scribus' and only import the names you need, such
     # as commonly used constants.
     import scribus
-except ImportError,err:
-    print "This Python script is written for the Scribus scripting interface."
-    print "It can only be run from within Scribus."
+except ImportError as err:
+    print ("This Python script is written for the Scribus scripting interface.")
+    print ("It can only be run from within Scribus.")
     sys.exit(1)
 
 ####################
@@ -168,7 +168,7 @@
         y = int(color[3])
         k = int(color[4])
         scribus.defineColorCMYK(cname,  c, m, y, k )
-        if spotDict.has_key(cname):
+        if cname in spotDict:
             scribus.setSpotColor(cname, spotDict[cname])
 
     #get the pageTitle form user and store it in PageTitle
Index: scribus/plugins/scriptplugin/scripts/csv2color.py
===================================================================
--- scribus/plugins/scriptplugin/scripts/csv2color.py	(revision 23269)
+++ scribus/plugins/scriptplugin/scripts/csv2color.py	(working copy)
@@ -51,9 +51,9 @@
     # Do so _after_ the 'import scribus' and only import the names you need, such
     # as commonly used constants.
     import scribus
-except ImportError,err:
-    print "This Python script is written for the Scribus scripting interface."
-    print "It can only be run from within Scribus."
+except ImportError as err:
+    print ("This Python script is written for the Scribus scripting interface.")
+    print ("It can only be run from within Scribus.")
     sys.exit(1)
 
 #########################
@@ -79,7 +79,7 @@
 
 def getColorsFromCsv(filename):
     """get colors from csv file and return a list with name and cmyk 255 values"""
-    csvreader=csv.reader(file(filename))
+    csvreader=csv.reader(open(filename, "r"))
 
     csvcolors=[]
     i=0
@@ -129,7 +129,7 @@
             m=color[2]
             y=color[3]
             k=color[4]
-            while colordict.has_key(name):# check if color already exists - then add PREFIX to name
+            while name in colordict:# check if color already exists - then add PREFIX to name
                 name = PREFIX+name
             
             scribus.defineColorCMYK(name, c, m, y, k)
Index: scribus/plugins/scriptplugin/scripts/DirectImageImport.py
===================================================================
--- scribus/plugins/scriptplugin/scripts/DirectImageImport.py	(revision 23269)
+++ scribus/plugins/scriptplugin/scripts/DirectImageImport.py	(working copy)
@@ -54,7 +54,7 @@
     from scribus import *
     
 except ImportError:
-    print "This script only runs from within Scribus."
+    print ("This script only runs from within Scribus.")
     sys.exit(1)
 try:
     from PIL import Image
@@ -77,8 +77,8 @@
 
 # for images taller than they are wide we want to limit height of frame to 80% of page height
     if (Hoehe > pageY * 0.8):
-	Hoehe = pageY * 0.8
-	Breite = Hoehe * xsize/ysize
+        Hoehe = pageY * 0.8
+        Breite = Hoehe * xsize/ysize
 
     ImageFrame = createImage(pageX/2 - Breite/2, pageY/2 - Hoehe/2, Breite, Hoehe)
     loadImage(ImageFileName, ImageFrame)
Index: scribus/plugins/scriptplugin/scripts/FontSample.py
===================================================================
--- scribus/plugins/scriptplugin/scripts/FontSample.py	(revision 23269)
+++ scribus/plugins/scriptplugin/scripts/FontSample.py	(working copy)
@@ -112,7 +112,7 @@
 
 import sys
 import os
-import cPickle
+import pickle
 
 
 showPreviewPanel = 1 # change to 0 to permanently hide the preview
@@ -122,17 +122,17 @@
 
 try:
     import scribus
-except ImportError,err:
-    print 'This Python script is written for the Scribus scripting interface.'
-    print 'It can only be run from within Scribus.'
+except ImportError as err:
+    print ('This Python script is written for the Scribus scripting interface.')
+    print ('It can only be run from within Scribus.')
     sys.exit(1)
 
 
 try:
-    from Tkinter import *
-except ImportError,err:
-    print 'This script will not work without Tkinter'
-    scribus.messageBox('Error','This script will not work without Tkinter\nPlease install and try again',
+    from tkinter import *
+except ImportError as err:
+    print ('This script will not work without tkinter')
+    scribus.messageBox('Error','This script will not work without tkinter\nPlease install and try again',
                     scribus.ICON_WARNING)
     sys.exit(1)
 
@@ -139,43 +139,43 @@
 
 if not os.path.exists(CONFIG_PATH):
     try:
-        print 'Attempting to creating configuration file directory...'
+        print ('Attempting to creating configuration file directory...')
         os.mkdir(CONFIG_PATH)
-        print 'Success, now testing for write access of new directory...'
+        print ('Success, now testing for write access of new directory...')
         if os.access(CONFIG_PATH, os.W_OK):
-            print 'Write access ok.'
+            print ('Write access ok.')
         else:
-            print 'Error, unable to write to .scribus/fontsampler directory.'
+            print ('Error, unable to write to .scribus/fontsampler directory.')
     except:
         CONFIG_PATH = ''
-        print 'Failed to make configuration file directory,'
-        print 'do you have a .scribus directory in your home directory?'
-        print 'font sampler will not be able to save your preferences'
+        print ('Failed to make configuration file directory,')
+        print ('do you have a .scribus directory in your home directory?')
+        print ('font sampler will not be able to save your preferences')
 
 
 try:
     from PIL import Image
-except ImportError,err:
-    print 'You need to install Python Imaging Library (PIL).'
-    print 'If using gentoo then you need to emerge /dev-python/imaging'
-    print 'If using an RPM based linux distribution then you add python-imaging or similar.'
-    print 'Script will continue without the font preview panel.'
+except ImportError as err:
+    print ('You need to install Python Imaging Library (PIL).')
+    print ('If using gentoo then you need to emerge /dev-python/imaging')
+    print ('If using an RPM based linux distribution then you add python-imaging or similar.')
+    print ('Script will continue without the font preview panel.')
     showPreviewPanel = 0
 
 
 try:
     from PIL import ImageTk
-except ImportError,err:
-    print 'Module ImageTk not found, font preview disabled'
+except ImportError as err:
+    print ('Module ImageTk not found, font preview disabled')
     showPreviewPanel = 0
 
 
 if showPreviewPanel:
     if not os.path.exists(TEMP_PATH):
-        print '.scribus folder not found, disabling font preview panel'
+        print ('.scribus folder not found, disabling font preview panel')
         showPreviewPanel = 0
     if not os.access(TEMP_PATH, os.W_OK):
-        print 'Unable to write to .scribus folder, disabling font preview panel'
+        print ('Unable to write to .scribus folder, disabling font preview panel')
         showPreviewPanel = 0
 
 
@@ -369,7 +369,7 @@
         for j in fontList:
             errorList = errorList + j + '\n'
         errorMessage ='No suitable fixed width font found.\nPlease install at least one of these fixed width fonts:\n'+errorList
-        print errorMessage
+        print (errorMessage)
         raise Exception(errorMessage)
 
 
@@ -391,7 +391,7 @@
         for j in fontList:
             errorList = errorList + j + '\n'
         errorMessage = 'No suitable proportional font found.\nPlease install at least one of these proportional fonts:\n'+errorList
-        print errorMessage
+        print (errorMessage)
         raise Exception(errorMessage)
 
 
@@ -406,10 +406,10 @@
                 'a' : defaultPrefs,
                 'b' : userPrefs
             }
-            cPickle.dump(data, file)
+            pickle.dump(data, file)
             file.close()
         except:
-            print 'failed to save data'
+            print ('failed to save data')
 
 
 def restore_user_conf(path):
@@ -416,13 +416,13 @@
     """Restore the data from the save file on the path specified by CONFIG_PATH."""
     try:
         file = open(os.path.join(path,'fontsampler.conf'), 'r')
-        data = cPickle.load(file)
+        data = pickle.load(file)
         file.close()
         defaultPrefs.update(data['a'])
         userPrefs.update(data['b'])
     except:
         userPrefs.update(defaultPrefs)
-        print 'failed to load saved data so using default values defined in the script'
+        print ('failed to load saved data so using default values defined in the script')
 
 
 def set_page_geometry(dD, geometriesList, paperSize, wantBindingOffset):
@@ -464,7 +464,7 @@
         return result
     except:
         errorMessage = 'set_page_geometry() failure: %s' % sys.exc_info()[1]
-        print errorMessage
+        print (errorMessage)
 
 
 def set_odd_even(pageNum):
@@ -1227,10 +1227,10 @@
         """
         available = self.listbox1.size()
         selected = self.listbox2.size()
-        size = FloatType(selected)
+        size = float(selected)
         blocksPerSheet = draw_selection(scribus.getFontNames(), 1)
         value = size / blocksPerSheet
-        pages = IntType(value)                  # Get whole part of number
+        pages = int(value)                  # Get whole part of number
         value = value - pages                   # Remove whole number part
         if value > 0:                           # Test remainder
             pages = pages + 1                   # Had remainder so add a page
@@ -1241,7 +1241,7 @@
         self.statusPaperSize['text'] = 'Paper size: %s   ' % userPrefs['paperSize']
 
     def __listSelectionToRight(self):
-        toMoveRight = ListType(self.listbox1.curselection())
+        toMoveRight = list(self.listbox1.curselection())
         self.listbox1.selection_clear(0,END)
         toMoveRight.reverse()   # reverse list so we delete from bottom of listbox first
         tempList = []
@@ -1255,13 +1255,13 @@
         self.statusbarUpdate()
 
     def __listSelectionToLeft(self):
-        toMoveLeft = ListType(self.listbox2.curselection())
+        toMoveLeft = list(self.listbox2.curselection())
         toMoveLeft.reverse()
         self.listbox2.selection_clear(0,END)
         for i in toMoveLeft:
             self.listbox1.insert(END, self.listbox2.get(i)) # Insert it at the end
             self.listbox2.delete(i)
-        fontList = ListType(self.listbox1.get(0, END))      # Copy contents to a list type
+        fontList = list(self.listbox1.get(0, END))      # Copy contents to a list type
         self.listbox1.delete(0, END)                        # Remove all contents
         fontList.sort()                                     # Use sort method of list
         for j in fontList:
@@ -1508,7 +1508,7 @@
 
 
 def setup_tk():
-    """Create and setup the Tkinter app."""
+    """Create and setup the tkinter app."""
     root = Tk()
     app = Application(root)
     app.master.title(WINDOW_TITLE)
@@ -1540,7 +1540,7 @@
     restore_user_conf(CONFIG_PATH)
     # get and set the initial paper size to match default radiobutton selection...
     dD.update(set_page_geometry(dD, geometriesList, userPrefs['paperSize'], userPrefs['wantBindingOffset']))
-    # Made it this far so its time to create our Tkinter app...
+    # Made it this far so its time to create our tkinter app...
     app = setup_tk()
     # now show the main window and wait for user to do something...
     app.mainloop()
Index: scribus/plugins/scriptplugin/scripts/importcsv2table.py
===================================================================
--- scribus/plugins/scriptplugin/scripts/importcsv2table.py	(revision 23269)
+++ scribus/plugins/scriptplugin/scripts/importcsv2table.py	(working copy)
@@ -72,9 +72,9 @@
     # Do so _after_ the 'import scribus' and only import the names you need, such
     # as commonly used constants.
     import scribus
-except ImportError,err:
-    print "This Python script is written for the Scribus scripting interface."
-    print "It can only be run from within Scribus."
+except ImportError as err:
+    print ("This Python script is written for the Scribus scripting interface.")
+    print ("It can only be run from within Scribus.")
     sys.exit(1)
 
 #########################
@@ -102,7 +102,7 @@
     csvfile = scribus.fileDialog("csv2table :: open file", "*.csv")
     if csvfile != "":
         try:
-            reader = csv.reader(file(csvfile))
+            reader = csv.reader(open(csvfile, "r"))
             datalist=[]
             for row in reader:
                 rowlist=[]
@@ -110,7 +110,7 @@
                     rowlist.append(col)
                 datalist.append(rowlist)
             return datalist
-        except Exception,  e:
+        except Exception as e:
             scribus.messageBox("csv2table", "Could not open file %s"%e)
     else:
         sys.exit
Index: scribus/plugins/scriptplugin/scripts/InfoBox.py
===================================================================
--- scribus/plugins/scriptplugin/scripts/InfoBox.py	(revision 23269)
+++ scribus/plugins/scriptplugin/scripts/InfoBox.py	(working copy)
@@ -60,8 +60,8 @@
 try:
     import scribus
 except ImportError:
-    print "Unable to import the 'scribus' module. This script will only run within"
-    print "the Python interpreter embedded in Scribus. Try Script->Execute Script."
+    print ("Unable to import the 'scribus' module. This script will only run within")
+    print ("the Python interpreter embedded in Scribus. Try Script->Execute Script.")
     sys.exit(1)
 
 def main(argv):
@@ -116,7 +116,7 @@
                                          str(o_cols) + ')?','1')
             column_pos = int(column_pos) - 1 
     if (o_cols == 1):
-	columns_width = 1
+        columns_width = 1
     new_height = 0
     while (new_height <= 0):
         new_height = scribus.valueDialog('Height','Your frame height is '+ str(o_height) +
Index: scribus/plugins/scriptplugin/scripts/Ligatursatz.py
===================================================================
--- scribus/plugins/scriptplugin/scripts/Ligatursatz.py	(revision 23269)
+++ scribus/plugins/scriptplugin/scripts/Ligatursatz.py	(working copy)
@@ -137,7 +137,7 @@
         Postcondition: Constructs a hyphenator object for the
         given patterns.
         """
-        if type(patterns) is not unicode:
+        if type(patterns) is not str:
             raise TypeError("The “patterns” parameter must be of type "
                             "“unicode”, but it isn’t.")
         self.tree = {}
@@ -170,7 +170,7 @@
             the word might get wrong hyphenation because the
             upper-case-letters are not recognized).
         """
-        if type(word) is not unicode:
+        if type(word) is not str:
             raise TypeError("The word must have the data type “unicode”, "
                             "but it doesn’t.")
         else:
@@ -289,7 +289,7 @@
         WARNING This function must be kept
         in synch with isWordCharacter().
         """
-        if type(my_unicode_string) is not unicode:
+        if type(my_unicode_string) is not str:
             raise TypeError("The “my_unicode_string” parameter must be of "
                             "type “unicode”, but it isn’t.")
         return my_unicode_string.lower().replace("ſ", "s")
@@ -22283,7 +22283,7 @@
         šâäéóöü
         :rtype: list
         """
-        if type(my_word) is not unicode:
+        if type(my_word) is not str:
             raise TypeError("myWord must be of type “unicode”, but it isn’t.")
         stripped_word = u""
         stripped_word_index = []
@@ -22367,7 +22367,7 @@
     Unicode scalar values consists of the ranges 0 to D7FF (16) and E000 (16)
     to 10FFFF (16), inclusive.”
     """
-    if type(my_string) is not unicode:
+    if type(my_string) is not str:
         raise TypeError(
             "“my_string” must be of type “unicode”, but it isn’t.")
     return re.search(u"[^\u0000-\uD7FF\uE000-\uFFFF]", my_string) is None
@@ -22460,7 +22460,7 @@
                 raise IndexError("“first” is out of range.")
             return u""
         scribus.selectText(first, count, self.__identifier)
-        return scribus.getAllText(self.__identifier).decode("utf8", "strict")
+        return scribus.getAllText(self.__identifier)
 
     def delete_text(self, first, count):
         """Precondition: The object with the unique identifier “textFrame”
@@ -22514,7 +22514,7 @@
         “story”, that means the common text content that is shared between
         this text frame and all linked text frames. Note that this function
         will (likely) change the current text selection of the story."""
-        if (type(first) is not int) or (type(text) is not unicode):
+        if (type(first) is not int) or (type(text) is not str):
             raise TypeError("“first” must be “integer” and “text” must "
                             "be “unicode”, but they aren’t.")
         if first < 0:
@@ -22528,7 +22528,7 @@
                                "the constructor does currently not refer to "
                                "a text frame in the current document.")
         scribus.insertText(
-            text.encode("utf8", "strict"),
+            text,
             first,
             self.__identifier)
 
@@ -22560,9 +22560,9 @@
     Preconditions: “caption” and “message” are of type “unicode”. icon,
     button1, button2 and button3 are either not used or of type int.
     Postcondition: Calls show_messagebox and returns the result."""
-    if type(caption) is not unicode:
+    if type(caption) is not str:
         raise TypeError("“caption” must be of type “unicode”, but it isn’t.")
-    if type(message) is not unicode:
+    if type(message) is not str:
         raise TypeError("“message” must be of type “unicode”, but it isn’t.")
     if type(icon) is not int:
         raise TypeError("“icon” must be of type “int”, but it isn’t.")
@@ -22573,8 +22573,8 @@
     if type(button3) is not int:
         raise TypeError("“button3” must be of type “int”, but it isn’t.")
     return scribus.messageBox(
-        caption.encode("utf8", "strict"),
-        message.encode("utf8", "strict"),
+        caption,
+        message,
         icon,
         button1,
         button2,
Index: win32/msvc2015/scriptplugin/scriptplugin.vcxproj
===================================================================
--- win32/msvc2015/scriptplugin/scriptplugin.vcxproj	(revision 23269)
+++ win32/msvc2015/scriptplugin/scriptplugin.vcxproj	(working copy)
@@ -95,7 +95,7 @@
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <ClCompile>
       <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>..;..\..\..\scribus;..\..\..\scribus\ui;$(QT5_DIR)\include\QtCore;$(QT5_DIR)\include\QtGui;$(QT5_DIR)\include\QtNetwork;$(QT5_DIR)\include\QtWidgets;$(QT5_DIR)\include\QtWebKit;$(QT5_DIR)\include\QtWebKitWidgets;$(QT5_DIR)\include\QtXml;$(QT5_DIR)\include;$(CAIRO_INCLUDE_DIR);$(FREETYPE_INCLUDE_DIR);$(ICU_INCLUDE_DIR);$(LCMS_INCLUDE_DIR);$(LIBJPEG_INCLUDE_DIR);$(LIBTIFF_INCLUDE_DIR);$(PYTHON_INCLUDE_DIR);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>..;..\..\..\scribus;..\..\..\scribus\ui;$(QT5_DIR)\include\QtCore;$(QT5_DIR)\include\QtGui;$(QT5_DIR)\include\QtNetwork;$(QT5_DIR)\include\QtWidgets;$(QT5_DIR)\include\QtWebKit;$(QT5_DIR)\include\QtWebKitWidgets;$(QT5_DIR)\include\QtXml;$(QT5_DIR)\include;$(CAIRO_INCLUDE_DIR);$(FREETYPE_INCLUDE_DIR);$(ICU_INCLUDE_DIR);$(LCMS_INCLUDE_DIR);$(LIBJPEG_INCLUDE_DIR);$(LIBTIFF_INCLUDE_DIR);$(PYTHON3_INCLUDE_DIR);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>WIN32;_DEBUG;_USE_MATH_DEFINES;_USRDLL;_WINDOWS;QT_DLL;QT_GUI_LIB;QT_CORE_LIB;QT_THREAD_SUPPORT;COMPILE_PLUGIN_AS_DLL;AVOID_WIN32_FILEIO;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <MinimalRebuild>true</MinimalRebuild>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
@@ -109,8 +109,8 @@
       <ForcedIncludeFiles>plugins_pch.h;%(ForcedIncludeFiles)</ForcedIncludeFiles>
     </ClCompile>
     <Link>
-      <AdditionalDependencies>$(QT5CORE_LIB);$(QT5GUI_LIB);$(QT5WIDGETS_LIB);$(QT5XML_LIB);$(FREETYPE_LIB);$(LIBJPEG_LIB);$(LIBTIFF_LIB);$(LCMS_LIB);$(PYTHON_LIB);scribus-api.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(LCMS_LIB_DIR);$(FREETYPE_LIB_DIR);$(LIBJPEG_LIB_DIR);$(LIBTIFF_LIB_DIR);$(PYTHON_LIB_DIR)s;$(QT5_DIR)\lib;$(OutDir)..;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalDependencies>$(QT5CORE_LIB);$(QT5GUI_LIB);$(QT5WIDGETS_LIB);$(QT5XML_LIB);$(FREETYPE_LIB);$(LIBJPEG_LIB);$(LIBTIFF_LIB);$(LCMS_LIB);$(PYTHON3_LIB);scribus-api.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalLibraryDirectories>$(LCMS_LIB_DIR);$(FREETYPE_LIB_DIR);$(LIBJPEG_LIB_DIR);$(LIBTIFF_LIB_DIR);$(PYTHON3_LIB_DIR)s;$(QT5_DIR)\lib;$(OutDir)..;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <RandomizedBaseAddress>false</RandomizedBaseAddress>
@@ -121,7 +121,7 @@
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
     <ClCompile>
       <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>..;..\..\..\scribus;..\..\..\scribus\ui;$(QT5_DIR)\include\QtCore;$(QT5_DIR)\include\QtGui;$(QT5_DIR)\include\QtNetwork;$(QT5_DIR)\include\QtWidgets;$(QT5_DIR)\include\QtWebKit;$(QT5_DIR)\include\QtWebKitWidgets;$(QT5_DIR)\include\QtXml;$(QT5_DIR)\include;$(CAIRO_INCLUDE_DIR);$(FREETYPE_INCLUDE_DIR);$(ICU_INCLUDE_DIR);$(LCMS_INCLUDE_DIR);$(LIBJPEG_INCLUDE_DIR);$(LIBTIFF_INCLUDE_DIR);$(PYTHON_INCLUDE_DIR);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>..;..\..\..\scribus;..\..\..\scribus\ui;$(QT5_DIR)\include\QtCore;$(QT5_DIR)\include\QtGui;$(QT5_DIR)\include\QtNetwork;$(QT5_DIR)\include\QtWidgets;$(QT5_DIR)\include\QtWebKit;$(QT5_DIR)\include\QtWebKitWidgets;$(QT5_DIR)\include\QtXml;$(QT5_DIR)\include;$(CAIRO_INCLUDE_DIR);$(FREETYPE_INCLUDE_DIR);$(ICU_INCLUDE_DIR);$(LCMS_INCLUDE_DIR);$(LIBJPEG_INCLUDE_DIR);$(LIBTIFF_INCLUDE_DIR);$(PYTHON3_INCLUDE_DIR);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>WIN32;_DEBUG;_USE_MATH_DEFINES;_USRDLL;_WINDOWS;QT_DLL;QT_GUI_LIB;QT_CORE_LIB;QT_THREAD_SUPPORT;COMPILE_PLUGIN_AS_DLL;AVOID_WIN32_FILEIO;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -134,8 +134,8 @@
       <ForcedIncludeFiles>plugins_pch.h;%(ForcedIncludeFiles)</ForcedIncludeFiles>
     </ClCompile>
     <Link>
-      <AdditionalDependencies>$(QT5CORE_LIB);$(QT5GUI_LIB);$(QT5WIDGETS_LIB);$(QT5XML_LIB);$(FREETYPE_LIB);$(LIBJPEG_LIB);$(LIBTIFF_LIB);$(LCMS_LIB);$(PYTHON_LIB);scribus-api.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(LCMS_LIB_DIR);$(FREETYPE_LIB_DIR);$(LIBJPEG_LIB_DIR);$(LIBTIFF_LIB_DIR);$(PYTHON_LIB_DIR)s;$(QT5_DIR)\lib;$(OutDir)..;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalDependencies>$(QT5CORE_LIB);$(QT5GUI_LIB);$(QT5WIDGETS_LIB);$(QT5XML_LIB);$(FREETYPE_LIB);$(LIBJPEG_LIB);$(LIBTIFF_LIB);$(LCMS_LIB);$(PYTHON3_LIB);scribus-api.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalLibraryDirectories>$(LCMS_LIB_DIR);$(FREETYPE_LIB_DIR);$(LIBJPEG_LIB_DIR);$(LIBTIFF_LIB_DIR);$(PYTHON3_LIB_DIR)s;$(QT5_DIR)\lib;$(OutDir)..;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <RandomizedBaseAddress>false</RandomizedBaseAddress>
@@ -148,7 +148,7 @@
       <Optimization>MinSpace</Optimization>
       <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
       <OmitFramePointers>true</OmitFramePointers>
-      <AdditionalIncludeDirectories>..;..\..\..\scribus;..\..\..\scribus\ui;$(QT5_DIR)\include\QtCore;$(QT5_DIR)\include\QtGui;$(QT5_DIR)\include\QtNetwork;$(QT5_DIR)\include\QtWidgets;$(QT5_DIR)\include\QtWebKit;$(QT5_DIR)\include\QtWebKitWidgets;$(QT5_DIR)\include\QtXml;$(QT5_DIR)\include;$(CAIRO_INCLUDE_DIR);$(FREETYPE_INCLUDE_DIR);$(ICU_INCLUDE_DIR);$(LCMS_INCLUDE_DIR);$(LIBJPEG_INCLUDE_DIR);$(LIBTIFF_INCLUDE_DIR);$(PYTHON_INCLUDE_DIR);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>..;..\..\..\scribus;..\..\..\scribus\ui;$(QT5_DIR)\include\QtCore;$(QT5_DIR)\include\QtGui;$(QT5_DIR)\include\QtNetwork;$(QT5_DIR)\include\QtWidgets;$(QT5_DIR)\include\QtWebKit;$(QT5_DIR)\include\QtWebKitWidgets;$(QT5_DIR)\include\QtXml;$(QT5_DIR)\include;$(CAIRO_INCLUDE_DIR);$(FREETYPE_INCLUDE_DIR);$(ICU_INCLUDE_DIR);$(LCMS_INCLUDE_DIR);$(LIBJPEG_INCLUDE_DIR);$(LIBTIFF_INCLUDE_DIR);$(PYTHON3_INCLUDE_DIR);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>WIN32;NDEBUG;_USE_MATH_DEFINES;_USRDLL;_WINDOWS;QT_DLL;QT_GUI_LIB;QT_CORE_LIB;QT_THREAD_SUPPORT;COMPILE_PLUGIN_AS_DLL;AVOID_WIN32_FILEIO;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>true</StringPooling>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
@@ -162,8 +162,8 @@
       <ForcedIncludeFiles>plugins_pch.h;%(ForcedIncludeFiles)</ForcedIncludeFiles>
     </ClCompile>
     <Link>
-      <AdditionalDependencies>$(QT5CORE_LIB);$(QT5GUI_LIB);$(QT5WIDGETS_LIB);$(QT5XML_LIB);$(FREETYPE_LIB);$(LIBJPEG_LIB);$(LIBTIFF_LIB);$(LCMS_LIB);$(PYTHON_LIB);scribus-api.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(LCMS_LIB_DIR);$(FREETYPE_LIB_DIR);$(LIBJPEG_LIB_DIR);$(LIBTIFF_LIB_DIR);$(PYTHON_LIB_DIR)s;$(QT5_DIR)\lib;$(OutDir)..;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalDependencies>$(QT5CORE_LIB);$(QT5GUI_LIB);$(QT5WIDGETS_LIB);$(QT5XML_LIB);$(FREETYPE_LIB);$(LIBJPEG_LIB);$(LIBTIFF_LIB);$(LCMS_LIB);$(PYTHON3_LIB);scribus-api.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalLibraryDirectories>$(LCMS_LIB_DIR);$(FREETYPE_LIB_DIR);$(LIBJPEG_LIB_DIR);$(LIBTIFF_LIB_DIR);$(PYTHON3_LIB_DIR)s;$(QT5_DIR)\lib;$(OutDir)..;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
@@ -178,7 +178,7 @@
       <Optimization>MinSpace</Optimization>
       <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
       <OmitFramePointers>true</OmitFramePointers>
-      <AdditionalIncludeDirectories>..;..\..\..\scribus;..\..\..\scribus\ui;$(QT5_DIR)\include\QtCore;$(QT5_DIR)\include\QtGui;$(QT5_DIR)\include\QtNetwork;$(QT5_DIR)\include\QtWidgets;$(QT5_DIR)\include\QtWebKit;$(QT5_DIR)\include\QtWebKitWidgets;$(QT5_DIR)\include\QtXml;$(QT5_DIR)\include;$(CAIRO_INCLUDE_DIR);$(FREETYPE_INCLUDE_DIR);$(ICU_INCLUDE_DIR);$(LCMS_INCLUDE_DIR);$(LIBJPEG_INCLUDE_DIR);$(LIBTIFF_INCLUDE_DIR);$(PYTHON_INCLUDE_DIR);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>..;..\..\..\scribus;..\..\..\scribus\ui;$(QT5_DIR)\include\QtCore;$(QT5_DIR)\include\QtGui;$(QT5_DIR)\include\QtNetwork;$(QT5_DIR)\include\QtWidgets;$(QT5_DIR)\include\QtWebKit;$(QT5_DIR)\include\QtWebKitWidgets;$(QT5_DIR)\include\QtXml;$(QT5_DIR)\include;$(CAIRO_INCLUDE_DIR);$(FREETYPE_INCLUDE_DIR);$(ICU_INCLUDE_DIR);$(LCMS_INCLUDE_DIR);$(LIBJPEG_INCLUDE_DIR);$(LIBTIFF_INCLUDE_DIR);$(PYTHON3_INCLUDE_DIR);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>WIN32;NDEBUG;_USE_MATH_DEFINES;_USRDLL;_WINDOWS;QT_DLL;QT_GUI_LIB;QT_CORE_LIB;QT_THREAD_SUPPORT;COMPILE_PLUGIN_AS_DLL;AVOID_WIN32_FILEIO;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>true</StringPooling>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
@@ -192,8 +192,8 @@
       <ForcedIncludeFiles>plugins_pch.h;%(ForcedIncludeFiles)</ForcedIncludeFiles>
     </ClCompile>
     <Link>
-      <AdditionalDependencies>$(QT5CORE_LIB);$(QT5GUI_LIB);$(QT5WIDGETS_LIB);$(QT5XML_LIB);$(FREETYPE_LIB);$(LIBJPEG_LIB);$(LIBTIFF_LIB);$(LCMS_LIB);$(PYTHON_LIB);scribus-api.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(LCMS_LIB_DIR);$(FREETYPE_LIB_DIR);$(LIBJPEG_LIB_DIR);$(LIBTIFF_LIB_DIR);$(PYTHON_LIB_DIR)s;$(QT5_DIR)\lib;$(OutDir)..;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalDependencies>$(QT5CORE_LIB);$(QT5GUI_LIB);$(QT5WIDGETS_LIB);$(QT5XML_LIB);$(FREETYPE_LIB);$(LIBJPEG_LIB);$(LIBTIFF_LIB);$(LCMS_LIB);$(PYTHON3_LIB);scribus-api.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalLibraryDirectories>$(LCMS_LIB_DIR);$(FREETYPE_LIB_DIR);$(LIBJPEG_LIB_DIR);$(LIBTIFF_LIB_DIR);$(PYTHON3_LIB_DIR)s;$(QT5_DIR)\lib;$(OutDir)..;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
15030_python3_jghali-2.patch (156,550 bytes)   

jghali

2019-10-27 13:21

administrator   ~0046862

Patch has now been applied to trunk. The scripts stored in the scriptplugin\samples and scriptplugin\scripts directories are now working. I also did some updates to the documentation and AppImage script.

Issue History

Date Modified Username Field Change
2017-10-25 22:29 u ltd. New Issue
2017-10-25 22:29 u ltd. File Added: python3.patch
2017-10-25 22:29 u ltd. File Added: Sample_script_result.png
2017-10-26 07:04 ale Note Added: 0044589
2017-10-26 07:40 u ltd. Note Added: 0044591
2017-10-26 07:45 u ltd. File Added: test.script
2017-10-26 07:45 u ltd. File Added: test.script.result
2017-10-26 07:45 u ltd. Note Added: 0044592
2017-11-19 22:37 u ltd. Note Added: 0044633
2017-11-19 22:53 u ltd. File Added: Scribus--Kursives_A.png
2017-11-19 22:53 u ltd. Note Added: 0044634
2017-11-28 21:49 JLuc Patch => Yes
2017-12-07 10:32 u ltd. Note Added: 0044719
2017-12-07 14:27 ale Note Added: 0044720
2017-12-07 15:14 u ltd. Note Added: 0044723
2018-01-05 04:08 william File Added: scribus-python3-20180104-200311.pat
2018-01-05 04:08 william File Added: pyqt_tutl2.py
2018-01-05 04:08 william File Added: build-scribus-dw0-p3.sh
2018-01-05 04:08 william Note Added: 0044810
2018-01-05 19:20 william Note Added: 0044812
2018-01-05 22:12 william File Added: scribus-python3-20180105-220717.pat
2018-01-05 22:12 william Note Added: 0044814
2018-01-07 01:32 jghali Note Added: 0044818
2018-01-07 01:34 jghali Note Edited: 0044818
2018-01-07 02:04 jghali Note Edited: 0044818
2018-01-07 03:25 william Note Added: 0044819
2018-01-28 02:17 u ltd. File Added: don_t_call_initscribus.png
2018-01-28 02:17 u ltd. Note Added: 0044878
2018-01-28 02:44 u ltd. Note Added: 0044879
2018-01-28 02:46 u ltd. Note Added: 0044880
2018-01-28 05:31 william Note Added: 0044881
2018-02-05 11:56 JLuc Note Edited: 0044810
2018-02-06 04:19 william Note Added: 0044922
2018-02-06 07:37 u ltd. File Added: scribus-20180205-095552-jonas-scripterpart.patch
2018-02-06 07:37 u ltd. Note Added: 0044924
2018-02-07 21:01 william Note Added: 0044944
2018-02-08 08:23 u ltd. Note Added: 0044945
2018-02-08 16:52 william File Added: show-commands.py
2018-02-08 16:52 william File Added: scribus-dir.py
2018-02-08 16:52 william File Added: export_to_pdf.py
2018-02-08 16:52 william File Added: scribus-dir-from-inside-scribus.txt
2018-02-08 16:52 william File Added: scribus-dir-from-command-line.txt
2018-02-08 16:52 william Note Added: 0044948
2018-02-24 21:29 william Note Added: 0044981
2018-03-24 08:35 u ltd. Note Added: 0045086
2018-11-05 15:03 HJarausch Note Added: 0045576
2019-08-03 08:28 cbradney Note Added: 0046427
2019-08-03 23:09 william Note Added: 0046429
2019-08-07 14:31 Archange Note Added: 0046447
2019-08-07 15:32 william Note Added: 0046448
2019-10-23 09:52 jghali File Added: 15030_python3_jghali.patch
2019-10-23 09:52 jghali Note Added: 0046839
2019-10-23 17:02 cbradney Note Added: 0046842
2019-10-23 19:53 william Note Added: 0046844
2019-10-24 13:44 jghali File Added: 15030_python3_jghali-2.patch
2019-10-24 13:44 jghali Note Added: 0046852
2019-10-27 13:05 jghali Summary Python 3 scripter update => Port scripter to Python 3
2019-10-27 13:21 jghali Assigned To => jghali
2019-10-27 13:21 jghali Status new => resolved
2019-10-27 13:21 jghali Resolution open => fixed
2019-10-27 13:21 jghali Fixed in Version => 1.5.6.svn
2019-10-27 13:21 jghali Note Added: 0046862
2019-12-08 21:24 cbradney Status resolved => closed