Skip to content

Commit

Permalink
Python MapScript updates for 8.2 Release (#7059)
Browse files Browse the repository at this point in the history
* Bump Python versions for CI

* Use string for 3.10

* Update SWIG version

* Switch to venv and use pip for install

* Update README and remove Python 2.7 references

* Switch back to virtualenv as venv is missing in Ubuntu CI. Use build for wheels rather than setup.py install

* Add docstrings to shadow functions
  • Loading branch information
geographika committed Apr 1, 2024
1 parent 5a943d5 commit 6508d1d
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 35 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build-mapscript-python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
runs-on: ubuntu-20.04
strategy:
matrix:
python-version: [3.8, 3.9]
python-version: [3.8, 3.9, "3.10", 3.11, 3.12]
env:
MAPSCRIPT_PYTHON_ONLY: 'true'

Expand Down
6 changes: 3 additions & 3 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,14 @@ cache:
environment:

global:
SWIG_VER: swigwin-4.1.0
SWIG_VER: swigwin-4.2.1
TWINE_USERNAME: mapserver
TWINE_PASSWORD:
secure: mHoJHeXdXbBNoDf7MA4ZEg==

# VS 2019
VS_VERSION: Visual Studio 16 2019
matrix:
- platform: x64
Python_ROOT_DIR: c:/python37-x64
- platform: x64
Python_ROOT_DIR: c:/python38-x64
- platform: x64
Expand All @@ -29,6 +27,8 @@ environment:
Python_ROOT_DIR: c:/python310-x64
- platform: x64
Python_ROOT_DIR: c:/python311-x64
- platform: x64
Python_ROOT_DIR: c:/python312-x64

matrix:
fast_finish: true
Expand Down
10 changes: 5 additions & 5 deletions src/mapscript/python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ add_custom_command(
DEPENDS mapscriptvenv.stamp
OUTPUT mapscriptwheel.stamp
WORKING_DIRECTORY ${OUTPUT_FOLDER}
COMMAND ${Python_VENV_SCRIPTS}/python setup.py bdist_wheel > wheel_build.log
COMMAND ${Python_VENV_SCRIPTS}/python -m build --wheel > wheel_build.log
COMMENT "Building the mapscript Python wheel"
)

Expand Down Expand Up @@ -108,21 +108,21 @@ add_custom_command(
COMMENT "Copying files required to build Mapscript"
)

install(
install(
CODE "
SET(ENV{PYTHONPATH} \${Python_SITELIB}:\$ENV{PYTHONPATH})
if(DEFINED ENV{DESTDIR})
SET(PYTHON_ROOT \"--root=\$ENV{DESTDIR}\")
endif()
if(DEFINED CMAKE_INSTALL_PREFIX)
SET(PYTHON_PREFIX \"--prefix=\${CMAKE_INSTALL_PREFIX}\")
endif()
execute_process(
COMMAND ${Python_EXECUTABLE} setup.py install \${PYTHON_ROOT} \${PYTHON_PREFIX}
COMMAND ${Python_EXECUTABLE} -m pip install \${PYTHON_ROOT} \${PYTHON_PREFIX}
WORKING_DIRECTORY ${OUTPUT_FOLDER}
)
"
Expand Down
42 changes: 23 additions & 19 deletions src/mapscript/python/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ Python MapScript for MapServer README
=====================================

:Author: MapServer Team
:Last Updated: 2021-01-29
:Last Updated: 2024-03-29

Introduction
------------

The Python mapscript module provides users an interface to `MapServer <http://mapserver.org>`_
classes on any platform, and has been tested on Python versions 2.7 and 3.5+.
classes on any platform, and has been tested on Python 3.8+.

The Python mapscript module is created using `SWIG <http://www.swig.org.>`_ the
the Simplified Wrapper and Interface Generator. This is used to create MapServer bindings in
Expand Down Expand Up @@ -38,13 +38,13 @@ Advantages of ready-made wheels on PyPI include:
Wheels are built based on the `Appveyor build environments <https://github.com/MapServer/MapServer/blob/main/appveyor.yml>`_.
These are as follows at the time of writing:

+ Python 2.7 x32
+ Python 2.7 x64
+ Python 3.6 x64
+ Python 3.7 x64
+ Python 3.8 x64
+ Python 3.9 x64
+ Python 3.10 x64
+ Python 3.11 x64
+ Python 3.12 x64

The mapscript wheels have been compiled using Visual Studio 2017 version 15 (``MSVC++ 14.11 _MSC_VER == 1911``).
The mapscript wheels have been compiled using Visual Studio 2022 version 17 (``MSVC++ 17.9 _MSC_VER == 1939``).
Linux Wheels may also be available in the future using the `manylinux <https://github.com/pypa/manylinux>`_ project.

No source distributions will be provided on PyPI - to build from source requires the full MapServer source code,
Expand Down Expand Up @@ -79,6 +79,12 @@ If several folders are required (e.g. GDAL DLLs) multiple paths can be provided
SET MAPSERVER_DLL_PATH=C:\MapServer\bin;C:\GDAL\bin
In PowerShell you can set this as follows:

.. code-block:: ps1
$env:MAPSERVER_DLL_PATH="C:\MapServer\bin"
For Earlier Python Versions
+++++++++++++++++++++++++++

Expand All @@ -93,14 +99,14 @@ Windows Binaries
++++++++++++++++

Windows binary packages can be downloaded from `GIS Internals <https://www.gisinternals.com/stable.php>`_.
To ensure compatibility with the wheels, please use identical release packages, e.g. ``release-1928-x64-gdal-3-2-mapserver-7-6``
for mapscript 7.6.
To ensure compatibility with the wheels, please use identical release packages, e.g. ``release-1930-x64-gdal-3-8-4-mapserver-8-0-1``
for mapscript 8.0.1.

.. NOTE::
`MS4W <https://www.ms4w.com>`_ (MapServer for Windows) is a full installer that contains Python & Python
MapScript already configured out-of-the-box, as well as default OGC web services and over 60 working mapfiles.

When using these packages the MapServer path will be similar to ``C:\release-1911-x64-gdal-2-3-mapserver-7-2\bin``.
When using these packages the MapServer path will be similar to ``C:\release-1930-x64-gdal-3-8-4-mapserver-8-0-1\bin``.

Prior to installing mapscript it is recommended to update pip to the latest version with the following command:

Expand All @@ -125,17 +131,17 @@ Now you should be able to import mapscript:
.. code-block:: python
python -c "import mapscript;print(mapscript.msGetVersion())"
MapServer version 7.6.0 OUTPUT=PNG OUTPUT=JPEG OUTPUT=KML SUPPORTS=PROJ SUPPORTS=AGG SUPPORTS=FREETYPE SUPPORTS=CAIRO SUPPORTS=SVG_SYMBOLS SUPPORTS=SVGCAIRO SUPPORTS=ICONV SUPPORTS=FRIBIDI SUPPORTS=WMS_SERVER SUPPORTS=WMS_CLIENT SUPPORTS=WFS_SERVER SUPPORTS=WFS_CLIENT SUPPORTS=WCS_SERVER SUPPORTS=SOS_SERVER SUPPORTS=FASTCGI SUPPORTS=THREADS SUPPORTS=GEOS SUPPORTS=PBF INPUT=JPEG INPUT=POSTGIS INPUT=OGR INPUT=GDAL INPUT=SHAPEFILE
MapServer version 8.0.1 PROJ version 9.3 GDAL version 3.9 OUTPUT=PNG OUTPUT=JPEG SUPPORTS=PROJ SUPPORTS=AGG SUPPORTS=FREETYPE SUPPORTS=CAIRO SUPPORTS=SVG_SYMBOLS SUPPORTS=SVGCAIRO SUPPORTS=ICONV SUPPORTS=FRIBIDI SUPPORTS=WMS_SERVER SUPPORTS=WMS_CLIENT SUPPORTS=WFS_SERVER SUPPORTS=WFS_CLIENT SUPPORTS=WCS_SERVER SUPPORTS=OGCAPI_SERVER SUPPORTS=FASTCGI SUPPORTS=THREADS SUPPORTS=GEOS SUPPORTS=PBF INPUT=JPEG INPUT=POSTGIS INPUT=OGR INPUT=GDAL INPUT=SHAPEFILE INPUT=FLATGEOBUF
Installation on Unix
--------------------

For Unix users there are two approaches to installing mapscript. The first is to install the ``python-mapscript`` package using a package manager. For example on
For Unix users there are two approaches to installing mapscript. The first is to install the ``python3-mapscript`` package using a package manager. For example on
Ubuntu the following command can be used:

.. code-block:: bat
sudo apt-get install python-mapscript
sudo apt-get install python3-mapscript
The second approach is to build and install the Python mapscript module from source. Full details on compiling MapServer from source are detailed on the
`Compiling on Unix <https://www.mapserver.org/installation/unix.html>`_ page. To make sure Python mapscript is built alongside MapServer the following flag needs to be set:
Expand Down Expand Up @@ -175,7 +181,6 @@ If the mapscript library is not on your ``PYTHONPATH`` you may see one of the fo

.. code-block:: python
ImportError: No module named _mapscript # Python 2.x
ModuleNotFoundError: No module named '_mapscript' # Python 3.x
If the ``MapServer.dll`` cannot be found in your system paths (or ``MAPSERVER_DLL_PATH`` environment variable when using Python 3.8
Expand Down Expand Up @@ -257,8 +262,7 @@ suite. This process runs commands similar to the following:

.. code-block:: bat
python -m pip install virtualenv
virtualenv mapscriptvenv
python -m venv mapscriptvenv
python -m pip install --upgrade pip
pip install -r requirements-dev.txt
python setup.py bdist_wheel
Expand Down Expand Up @@ -291,12 +295,12 @@ The mapscript module includes a test suite and a small sample dataset to check t
pip install pytest
Make sure the MapServer binaries are on the system path, and that the PROJ_LIB variable has been set as this is required for many of the tests.
Make sure the MapServer binaries are on the system path, and that the PROJ_DATA variable has been set as this is required for many of the tests.

.. code-block:: bat
SET PATH=C:\release-1928-x64-gdal-3-2-mapserver-7-6\bin;%PATH%
SET PROJ_LIB=C:\release-1928-x64-gdal-3-2-mapserver-7-6\bin\proj\SHARE
SET PATH=C:\release-1930-x64-gdal-3-8-4-mapserver-8-0-1\bin;%PATH%
SET PROJ_DATA=C:\release-1930-x64-gdal-3-8-4-mapserver-8-0-1\bin\proj\SHARE
Finally run the command below to run the test suite:

Expand Down
20 changes: 20 additions & 0 deletions src/mapscript/python/pymodule.i
Original file line number Diff line number Diff line change
Expand Up @@ -271,12 +271,21 @@ MapServerChildError = _mapscript.MapServerChildError

%feature("shadow") insertClass %{
def insertClass(*args):
"""
Insert a **copy** of the class into the layer at the requested *index*.
Default index of -1 means insertion at the end of the array of classes. Returns the index at which the class was inserted.
"""
actualIndex=$action(*args)
args[1].p_layer=args[0]
return actualIndex%}


%feature("shadow") getClass %{
def getClass(*args):
"""
Fetch the requested class object at *i*. Returns NULL if the class index is out of the legal range.
The numclasses field contains the number of classes available, and the first class is index 0.
"""
clazz = $action(*args)
if clazz:
if args and len(args)!=0:
Expand All @@ -287,12 +296,20 @@ MapServerChildError = _mapscript.MapServerChildError

%feature("shadow") insertLayer %{
def insertLayer(*args):
"""
Insert a copy of *layer* into the map at *index*.
The default value of *index* is -1, which means the last possible index.
Returns the index of the new layer, or -1 in the case of a failure.
"""
actualIndex=$action(*args)
args[1].p_map=args[0]
return actualIndex%}

%feature("shadow") getLayer %{
def getLayer(*args):
"""
Returns a reference to the layer at index *i*.
"""
layer = $action(*args)
if layer:
if args and len(args)!=0:
Expand All @@ -303,6 +320,9 @@ MapServerChildError = _mapscript.MapServerChildError

%feature("shadow") getLayerByName %{
def getLayerByName(*args):
"""
Returns a reference to the named layer.
"""
layer = $action(*args)
if layer:
if args and len(args)!=0:
Expand Down
3 changes: 2 additions & 1 deletion src/mapscript/python/requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pytest
pillow
wheel>=0.38.0
setuptools>=45.0.0
setuptools>=45.0.0
build[virtualenv]
1 change: 0 additions & 1 deletion src/mapscript/python/setup.py.in
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ setup(
'Intended Audience :: Science/Research',
'License :: OSI Approved :: MIT License',
'Operating System :: OS Independent',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: C',
'Programming Language :: C++',
Expand Down
10 changes: 5 additions & 5 deletions src/mapscript/swiginc/layer.i
Original file line number Diff line number Diff line change
Expand Up @@ -314,12 +314,12 @@
/// The numclasses field contains the number of classes available, and the first class is index 0.
classObj *getClass(int i)
{
classObj *result=NULL;
classObj *result=NULL;
if (i >= 0 && i < self->numclasses) {
result=self->class[i];
MS_REFCNT_INCR(result);
}
return result;
result=self->class[i];
MS_REFCNT_INCR(result);
}
return result;
}

/// Returns the requested item. Items are attribute fields, and this method returns the
Expand Down

0 comments on commit 6508d1d

Please sign in to comment.