Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions pycsw/core/repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,12 @@ def connect(dbapi_connection, connection_rec):
return clazz._engines[url]

''' Class to interact with underlying repository '''
def __init__(self, database, context, app_root=None, table='records', repo_filter=None):
def __init__(self, database, context, app_root=None, table='records', repo_filter=None, stable_sort = False):
''' Initialize repository '''

self.context = context
self.filter = repo_filter
self.stable_sort = stable_sort
self.fts = False
self.database = database
self.table = table
Expand Down Expand Up @@ -450,7 +451,11 @@ def query(self, constraint, sortby=None, typenames=None,
query = query.order_by(func.get_geometry_area(sortby_column))
else: # aspatial sort
query = query.order_by(sortby_column)


if self.stable_sort:
identifier = self.context.md_core_model['mappings']['pycsw:Identifier']
query = query.order_by(identifier)

# always apply limit and offset
return [str(total), self._get_repo_filter(query).limit(
maxrecords).offset(startposition).all()]
Expand Down
3 changes: 2 additions & 1 deletion pycsw/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,8 @@ def dispatch(self, writer=sys.stdout, write_headers=True):
self.context,
self.environ.get('local.app_root', None),
self.config['repository'].get('table'),
repo_filter
repo_filter,
self.config['repository'].get('stable_sort', False)
)
LOGGER.debug(
'Repository loaded (local): %s.' % self.repository.dbtype)
Expand Down
98 changes: 98 additions & 0 deletions tests/functionaltests/suites/stablesort/default.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# =================================================================
#
# Authors: Tom Kralidis <[email protected]>
#
# Copyright (c) 2024 Tom Kralidis
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
# files (the "Software"), to deal in the Software without
# restriction, including without limitation the rights to use,
# copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following
# conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
#
# =================================================================

server:
url: http://localhost/pycsw/csw.py?config=tests/functionaltests/suites/csw30/default.yml
mimetype: application/xml; charset=UTF-8
encoding: UTF-8
language: en-US
maxrecords: 10
pretty_print: true

logging:
level: DEBUG

federatedcatalogues:
- http://geo.data.gov/geoportal/csw/discovery

manager:
transactions: false
allowed_ips:
- 127.0.0.1

metadata:
identification:
title: pycsw Geospatial Catalogue
description: pycsw is an OARec and OGC CSW server implementation written in Python
keywords:
- catalogue
- discovery
keywords_type: theme
fees: None
accessconstraints: None
provider:
name: pycsw
url: https://pycsw.org/
contact:
name: Kralidis, Tom
position: Senior Systems Scientist
address: TBA
city: Toronto
stateorprovince: Ontario
postalcode: M9C 3Z9
country: Canada
phone: +01-416-xxx-xxxx
fax: +01-416-xxx-xxxx
email: [email protected]
url: http://kralidis.ca/
hours: 0800h - 1600h EST
instructions: During hours of service. Off on weekends.
role: pointOfContact

inspire:
enabled: false
languages_supported:
- eng
- gre
default_language: eng
date: 2011-03-29
gemet_keywords:
- Utility and governmental services
conformity_service: notEvaluated
contact_name: National Technical University of Athens
contact_email: [email protected]
temp_extent:
begin: 2011-02-01
end: 2011-03-30

repository:
# sqlite
database: sqlite:///tests/functionaltests/suites/cite/data/cite.db
table: records
stable_sort: true
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- PYCSW_VERSION -->
<csw:GetRecordsResponse xmlns:csw="http://www.opengis.net/cat/csw/2.0.2" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dct="http://purl.org/dc/terms/" xmlns:gmd="http://www.isotc211.org/2005/gmd" xmlns:gml="http://www.opengis.net/gml" xmlns:ows="http://www.opengis.net/ows" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0.2" xsi:schemaLocation="http://www.opengis.net/cat/csw/2.0.2 http://schemas.opengis.net/csw/2.0.2/CSW-discovery.xsd">
<csw:SearchStatus timestamp="PYCSW_TIMESTAMP"/>
<csw:SearchResults numberOfRecordsMatched="12" numberOfRecordsReturned="4" nextRecord="5" recordSchema="http://www.opengis.net/cat/csw/2.0.2" elementSet="full">
<csw:Record>
<dc:identifier>urn:uuid:66ae76b7-54ba-489b-a582-0f0633d96493</dc:identifier>
<dc:title>Maecenas enim</dc:title>
<dc:type>http://purl.org/dc/dcmitype/Text</dc:type>
<dc:format>application/xhtml+xml</dc:format>
<dc:subject>Marine sediments</dc:subject>
<dct:abstract>Pellentesque tempus magna non sapien fringilla blandit.</dct:abstract>
</csw:Record>
<csw:Record>
<dc:identifier>urn:uuid:784e2afd-a9fd-44a6-9a92-a3848371c8ec</dc:identifier>
<dc:title>Aliquam fermentum purus quis arcu</dc:title>
<dc:type>http://purl.org/dc/dcmitype/Text</dc:type>
<dc:subject>Hydrography--Dictionaries</dc:subject>
<dc:format>application/pdf</dc:format>
<dc:date>2006-05-12</dc:date>
<dct:abstract>Vestibulum quis ipsum sit amet metus imperdiet vehicula. Nulla scelerisque cursus mi.</dct:abstract>
</csw:Record>
<csw:Record>
<dc:identifier>urn:uuid:e9330592-0932-474b-be34-c3a3bb67c7db</dc:identifier>
<dc:type>http://purl.org/dc/dcmitype/Text</dc:type>
<dc:title>Fuscé vitae ligulä</dc:title>
<dc:date>2003-05-09</dc:date>
<dc:subject>Land titles</dc:subject>
<dc:format>text/rtf</dc:format>
<dct:abstract>Morbi ultriçes, dui suscipit vestibulum prètium, velit ante pretium tortor, egët tincidunt pede odio ac nulla.</dct:abstract>
</csw:Record>
<csw:Record>
<dc:identifier>urn:uuid:1ef30a8b-876d-4828-9246-c37ab4510bbd</dc:identifier>
<dc:type>http://purl.org/dc/dcmitype/Service</dc:type>
<dct:abstract>Proin sit amet justo. In justo. Aenean adipiscing nulla id tellus.</dct:abstract>
<ows:BoundingBox crs="urn:x-ogc:def:crs:EPSG:6.11:4326">
<ows:LowerCorner>60.042 13.754</ows:LowerCorner>
<ows:UpperCorner>68.410 17.920</ows:UpperCorner>
</ows:BoundingBox>
</csw:Record>
</csw:SearchResults>
</csw:GetRecordsResponse>
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- PYCSW_VERSION -->
<csw:GetRecordsResponse xmlns:csw="http://www.opengis.net/cat/csw/2.0.2" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dct="http://purl.org/dc/terms/" xmlns:gmd="http://www.isotc211.org/2005/gmd" xmlns:gml="http://www.opengis.net/gml" xmlns:ows="http://www.opengis.net/ows" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0.2" xsi:schemaLocation="http://www.opengis.net/cat/csw/2.0.2 http://schemas.opengis.net/csw/2.0.2/CSW-discovery.xsd">
<csw:SearchStatus timestamp="PYCSW_TIMESTAMP"/>
<csw:SearchResults numberOfRecordsMatched="12" numberOfRecordsReturned="4" nextRecord="9" recordSchema="http://www.opengis.net/cat/csw/2.0.2" elementSet="full">
<csw:Record>
<dc:identifier>urn:uuid:6a3de50b-fa66-4b58-a0e6-ca146fdd18d4</dc:identifier>
<dc:type>http://purl.org/dc/dcmitype/Service</dc:type>
<dc:title>Ut facilisis justo ut lacus</dc:title>
<dc:subject scheme="http://www.digest.org/2.1">Vegetation</dc:subject>
<dc:relation>urn:uuid:94bc9c83-97f6-4b40-9eb8-a8e8787a5c63</dc:relation>
</csw:Record>
<csw:Record>
<dc:identifier>urn:uuid:ab42a8c4-95e8-4630-bf79-33e59241605a</dc:identifier>
<dc:type>http://purl.org/dc/dcmitype/Service</dc:type>
<dc:subject scheme="http://www.digest.org/2.1">Physiography</dc:subject>
<dct:abstract>Suspendisse accumsan molestie lorem. Nullam velit turpis, mattis ut, varius bibendum, laoreet non, quam.</dct:abstract>
<dc:relation>urn:uuid:88247b56-4cbc-4df9-9860-db3f8042e357</dc:relation>
</csw:Record>
<csw:Record>
<dc:identifier>urn:uuid:19887a8a-f6b0-4a63-ae56-7fba0e17801f</dc:identifier>
<dc:type>http://purl.org/dc/dcmitype/Image</dc:type>
<dc:format>image/svg+xml</dc:format>
<dc:title>Lorem ipsum</dc:title>
<dct:spatial>GR-22</dct:spatial>
<dc:subject>Tourism--Greece</dc:subject>
<dct:abstract>Quisque lacus diam, placerat mollis, pharetra in, commodo sed, augue. Duis iaculis arcu vel arcu.</dct:abstract>
</csw:Record>
<csw:Record>
<dc:identifier>urn:uuid:829babb0-b2f1-49e1-8cd5-7b489fe71a1e</dc:identifier>
<dc:type>http://purl.org/dc/dcmitype/Image</dc:type>
<dc:format>image/jp2</dc:format>
<dc:title>Vestibulum massa purus</dc:title>
<dc:relation>urn:uuid:9a669547-b69b-469f-a11f-2d875366bbdc</dc:relation>
</csw:Record>
</csw:SearchResults>
</csw:GetRecordsResponse>
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- PYCSW_VERSION -->
<csw:GetRecordsResponse xmlns:csw="http://www.opengis.net/cat/csw/2.0.2" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dct="http://purl.org/dc/terms/" xmlns:gmd="http://www.isotc211.org/2005/gmd" xmlns:gml="http://www.opengis.net/gml" xmlns:ows="http://www.opengis.net/ows" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0.2" xsi:schemaLocation="http://www.opengis.net/cat/csw/2.0.2 http://schemas.opengis.net/csw/2.0.2/CSW-discovery.xsd">
<csw:SearchStatus timestamp="PYCSW_TIMESTAMP"/>
<csw:SearchResults numberOfRecordsMatched="12" numberOfRecordsReturned="4" nextRecord="0" recordSchema="http://www.opengis.net/cat/csw/2.0.2" elementSet="full">
<csw:Record>
<dc:identifier>urn:uuid:a06af396-3105-442d-8b40-22b57a90d2f2</dc:identifier>
<dc:type>http://purl.org/dc/dcmitype/Image</dc:type>
<dc:title>Lorem ipsum dolor sit amet</dc:title>
<dc:format>image/jpeg</dc:format>
<dct:spatial>IT-FI</dct:spatial>
</csw:Record>
<csw:Record>
<dc:identifier>urn:uuid:88247b56-4cbc-4df9-9860-db3f8042e357</dc:identifier>
<dc:type>http://purl.org/dc/dcmitype/Dataset</dc:type>
<dc:subject scheme="http://www.digest.org/2.1">Physiography-Landforms</dc:subject>
<dct:spatial>FI-ES</dct:spatial>
<dct:abstract>Donec scelerisque pede ut nisl luctus accumsan. Quisque ultrices, lorem eget feugiat fringilla, lorem dui porttitor ante, cursus ultrices magna odio eu neque.</dct:abstract>
</csw:Record>
<csw:Record>
<dc:identifier>urn:uuid:94bc9c83-97f6-4b40-9eb8-a8e8787a5c63</dc:identifier>
<dc:type>http://purl.org/dc/dcmitype/Dataset</dc:type>
<dc:title>Mauris sed neque</dc:title>
<dc:subject scheme="http://www.digest.org/2.1">Vegetation-Cropland</dc:subject>
<dct:abstract>Curabitur lacinia, ante non porta tempus, mi lorem feugiat odio, eget suscipit eros pede ac velit.</dct:abstract>
<dc:date>2006-03-26</dc:date>
<ows:BoundingBox crs="urn:x-ogc:def:crs:EPSG:6.11:4326">
<ows:LowerCorner>47.595 -4.097</ows:LowerCorner>
<ows:UpperCorner>51.217 0.889</ows:UpperCorner>
</ows:BoundingBox>
</csw:Record>
<csw:Record>
<dc:identifier>urn:uuid:9a669547-b69b-469f-a11f-2d875366bbdc</dc:identifier>
<dc:type>http://purl.org/dc/dcmitype/Dataset</dc:type>
<dc:title>Ñunç elementum</dc:title>
<dc:subject scheme="http://www.digest.org/2.1">Hydrography-Oceanographic</dc:subject>
<dc:date>2005-10-24</dc:date>
<ows:BoundingBox crs="urn:x-ogc:def:crs:EPSG:6.11:4326">
<ows:LowerCorner>44.792 -6.171</ows:LowerCorner>
<ows:UpperCorner>51.126 -2.228</ows:UpperCorner>
</ows:BoundingBox>
</csw:Record>
</csw:SearchResults>
</csw:GetRecordsResponse>
3 changes: 3 additions & 0 deletions tests/functionaltests/suites/stablesort/get/requests.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
GetRecords-page1,service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&sortby=dc:type:D&maxRecords=4&startPosition=1
GetRecords-page2,service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&sortby=dc:type:D&maxRecords=4&startPosition=5
GetRecords-page3,service=CSW&version=2.0.2&request=GetRecords&typenames=csw:Record&elementsetname=full&resulttype=results&sortby=dc:type:D&maxRecords=4&startPosition=9