[Git][debian-gis-team/mapproxy][upstream] New upstream version 6.1.1+dfsg
Bas Couwenberg (@sebastic)
gitlab at salsa.debian.org
Wed Jun 17 14:35:31 BST 2026
Bas Couwenberg pushed to branch upstream at Debian GIS Project / mapproxy
Commits:
a4406513 by Bas Couwenberg at 2026-06-17T15:21:06+02:00
New upstream version 6.1.1+dfsg
- - - - -
19 changed files:
- .github/workflows/post-comment.yml
- .github/workflows/test.yml
- .gitignore
- CHANGES.txt
- mapproxy/config/configuration/proxy.py
- mapproxy/image/__init__.py
- mapproxy/service/demo.py
- mapproxy/service/ogcapi/api.py
- mapproxy/service/ogcapi/server.py
- mapproxy/service/templates/ogcapi/_base.html
- mapproxy/service/templates/ogcapi/collections/collection.html
- mapproxy/service/templates/ogcapi/landing_page.html
- mapproxy/service/templates/ogcapi/openapi/redoc.html
- mapproxy/service/templates/ogcapi/openapi/swagger.html
- mapproxy/service/templates/ogcapi/tilesets/tileset.html
- mapproxy/test/unit/test_conf_loader.py
- mapproxy/test/unit/test_image.py
- requirements-tests.txt
- setup.py
Changes:
=====================================
.github/workflows/post-comment.yml
=====================================
@@ -15,7 +15,7 @@ jobs:
pull-requests: write
steps:
- name: Download artifact
- uses: actions/download-artifact at v4
+ uses: actions/download-artifact at v8
with:
name: coverage-report
run-id: ${{ github.event.workflow_run.id }}
=====================================
.github/workflows/test.yml
=====================================
@@ -131,7 +131,7 @@ jobs:
echo "${{ github.event.number }}" > pr_number.txt
- name: Upload Coverage Artifact
- uses: actions/upload-artifact at v4
+ uses: actions/upload-artifact at v7
if: github.event_name == 'pull_request'
with:
name: coverage-report
=====================================
.gitignore
=====================================
@@ -16,7 +16,7 @@ nosetests*.xml
.pydevproject
.tox/
/cache_data/
-
+venv/
.idea/
*.iml
.cursor/
=====================================
CHANGES.txt
=====================================
@@ -1,3 +1,18 @@
+6.1.1 2026-06-17
+~~~~~~~~~~~~~~~~
+
+Maintenance:
+
+ - Update dependencies
+
+Fixes:
+
+ - ImageResult.as_buffer will always return image mode rgba if requested
+ - Restore context manager protocol on ProxyConfiguration
+ - Fix base path for rendering OGC API HTML pages in multi mapproxy setups
+ - Fix determination of resolutions in WMTS demo
+
+
6.1.0 2026-06-03
~~~~~~~~~~~~~~~~
=====================================
mapproxy/config/configuration/proxy.py
=====================================
@@ -186,11 +186,18 @@ class ProxyConfiguration(object):
self.services = ServiceConfiguration(self.configuration.get('services', {}), context=self)
def configured_services(self):
+ with self:
+ return self.services.services()
+
+ def __enter__(self):
+ # push local base_config onto config stack
import mapproxy.config.config
mapproxy.config.config._config.push(self.base_config)
- services = self.services.services()
+
+ def __exit__(self, type, value, traceback):
+ # pop local base_config from config stack
+ import mapproxy.config.config
mapproxy.config.config._config.pop()
- return services
@property
def base_config(self):
=====================================
mapproxy/image/__init__.py
=====================================
@@ -242,7 +242,8 @@ class ImageResult(BaseImageResult):
# need actual image_opts.format for next check
self.image_opts = self.image_opts.copy()
self.image_opts.format = peek_image_format(buf)
- if self.image_opts and image_opts and self.image_opts.format != image_opts.format:
+ if self.image_opts and image_opts and (
+ self.image_opts.format != image_opts.format or self.image_opts.mode != image_opts.mode):
log.debug('converting image from %s -> %s' % (self.image_opts, image_opts))
self.image = self.as_image()
self._buf = None
@@ -419,6 +420,9 @@ def img_to_buf(img: Image.Image, image_opts, georef=None) -> BytesIO:
and 'transparency' in img.info and isinstance(img.info['transparency'], tuple)):
del img.info['transparency']
+ if image_opts.mode is not None and img.mode != image_opts.mode:
+ img = img.convert(image_opts.mode)
+
img.save(buf, format, **defaults)
buf.seek(0)
return buf
=====================================
mapproxy/service/demo.py
=====================================
@@ -352,11 +352,13 @@ class DemoServer(Server):
background_url = base_config().background.url
if self.background:
background_url = self.background["url"]
+
+ res = [wmts_layer.grid.resolutions[k] for k in list(wmts_layer.grid.resolutions)]
return template.substitute(layer=wmts_layer,
matrix_set=wmts_layer.grid.name,
format=escape_html(req.args['format']),
srs=escape_html(req.args['srs']),
- resolutions=wmts_layer.grid.resolutions,
+ resolutions=res,
units=units,
all_tile_layers=self.tile_layers,
rest_enabled=rest_enabled,
=====================================
mapproxy/service/ogcapi/api.py
=====================================
@@ -113,9 +113,13 @@ def api(server: OGCAPIServer, req: Request):
oas["info"] = info
+ server_url = cfg["server"]["url"]
+ if not req.script_url.endswith("/ogcapi"):
+ server_url = server.create_href(req, "/ogcapi")
+
oas["servers"] = [
{
- "url": cfg["server"]["url"],
+ "url": server_url,
}
]
server_description = _get(cfg, "metadata", "identification", "description")
=====================================
mapproxy/service/ogcapi/server.py
=====================================
@@ -307,6 +307,11 @@ class OGCAPIServer(Server):
headers.update(self.response_headers)
if self.is_html_req(req):
+ # Add the ogc_api_base to render the HTML response.
+ # In this case it is used in the templates to get the correct
+ # resource urls especially in multi-mapproxy setups
+ json_resp["ogc_api_base"] = self.create_href(req, "/ogcapi")
+
content = render_j2_template(
self.get_pygeoapi_config(req),
service_package.__package__,
=====================================
mapproxy/service/templates/ogcapi/_base.html
=====================================
@@ -4,13 +4,13 @@
{% if config['server']['icon'] %}
{% set icon = config['server']['icon'] %}
{% else %}
-{% set icon = config['server']['url'] + '/static/img/favicon.ico' %}
+{% set icon = data['ogc_api_base'] + '/static/img/favicon.ico' %}
{% endif %}
{% if config['server']['logo'] %}
{% set logo = config['server']['logo'] %}
{% else %}
-{% set logo = config['server']['url'] + '/static/img/logo.png' %}
+{% set logo = data['ogc_api_base'] + '/static/img/logo.png' %}
{% endif %}
<head>
@@ -21,8 +21,8 @@
<meta name="description" content="{{ config['metadata']['identification']['title'] }}">
<meta name="keywords" content="{{ config['metadata']['identification']['keywords']|join(',') }}">
<link rel="shortcut icon" href="{{ icon }}" type="image/x-icon">
- <link rel="stylesheet" href="{{ config['server']['url'] }}/static/css/bootstrap.min.css">
- <link rel="stylesheet" href="{{ config['server']['url'] }}/static/css/default.css">
+ <link rel="stylesheet" href="{{ data['ogc_api_base'] }}/static/css/bootstrap.min.css">
+ <link rel="stylesheet" href="{{ data['ogc_api_base'] }}/static/css/default.css">
<meta name="twitter:image:src" content="{% block thumb %}{% endblock %}{% if not self.thumb() %}{{ logo }}{% endif %}" />
<meta property="og:image" content="{{ self.thumb() }}{% if not self.thumb() %}{{ logo }}{% endif %}" />
<meta name="twitter:site" content="{{ config['metadata']['identification']['title'] }}" />
@@ -48,7 +48,7 @@
<div class="bg-light sticky-top border-bottom">
<div class="container">
<header class="d-flex flex-wrap align-items-center py-3 justify-content-between">
- <a href="{{ config['server']['url'] }}"
+ <a href="{{ data['ogc_api_base'] }}"
class="d-flex align-items-center mb-3 mb-md-0 text-dark text-decoration-none">
<img src="{{ logo }}"
title="{{ config['metadata']['identification']['title'] }}" style="height:40px;vertical-align: middle;" /></a>
@@ -60,7 +60,7 @@
{% endif %}
{% if config['server']['admin'] %}
<li class="nav-item">
- <a href="{{ config['server']['url'] }}/admin/config" class="nav-link" aria-current="page">{% trans %}Admin{% endtrans %}</a>
+ <a href="{{ data['ogc_api_base'] }}/admin/config" class="nav-link" aria-current="page">{% trans %}Admin{% endtrans %}</a>
</li>
{% endif %}
<!--
@@ -76,7 +76,7 @@
<div class="row">
<div class="col-sm-12">
{% block crumbs %}
- <a href="{{ config['server']['url'] }}">{% trans %}Home{% endtrans %}</a>
+ <a href="{{ data['ogc_api_base'] }}">{% trans %}Home{% endtrans %}</a>
{% endblock %}
<span style="float: inline-end">
{% set links_found = namespace(json=0, jsonld=0) %}
@@ -114,10 +114,10 @@
<footer class="sticky-bottom bg-light d-flex justify-content-center align-items-center py-3 px-3 border-top">
<div class="text-center w-100">
{% trans %}Powered by {% endtrans %}
- <a title="mapproxy" href="https://mapproxy.org/"><img src="{{ config['server']['url'] }}/static/img/logo.png" class="mx-1" title="mapproxy logo" style="height:24px;vertical-align: middle;" /> MapProxy</a>
+ <a title="mapproxy" href="https://mapproxy.org/"><img src="{{ data['ogc_api_base'] }}/static/img/logo.png" class="mx-1" title="mapproxy logo" alt="mapproxy logo" style="height:24px;vertical-align: middle;" /> MapProxy</a>
{{ version }}
<br>
- (HTML theming based on <a title="mapproxy" href="https://pygeoapi.io/"><img src="/ogcapi/static/img/pygeoapi-logo.png" class="mx-1" title="pygeoapi logo" style="height:24px;vertical-align: middle;" /></a>)
+ (HTML theming based on <a title="mapproxy" href="https://pygeoapi.io/"><img src="{{ data['ogc_api_base'] }}/static/img/pygeoapi-logo.png" class="mx-1" title="pygeoapi logo" alt="pygeoapi logo" style="height:24px;vertical-align: middle;" /></a>)
</div>
</footer>
{% block extrafoot %}
=====================================
mapproxy/service/templates/ogcapi/collections/collection.html
=====================================
@@ -9,9 +9,9 @@
{% block extrahead %}
-<script src="{{ config['server']['url'] }}/static/ol.js"></script>
-<script src="{{ config['server']['url'] }}/static/proj4.min.js"></script>
-<link rel="stylesheet" href="{{ config['server']['url'] }}/static/ol.css"/>
+<script src="{{ data['ogc_api_base'] }}/static/ol.js"></script>
+<script src="{{ data['ogc_api_base'] }}/static/proj4.min.js"></script>
+<link rel="stylesheet" href="{{ data['ogc_api_base'] }}/static/ol.css"/>
{% endblock %}
@@ -93,7 +93,7 @@ let init;
const extent = {{ data['extent'] }};
if (!ol.proj.get(srs)) {
- const projDefsUrl = "{{ config['server']['url'] }}/static/proj4defs.js";
+ const projDefsUrl = "{{ data['ogc_api_base'] }}/static/proj4defs.js";
const allDefs = await import(projDefsUrl);
const srsNum = srs.indexOf(':') > -1 ? parseInt(srs.split(':')[1]) : parseInt(srs);
if (!allDefs.defs[srsNum]) {
@@ -155,7 +155,7 @@ let init;
const storageCrs = "{{ data['storageCrs'] }}";
if (!ol.proj.get(srs)) {
- const projDefsUrl = "{{ config['server']['url'] }}/static/proj4defs.js";
+ const projDefsUrl = "{{ data['ogc_api_base'] }}/static/proj4defs.js";
const allDefs = await import(projDefsUrl);
const srsNum = srs.indexOf(':') > -1 ? parseInt(srs.split(':')[1]) : parseInt(srs);
if (!allDefs.defs[srsNum]) {
=====================================
mapproxy/service/templates/ogcapi/landing_page.html
=====================================
@@ -61,7 +61,7 @@
<section id="collections">
<h2>{% trans %}Collections{% endtrans %}</h2>
<p>
- <a href="{{ config['server']['url'] }}/collections?f=html">{% trans %}View the collections in this service{% endtrans %}</a>
+ <a href="{{ data['ogc_api_base'] }}/collections?f=html">{% trans %}View the collections in this service{% endtrans %}</a>
</p>
</section>
{% endif %}
@@ -69,7 +69,7 @@
<section id="collections">
<h2>{% trans %}SpatioTemporal Assets{% endtrans %}</h2>
<p>
- <a href="{{ config['server']['url'] }}/stac?f=html">{% trans %}View the SpatioTemporal Assets in this service{% endtrans %}</a>
+ <a href="{{ data['ogc_api_base'] }}/stac?f=html">{% trans %}View the SpatioTemporal Assets in this service{% endtrans %}</a>
</p>
</section>
{% endif %}
@@ -77,7 +77,7 @@
<section id="processes">
<h2>{% trans %}Processes{% endtrans %}</h2>
<p>
- <a href="{{ config['server']['url'] }}/processes?f=html">{% trans %}View the processes in this service{% endtrans %}</a>
+ <a href="{{ data['ogc_api_base'] }}/processes?f=html">{% trans %}View the processes in this service{% endtrans %}</a>
</p>
</section>
<section id="jobs">
@@ -90,23 +90,23 @@
<section id="openapi">
<h2>{% trans %}API Definition{% endtrans %}</h2>
<p>
- {% trans %}Documentation{% endtrans %}: <a href="{{ config['server']['url'] }}/api?f=html">{% trans %}Swagger UI{% endtrans %}</a> <a href="{{ config['server']['url'] }}/api?f=html&ui=redoc">{% trans %}ReDoc{% endtrans %}</a>
+ {% trans %}Documentation{% endtrans %}: <a href="{{ data['ogc_api_base'] }}/api?f=html">{% trans %}Swagger UI{% endtrans %}</a> | <a href="{{ data['ogc_api_base'] }}/api?f=html&ui=redoc">{% trans %}ReDoc{% endtrans %}</a>
</p>
<p>
- <a href="{{ config['server']['url'] }}/api?f=json">{% trans %}OpenAPI Document{% endtrans %}</a>
+ <a href="{{ data['ogc_api_base'] }}/api?f=json">{% trans %}OpenAPI Document{% endtrans %}</a>
</p>
</section>
<section id="conformance">
<h2>{% trans %}Conformance{% endtrans %}</h2>
<p>
- <a href="{{ config['server']['url'] }}/conformance?f=html">{% trans %}View the conformance classes of this service{% endtrans %}</a>
+ <a href="{{ data['ogc_api_base'] }}/conformance?f=html">{% trans %}View the conformance classes of this service{% endtrans %}</a>
</p>
</section>
{% if data['tile'] %}
<section id="tilematrixsets">
<h2>{% trans %}Tile Matrix Sets{% endtrans %}</h2>
<p>
- <a href="{{ config['server']['url'] }}/tileMatrixSets?f=html">{% trans %}View the Tile Matrix Sets available on this service{% endtrans %}</a>
+ <a href="{{ data['ogc_api_base'] }}/tileMatrixSets?f=html">{% trans %}View the Tile Matrix Sets available on this service{% endtrans %}</a>
</p>
</section>
{% endif %}
@@ -114,10 +114,10 @@
<section id="dataset_map">
<h2>{% trans %}Dataset maps{% endtrans %}</h2>
<p>
- <a href="{{ config['server']['url'] }}/map.png">{% trans %}Default map of the whole dataset (as PNG){% endtrans %}</a>
+ <a href="{{ data['ogc_api_base'] }}/map.png">{% trans %}Default map of the whole dataset (as PNG){% endtrans %}</a>
</p>
<p>
- <a href="{{ config['server']['url'] }}/map.jpg">{% trans %}Default map of the whole dataset (as JPEG){% endtrans %}</a>
+ <a href="{{ data['ogc_api_base'] }}/map.jpg">{% trans %}Default map of the whole dataset (as JPEG){% endtrans %}</a>
</p>
</section>
{% endif %}
@@ -125,10 +125,10 @@
<section id="dataset_tiles">
<h2>{% trans %}Dataset tilesets{% endtrans %}</h2>
<p>
- <a href="{{ config['server']['url'] }}/map/tiles?f=html">{% trans %}Default tilesets for the whole dataset (as HTML){% endtrans %}</a>
+ <a href="{{ data['ogc_api_base'] }}/map/tiles?f=html">{% trans %}Default tilesets for the whole dataset (as HTML){% endtrans %}</a>
</p>
<p>
- <a href="{{ config['server']['url'] }}/map/tiles?f=json">{% trans %}Default tilesets for the whole dataset (as JSON){% endtrans %}</a>
+ <a href="{{ data['ogc_api_base'] }}/map/tiles?f=json">{% trans %}Default tilesets for the whole dataset (as JSON){% endtrans %}</a>
</p>
</section>
{% endif %}
=====================================
mapproxy/service/templates/ogcapi/openapi/redoc.html
=====================================
@@ -4,7 +4,7 @@
<title>ReDoc - {{ config['metadata']['identification']['title'] }}</title>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1">
- <link href="{{ config['server']['url'] }}/static/fonts_montserra_roboto.css" rel="stylesheet">
+ <link href="{{ data['openapi-document-path'] }}/../static/fonts_montserra_roboto.css" rel="stylesheet">
<style>
body {
margin: 0;
@@ -14,6 +14,6 @@
</head>
<body>
<redoc spec-url='{{ data['openapi-document-path'] }}?f=json'></redoc>
- <script src="{{ config['server']['url'] }}/static/redoc.standalone.js"> </script>
+ <script src="{{ data['openapi-document-path'] }}/../static/redoc.standalone.js"> </script>
</body>
</html>
=====================================
mapproxy/service/templates/ogcapi/openapi/swagger.html
=====================================
@@ -4,9 +4,9 @@
<head>
<meta charset="UTF-8">
<title>Swagger UI - {{ config['metadata']['identification']['title'] }}</title>
- <link rel="stylesheet" type="text/css" href="{{ config['server']['url'] }}/static/swagger-ui-dist/swagger-ui.css" >
- <link rel="icon" type="image/png" href="{{ config['server']['url'] }}/static/swagger-ui-dist/favicon-32x32.png" sizes="32x32" />
- <link rel="icon" type="image/png" href="{{ config['server']['url'] }}/static/swagger-ui-dist/favicon-16x16.png" sizes="16x16" />
+ <link rel="stylesheet" type="text/css" href="{{ data['openapi-document-path'] }}/../static/swagger-ui-dist/swagger-ui.css" >
+ <link rel="icon" type="image/png" href="{{ data['openapi-document-path'] }}/../static/swagger-ui-dist/favicon-32x32.png" sizes="32x32" />
+ <link rel="icon" type="image/png" href="{{ data['openapi-document-path'] }}/../static/swagger-ui-dist/favicon-16x16.png" sizes="16x16" />
<style>
html
{
@@ -30,8 +30,8 @@
<body>
<div id="swagger-ui"></div>
- <script src="{{ config['server']['url'] }}/static/swagger-ui-dist/swagger-ui-bundle.js"> </script>
- <script src="{{ config['server']['url'] }}/static/swagger-ui-dist/swagger-ui-standalone-preset.js"> </script>
+ <script src="{{ data['openapi-document-path'] }}/../static/swagger-ui-dist/swagger-ui-bundle.js"> </script>
+ <script src="{{ data['openapi-document-path'] }}/../static/swagger-ui-dist/swagger-ui-standalone-preset.js"> </script>
<script>
window.onload = function() {
// Begin Swagger UI call region
=====================================
mapproxy/service/templates/ogcapi/tilesets/tileset.html
=====================================
@@ -10,9 +10,9 @@
{% endblock %}
{% block extrahead %}
-<script src="{{ config['server']['url'] }}/static/ol.js"></script>
-<script src="{{ config['server']['url'] }}/static/proj4.min.js"></script>
-<link rel="stylesheet" href="{{ config['server']['url'] }}/static/ol.css"/>
+<script src="{{ data['ogc_api_base'] }}/static/ol.js"></script>
+<script src="{{ data['ogc_api_base'] }}/static/proj4.min.js"></script>
+<link rel="stylesheet" href="{{ data['ogc_api_base'] }}/static/ol.css"/>
{% endblock %}
@@ -54,7 +54,7 @@
const extent = {{ data['extent'] }};
if (!ol.proj.get(srs)) {
- const projDefsUrl = "{{ config['server']['url'] }}/static/proj4defs.js";
+ const projDefsUrl = "{{ data['ogc_api_base'] }}/static/proj4defs.js";
const allDefs = await import(projDefsUrl);
const srsNum = srs.indexOf(':') > -1 ? parseInt(srs.split(':')[1]) : parseInt(srs);
if (!allDefs.defs[srsNum]) {
=====================================
mapproxy/test/unit/test_conf_loader.py
=====================================
@@ -267,6 +267,30 @@ class TestLayerConfiguration(object):
assert False, 'expected ConfigurationError'
+class TestProxyConfigurationContextManager(object):
+ # mapproxy-seed enters the configuration with ``with mapproxy_conf:``;
+ # ProxyConfiguration must therefore support the context manager protocol
+ # (regression: it was lost when the loader was split, see #1442).
+ def test_context_manager_pushes_and_pops_base_config(self):
+ import mapproxy.config.config as mpconfig
+
+ conf = ProxyConfiguration({})
+ before = mpconfig._config.top
+ with conf:
+ assert mpconfig._config.top is conf.base_config
+ assert mpconfig._config.top is before
+
+ def test_context_manager_pops_on_exception(self):
+ import mapproxy.config.config as mpconfig
+
+ conf = ProxyConfiguration({})
+ before = mpconfig._config.top
+ with pytest.raises(ValueError):
+ with conf:
+ raise ValueError
+ assert mpconfig._config.top is before
+
+
class TestGridConfiguration(object):
def test_default_grids(self):
conf = {}
=====================================
mapproxy/test/unit/test_image.py
=====================================
@@ -191,6 +191,34 @@ class TestImageResult(object):
img = Image.open(ir.as_buffer())
assert img.mode == "P"
+ def test_rgb_image_as_buffer_with_rgba_mode(self):
+ # Regression test for https://github.com/mapproxy/mapproxy/issues/1354
+ # When mode=RGBA is requested, an RGB source image must be returned as
+ # RGBA PNG, not RGB PNG, regardless of whether it contains transparency.
+ img = Image.new("RGB", (10, 10), (255, 0, 0))
+ ir = ImageResult(img, image_opts=PNG_FORMAT)
+ rgba_opts = ImageOptions(mode="RGBA", transparent=True, format="image/png")
+ result = Image.open(ir.as_buffer(rgba_opts))
+ assert result.mode == "RGBA", (
+ "Expected RGBA PNG when mode=RGBA requested, got %s" % result.mode
+ )
+
+ def test_rgb_buf_as_buffer_with_rgba_mode(self):
+ # Regression test for https://github.com/mapproxy/mapproxy/issues/1354
+ # When an upstream source returns an opaque RGB PNG buffer and mode=RGBA
+ # is explicitly configured, as_buffer must re-encode to RGBA, not pass
+ # through the RGB bytes unchanged.
+ src = BytesIO()
+ Image.new("RGB", (10, 10), (255, 0, 0)).save(src, "png")
+ src.seek(0)
+ src_opts = ImageOptions(format="image/png", transparent=False)
+ ir = ImageResult(src, image_opts=src_opts)
+ rgba_opts = ImageOptions(mode="RGBA", transparent=True, format="image/png")
+ result = Image.open(ir.as_buffer(rgba_opts))
+ assert result.mode == "RGBA", (
+ "Expected RGBA PNG when mode=RGBA requested, got %s" % result.mode
+ )
+
class TestSubImageResult(object):
@@ -489,6 +517,22 @@ class TestLayerMerge(object):
img = result.as_image()
assert img.getpixel((0, 0)) == (255, 0, 255)
+ def test_single_opaque_rgb_layer_with_rgba_output(self):
+ # Regression test for https://github.com/mapproxy/mapproxy/issues/1354
+ # A single fully-opaque RGB source layer must produce an RGBA PNG when
+ # the requested ImageOptions specify mode=RGBA / transparent=True.
+ # Previously the single-layer shortcut in LayerMerger.merge() returned
+ # the source layer unchanged, so the RGB bytes were passed through
+ # without being converted.
+ source = ImageResult(Image.new("RGB", (10, 10), (255, 0, 0)))
+ rgba_opts = ImageOptions(mode="RGBA", transparent=True, format="image/png")
+ result = merge_images([(source, None)], rgba_opts)
+ output = Image.open(result.as_buffer(rgba_opts))
+ assert output.mode == "RGBA", (
+ "Expected RGBA PNG for opaque source when mode=RGBA requested, got %s"
+ % output.mode
+ )
+
@pytest.mark.skipif(
not hasattr(Image, "alpha_composite"), reason="PIL has no alpha_composite"
=====================================
requirements-tests.txt
=====================================
@@ -2,7 +2,7 @@ attrs==23.2.0
aws-sam-translator==1.91.0
aws-xray-sdk==2.12.1
azure-storage-blob==12.27.1
-beautifulsoup4==4.12.3
+beautifulsoup4==4.14.3
boto3==1.40.55
botocore==1.40.55
certifi==2025.4.26
@@ -10,10 +10,10 @@ cffi==2.0.0
cfn-lint==0.80.3
chardet==5.2.0
coverage==7.11.3
-cryptography==46.0.5
+cryptography==46.0.7
decorator==5.2.1
docker==7.1.0
-docutils==0.21.2
+docutils==0.22.4
ecdsa==0.18.0
flake8==7.0.0
flake8-toml-config==1.0.0
@@ -42,11 +42,11 @@ pluggy==1.6.0
py==1.11.0
pyasn1==0.6.3
pycparser==2.22
-pyparsing==3.2.3
+pyparsing==3.3.2
pyproj==3.7.1
pyrsistent==0.20.0
pytest-rerunfailures==16.0.1
-pytest==8.3.2
+pytest==9.0.3
python-dateutil==2.9.0.post0
python-jose==3.5.0
pytz==2024.2
=====================================
setup.py
=====================================
@@ -44,7 +44,7 @@ def long_description(changelog_releases=10):
setup(
name='MapProxy',
- version="6.1.0",
+ version="6.1.1",
description='An accelerating proxy for tile and web map services',
long_description=long_description(7),
long_description_content_type='text/x-rst',
View it on GitLab: https://salsa.debian.org/debian-gis-team/mapproxy/-/commit/a44065136242c46bb83453e6a25028510a3d0d6d
--
View it on GitLab: https://salsa.debian.org/debian-gis-team/mapproxy/-/commit/a44065136242c46bb83453e6a25028510a3d0d6d
You're receiving this email because of your account on salsa.debian.org. Manage all notifications: https://salsa.debian.org/-/profile/notifications | Help: https://salsa.debian.org/help
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-grass-devel/attachments/20260617/be25f37b/attachment-0001.htm>
More information about the Pkg-grass-devel
mailing list