Skip to content

Commit

Permalink
Refactor and fixes Python binding
Browse files Browse the repository at this point in the history
Python binding was broke since commit b1f37a8.
This is a fix and to some degree a refactor.
The binding build is now integrated. Controlled by the CMake
QTERMWIDGET_BUILD_PYTHON_BINDING option.

CMake components taken from https://cgit.kde.org/pykde5.git/. No need to
reinvent the wheel.

Closes #135.
  • Loading branch information
luis-pereira authored and agaida committed Apr 29, 2018
1 parent 4cc05f9 commit 3ba895f
Show file tree
Hide file tree
Showing 17 changed files with 537 additions and 226 deletions.
7 changes: 7 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ set(LXQTBT_MINIMUM_VERSION "0.4.1")
option(UPDATE_TRANSLATIONS "Update source translation translations/*.ts files" OFF)
option(BUILD_EXAMPLE "Build example application. Default OFF." OFF)
option(QTERMWIDGET_USE_UTEMPTER "Uses the libutempter library. Mainly for FreeBSD" OFF)
option(QTERMWIDGET_BUILD_PYTHON_BINDING "Build python binding" OFF)

# just change version for releases
set(QTERMWIDGET_VERSION_MAJOR "0")
Expand Down Expand Up @@ -304,6 +305,12 @@ if(BUILD_EXAMPLE)
endif()
# end of example application

# python binding
if (QTERMWIDGET_BUILD_PYTHON_BINDING)
add_subdirectory(pyqt)
endif()
# end of python binding


CONFIGURE_FILE(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in"
Expand Down
61 changes: 61 additions & 0 deletions pyqt/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)

# Match what's used in the main macros
cmake_policy(SET CMP0002 OLD)
find_package(PythonLibrary)

include(PythonMacros)

find_package(SIP)
include(SIPMacros)

if(SIP_VERSION STRLESS "040f03") # These version numbers also appear in ../CMakeLists.txt
message(FATAL_ERROR "The version of SIP found is too old. 4.15.3 or later is needed.")
endif()

find_package(PyQt5)
if(PYQT5_VERSION STRLESS "050101") # These version numbers also appear in ../CMakeLists.txt
message(FATAL_ERROR "The version of PyQt found is too old. 5.1.1 or later is required.")
endif()

set(SIP_INCLUDES ${PYQT5_SIP_DIR} sip)
set(SIP_CONCAT_PARTS 8)
set(SIP_TAGS ALL WS_X11 ${PYQT5_VERSION_TAG})
set(SIP_DISABLE_FEATURES VendorID PyQt_NoPrintRangeBug)

# Use an extra option when compiling on Python 3.
if (PYTHON_VERSION_MAJOR GREATER 2)
if(PYQT5_VERSION STRGREATER "040904")
# Disable for newer PyQt
set(SIP_EXTRA_OPTIONS -P -g)
else ()
set(SIP_EXTRA_OPTIONS -g)
endif()
else (PYTHON_VERSION_MAJOR GREATER 2)
if(PYQT5_VERSION STRGREATER "040904")
# Disable for newer PyQt
set(SIP_EXTRA_OPTIONS -P -g -x Py_v3)
else ()
set(SIP_EXTRA_OPTIONS -g -x Py_v3)
endif()
endif ()

include_directories(
"${SIP_INCLUDE_DIR}"
)

add_definitions(-D_REENTRANT -DSIP_PROTECTED_IS_PUBLIC -Dprotected=public)

file(GLOB qtermwidget_files_sip sip/*.sip)
set(SIP_EXTRA_FILES_DEPEND "${qtermwidget_files_sip}")
add_sip_python_module(QTermWidget sip/qtermwidget.sip qtermwidget5)

python_install(__init__.py "${PYTHON_SITE_PACKAGES_INSTALL_DIR}/PyQt5/qtermwidget")

set (SIP_FILES_INSTALL_DIR "${CMAKE_INSTALL_DATAROOTDIR}/sip")

install(DIRECTORY sip/ DESTINATION "${SIP_FILES_INSTALL_DIR}/PyQt5/qtermwidget"
PATTERN "*~" EXCLUDE # This sucks, why can't I just whitelist what I _do_ want?
PATTERN ".svn" EXCLUDE
PATTERN "*.in" EXCLUDE
)
36 changes: 0 additions & 36 deletions pyqt/README.md

This file was deleted.

File renamed without changes.
22 changes: 22 additions & 0 deletions pyqt/cmake/COPYING-CMAKE-SCRIPTS
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

1. Redistributions of source code must retain the copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
53 changes: 53 additions & 0 deletions pyqt/cmake/FindPyQt5.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Find PyQt5
# ~~~~~~~~~~
# Copyright (c) 2014, Simon Edwards <[email protected]>
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
# PyQt5 website: http://www.riverbankcomputing.co.uk/pyqt/index.php
#
# Find the installed version of PyQt5. FindPyQt5 should only be called after
# Python has been found.
#
# This file defines the following variables:
#
# PYQT5_VERSION - The version of PyQt5 found expressed as a 6 digit hex number
# suitable for comparison as a string
#
# PYQT5_VERSION_STR - The version of PyQt5 as a human readable string.
#
# PYQT5_VERSION_TAG - The PyQt version tag using by PyQt's sip files.
#
# PYQT5_SIP_DIR - The directory holding the PyQt5 .sip files.
#
# PYQT5_SIP_FLAGS - The SIP flags used to build PyQt.

IF(EXISTS PYQT5_VERSION)
# Already in cache, be silent
SET(PYQT5_FOUND TRUE)
ELSE(EXISTS PYQT5_VERSION)

FIND_FILE(_find_pyqt5_py FindPyQt5.py PATHS ${CMAKE_MODULE_PATH})

EXECUTE_PROCESS(COMMAND ${PYTHON_EXECUTABLE} ${_find_pyqt5_py} OUTPUT_VARIABLE pyqt5_config)
IF(pyqt5_config)
STRING(REGEX REPLACE "^pyqt_version:([^\n]+).*$" "\\1" PYQT5_VERSION ${pyqt5_config})
STRING(REGEX REPLACE ".*\npyqt_version_str:([^\n]+).*$" "\\1" PYQT5_VERSION_STR ${pyqt5_config})
STRING(REGEX REPLACE ".*\npyqt_version_tag:([^\n]+).*$" "\\1" PYQT5_VERSION_TAG ${pyqt5_config})
STRING(REGEX REPLACE ".*\npyqt_sip_dir:([^\n]+).*$" "\\1" PYQT5_SIP_DIR ${pyqt5_config})
STRING(REGEX REPLACE ".*\npyqt_sip_flags:([^\n]+).*$" "\\1" PYQT5_SIP_FLAGS ${pyqt5_config})

SET(PYQT5_FOUND TRUE)
ENDIF(pyqt5_config)

IF(PYQT5_FOUND)
IF(NOT PYQT5_FIND_QUIETLY)
MESSAGE(STATUS "Found PyQt5 version: ${PYQT5_VERSION_STR}")
ENDIF(NOT PYQT5_FIND_QUIETLY)
ELSE(PYQT5_FOUND)
IF(PYQT5_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find PyQt5.")
ENDIF(PYQT5_FIND_REQUIRED)
ENDIF(PYQT5_FOUND)

ENDIF(EXISTS PYQT5_VERSION)
28 changes: 28 additions & 0 deletions pyqt/cmake/FindPyQt5.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Copyright (c) 2014, Simon Edwards <[email protected]>
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.

import PyQt5.Qt
import sys
import os.path

print("pyqt_version:%06.0x" % PyQt5.Qt.PYQT_VERSION)
print("pyqt_version_str:%s" % PyQt5.Qt.PYQT_VERSION_STR)

pyqt_version_tag = ""
in_t = False
for item in PyQt5.Qt.PYQT_CONFIGURATION["sip_flags"].split(' '):
if item=="-t":
in_t = True
elif in_t:
if item.startswith("Qt_5"):
pyqt_version_tag = item
else:
in_t = False
print("pyqt_version_tag:%s" % pyqt_version_tag)

# FIXME This next line is just a little bit too crude.
pyqt_sip_dir = os.path.join(sys.prefix, "share", "sip", "PyQt5")
print("pyqt_sip_dir:%s" % pyqt_sip_dir)

print("pyqt_sip_flags:%s" % PyQt5.Qt.PYQT_CONFIGURATION["sip_flags"])
73 changes: 73 additions & 0 deletions pyqt/cmake/FindPythonLibrary.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Find Python
# ~~~~~~~~~~~
# Find the Python interpreter and related Python directories.
#
# This file defines the following variables:
#
# PYTHON_EXECUTABLE - The path and filename of the Python interpreter.
#
# PYTHON_SHORT_VERSION - The version of the Python interpreter found,
# excluding the patch version number. (e.g. 2.5 and not 2.5.1))
#
# PYTHON_LONG_VERSION - The version of the Python interpreter found as a human
# readable string.
#
# PYTHON_SITE_PACKAGES_INSTALL_DIR - this cache variable can be used for installing
# own python modules. You may want to adjust this to be the
# same as ${PYTHON_SITE_PACKAGES_DIR}, but then admin
# privileges may be required for installation.
#
# PYTHON_SITE_PACKAGES_DIR - Location of the Python site-packages directory.
#
# PYTHON_INCLUDE_PATH - Directory holding the python.h include file.
#
# PYTHON_LIBRARY, PYTHON_LIBRARIES- Location of the Python library.

# Copyright (c) 2007, Simon Edwards <[email protected]>
# Copyright (c) 2012, Luca Beltrame <[email protected]>
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.

include(FindPackageHandleStandardArgs)

find_package(PythonInterp)

if (PYTHONINTERP_FOUND)

option(INSTALL_PYTHON_FILES_IN_PYTHON_PREFIX "Install the Python files in the Python packages dir" FALSE)

# Set the Python libraries to what we actually found for interpreters
set(Python_ADDITIONAL_VERSIONS "${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}")
# These are kept for compatibility
set(PYTHON_SHORT_VERSION "${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}")
set(PYTHON_LONG_VERSION ${PYTHON_VERSION_STRING})

find_package(PythonLibs QUIET)

if(PYTHONLIBS_FOUND)
set(PYTHON_LIBRARY ${PYTHON_LIBRARIES})
endif(PYTHONLIBS_FOUND)

# Auto detect Python site-packages directory
execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib(True))"
OUTPUT_VARIABLE PYTHON_SITE_PACKAGES_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE
)

message(STATUS "Python system site-packages directory: ${PYTHON_SITE_PACKAGES_DIR}")
if(INSTALL_PYTHON_FILES_IN_PYTHON_PREFIX)
set(PYTHON_SITE_PACKAGES_INSTALL_DIR ${PYTHON_SITE_PACKAGES_DIR})
else()
execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib(True, prefix='${CMAKE_INSTALL_PREFIX}'))"
OUTPUT_VARIABLE PYTHON_SITE_PACKAGES_INSTALL_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE
)
endif()

if(NOT PYTHON_SITE_PACKAGES_INSTALL_DIR STREQUAL PYTHON_SITE_PACKAGES_DIR)
message(STATUS "The Python files will be installed to ${PYTHON_SITE_PACKAGES_INSTALL_DIR}. Make sure to add them to the Python search path (e.g. by setting PYTHONPATH)")
endif()

endif(PYTHONINTERP_FOUND)

find_package_handle_standard_args(PythonLibrary DEFAULT_MSG PYTHON_LIBRARY)
64 changes: 64 additions & 0 deletions pyqt/cmake/FindSIP.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Find SIP
# ~~~~~~~~
#
# SIP website: http://www.riverbankcomputing.co.uk/sip/index.php
#
# Find the installed version of SIP. FindSIP should be called after Python
# has been found.
#
# This file defines the following variables:
#
# SIP_VERSION - The version of SIP found expressed as a 6 digit hex number
# suitable for comparison as a string.
#
# SIP_VERSION_STR - The version of SIP found as a human readable string.
#
# SIP_EXECUTABLE - Path and filename of the SIP command line executable.
#
# SIP_INCLUDE_DIR - Directory holding the SIP C++ header file.
#
# SIP_DEFAULT_SIP_DIR - Default directory where .sip files should be installed
# into.

# Copyright (c) 2007, Simon Edwards <[email protected]>
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.



IF(SIP_VERSION)
# Already in cache, be silent
SET(SIP_FOUND TRUE)
ELSE(SIP_VERSION)

FIND_FILE(_find_sip_py FindSIP.py PATHS ${CMAKE_MODULE_PATH})

EXECUTE_PROCESS(COMMAND ${PYTHON_EXECUTABLE} ${_find_sip_py} OUTPUT_VARIABLE sip_config)
IF(sip_config)
STRING(REGEX REPLACE "^sip_version:([^\n]+).*$" "\\1" SIP_VERSION ${sip_config})
STRING(REGEX REPLACE ".*\nsip_version_str:([^\n]+).*$" "\\1" SIP_VERSION_STR ${sip_config})
STRING(REGEX REPLACE ".*\nsip_bin:([^\n]+).*$" "\\1" SIP_EXECUTABLE ${sip_config})
IF(NOT SIP_DEFAULT_SIP_DIR)
STRING(REGEX REPLACE ".*\ndefault_sip_dir:([^\n]+).*$" "\\1" SIP_DEFAULT_SIP_DIR ${sip_config})
ENDIF(NOT SIP_DEFAULT_SIP_DIR)
STRING(REGEX REPLACE ".*\nsip_inc_dir:([^\n]+).*$" "\\1" SIP_INCLUDE_DIR ${sip_config})
FILE(TO_CMAKE_PATH ${SIP_DEFAULT_SIP_DIR} SIP_DEFAULT_SIP_DIR)
FILE(TO_CMAKE_PATH ${SIP_INCLUDE_DIR} SIP_INCLUDE_DIR)
IF(EXISTS ${SIP_EXECUTABLE})
SET(SIP_FOUND TRUE)
ELSE()
MESSAGE(STATUS "Found SIP configuration but the sip executable could not be found.")
ENDIF()
ENDIF(sip_config)

IF(SIP_FOUND)
IF(NOT SIP_FIND_QUIETLY)
MESSAGE(STATUS "Found SIP version: ${SIP_VERSION_STR}")
ENDIF(NOT SIP_FIND_QUIETLY)
ELSE(SIP_FOUND)
IF(SIP_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find SIP")
ENDIF(SIP_FIND_REQUIRED)
ENDIF(SIP_FOUND)

ENDIF(SIP_VERSION)
15 changes: 15 additions & 0 deletions pyqt/cmake/FindSIP.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# FindSIP.py
#
# Copyright (c) 2007, Simon Edwards <[email protected]>
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.

import sys
import sipconfig

sipcfg = sipconfig.Configuration()
print("sip_version:%06.0x" % sipcfg.sip_version)
print("sip_version_str:%s" % sipcfg.sip_version_str)
print("sip_bin:%s" % sipcfg.sip_bin)
print("default_sip_dir:%s" % sipcfg.default_sip_dir)
print("sip_inc_dir:%s" % sipcfg.sip_inc_dir)
4 changes: 4 additions & 0 deletions pyqt/cmake/PythonCompile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# By Simon Edwards <[email protected]>
# This file is in the public domain.
import py_compile, sys
sys.exit(py_compile.main())
Loading

0 comments on commit 3ba895f

Please sign in to comment.