Skip to content

Commit

Permalink
refactor backend code into repository module, remove PL/Python
Browse files Browse the repository at this point in the history
  • Loading branch information
tomkralidis committed Oct 9, 2023
1 parent bd79242 commit ef31777
Show file tree
Hide file tree
Showing 8 changed files with 437 additions and 531 deletions.
83 changes: 14 additions & 69 deletions docker/entrypoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,10 @@
import os
import configparser
import sys
from time import sleep

from sqlalchemy import create_engine
from sqlalchemy.exc import OperationalError
from sqlalchemy.exc import ProgrammingError

from pycsw.core import admin
from pycsw.core.config import StaticContext
from pycsw.core.util import EnvInterpolation
from pycsw.core.repository import Repository, setup

LOGGER = logging.getLogger(__name__)

Expand All @@ -77,28 +73,17 @@ def launch_pycsw(pycsw_config, workers=2, reload=False):
for more information on how to control gunicorn by sending UNIX signals.
"""

db_url = pycsw_config.get("repository", "database")

db = db_url.partition(":")[0].partition("+")[0]

db_handler = {
"sqlite": handle_sqlite_db,
"postgresql": handle_postgresql_db,
}.get(db)

# FIXME: pycsw.wsgi_flask is bound to PostgreSQL backends only
# An update in pycsw/ogc/api/records.py is required
if db_handler is not None:
LOGGER.debug("Setting up pycsw's data repository...")
LOGGER.debug(f"Repository URL: {db_url}")
db_handler(
db_url,
pycsw_config.get("repository", "table"),
pycsw_config.get("server", "home")
)
pycsw_app = 'pycsw.wsgi_flask:APP'
else:
pycsw_app = 'pycsw.wsgi'
try:
setup(pycsw_config.get("repository", "database"),
pycsw_config.get("repository", "table"))
except Exception as err:
LOGGER.debug(err)

repo = Repository(pycsw_config.get("repository", "database"),
StaticContext(),
table=pycsw_config.get("repository", "table"))

repo.ping()

sys.stdout.flush()
# we're using --reload-engine=poll because there is a bug with gunicorn
Expand All @@ -119,7 +104,7 @@ def launch_pycsw(pycsw_config, workers=2, reload=False):
"--error-logfile=-",
f"--workers={workers}",
f"--timeout={timeout}",
pycsw_app,
'pycsw.wsgi_flask:APP'

]
LOGGER.debug(f"Launching pycsw with {' '.join(execution_args)} ...")
Expand All @@ -129,46 +114,6 @@ def launch_pycsw(pycsw_config, workers=2, reload=False):
)


def handle_sqlite_db(database_url, table_name, pycsw_home):
db_path = database_url.rpartition(":///")[-1]
if not os.path.isfile(db_path):
try:
os.makedirs(os.path.dirname(db_path))
except OSError as exc:
if exc.args[0] == 17: # directory already exists
pass
admin.setup_db(database=database_url, table=table_name,
home=pycsw_home)


def handle_postgresql_db(database_url, table_name, pycsw_home):
_wait_for_postgresql_db(database_url)
try:
admin.setup_db(database=database_url, table=table_name,
home=pycsw_home)
except ProgrammingError:
pass # database tables are already created


def _wait_for_postgresql_db(database_url, max_tries=10, wait_seconds=3):
LOGGER.debug(f"Waiting for {database_url}...")
engine = create_engine(database_url)
current_try = 0
while current_try < max_tries:
try:
engine.execute("SELECT version();")
LOGGER.debug("Database is already up!")
break
except OperationalError:
LOGGER.debug("Database not responding yet ...")
current_try += 1
sleep(wait_seconds)
else:
raise RuntimeError(
f"Database not responding at {database_url} after {max_tries} tries. "
)


if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument(
Expand Down
8 changes: 4 additions & 4 deletions docs/administration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ Setting up the Database

.. code-block:: bash
pycsw-admin.py setup_db --config default.cfg
pycsw-admin.py setup_repository --config default.cfg
This will create the necessary tables and values for the repository.

Expand Down Expand Up @@ -120,8 +120,8 @@ Database Specific Notes
PostgreSQL
^^^^^^^^^^

- if PostGIS is not enabled, pycsw makes uses of PL/Python functions. To enable PostgreSQL support, the database user must be able to create functions within the database. In case of recent PostgreSQL versions (9.x), the PL/Python extension must be enabled prior to pycsw setup
- `PostgreSQL Full Text Search`_ is supported for ``csw:AnyText`` based queries. pycsw creates a tsvector column based on the text from anytext column. Then pycsw creates a GIN index against the anytext_tsvector column. This is created automatically in ``pycsw.admin.setup_db``. Any query against OARec's ``q`` parameter or CSW `csw:AnyText` or `apiso:AnyText` will process using PostgreSQL FTS handling
- To enable PostgreSQL support, the database user must be able to create functions within the database.
- `PostgreSQL Full Text Search`_ is supported for ``csw:AnyText`` based queries. pycsw creates a tsvector column based on the text from anytext column. Then pycsw creates a GIN index against the anytext_tsvector column. This is created automatically in ``pycsw.core.repository.setup``. Any query against OARec's ``q`` parameter or CSW `csw:AnyText` or `apiso:AnyText` will process using PostgreSQL FTS handling

PostGIS
^^^^^^^
Expand All @@ -131,7 +131,7 @@ PostGIS
- If PostGIS is detected, the ``pycsw-admin.py`` script will create both a native geometry column and a WKT column, as well as a trigger to keep both synchronized
- In case PostGIS gets disabled, pycsw will continue to work with the `WKT`_ column
- In case of migration from plain PostgreSQL database to PostGIS, the spatial functions of PostGIS will be used automatically
- When migrating from plain PostgreSQL database to PostGIS, in order to enable native geometry support, a "GEOMETRY" column named "wkb_geometry" needs to be created manually (along with the update trigger in ``pycsw.admin.setup_db``). Also the native geometries must be filled manually from the `WKT`_ field. Next versions of pycsw will automate this process
- When migrating from plain PostgreSQL database to PostGIS, in order to enable native geometry support, a "GEOMETRY" column named "wkb_geometry" needs to be created manually (along with the update trigger in ``pycsw.core.repository.setup``). Also the native geometries must be filled manually from the `WKT`_ field. Next versions of pycsw will automate this process

.. _custom_repository:

Expand Down
20 changes: 8 additions & 12 deletions docs/locale/zh/LC_MESSAGES/administration.po
Original file line number Diff line number Diff line change
Expand Up @@ -196,26 +196,22 @@ msgstr "PostgreSQL"

#: ../../administration.rst:119
msgid ""
"if PostGIS is not enabled, pycsw makes uses of PL/Python functions. To enable "
"PostgreSQL support, the database user must be able to create functions within "
"the database. In case of recent PostgreSQL versions (9.x), the PL/Python "
"extension must be enabled prior to pycsw setup"
"To enable the database user must be able to create functions within the database."
msgstr ""
"若 PostGIS不可用,pycsw会启用 PL/Python功能。在PostgreSQL支持下,用户必须在数据"
"库中创建这些功能。如果是最新版本PostgreSQL (9.x),PL/ Python扩展"
"在PostgreSQL支持下,用户必须在数据"

#: ../../administration.rst:120
msgid ""
"`PostgreSQL Full Text Search`_ is supported for ``csw:AnyText`` based queries. "
"pycsw creates a tsvector column based on the text from anytext column. Then "
"pycsw creates a GIN index against the anytext_tsvector column. This is created "
"automatically in ``pycsw.admin.setup_db``. Any query against OARec's ``q`` "
"automatically in ``pycsw.core.repository.setup``. Any query against OARec's ``q`` "
"parameter or CSW `csw:AnyText` or `apiso:AnyText` will process using PostgreSQL "
"FTS handling"
msgstr ""
"`PostgreSQL Full Text Search`_ (全文搜索)支持基于 ``csw:AnyText`` (任意文本)的"
"查询。pycsw创建的tsvector栏是基于文本anytext栏。然而pycsw针对"
"anytext_tsvector(任意文本)栏创建了GIN索引。这在 ``pycsw.admin.setup_db`` 是自"
"anytext_tsvector(任意文本)栏创建了GIN索引。这在 ``pycsw.core.repository.setup`` 是自"
"动生成的。任何针对 `csw:AnyText` or `apiso:AnyText` 的查询都是使用PostgreSQL FT"
"进行处理"

Expand Down Expand Up @@ -258,13 +254,13 @@ msgstr "如果plain PostgreSQL数据库移入PostGIS中,PostGIS的空间功能
msgid ""
"When migrating from plain PostgreSQL database to PostGIS, in order to enable "
"native geometry support, a \"GEOMETRY\" column named \"wkb_geometry\" needs to "
"be created manually (along with the update trigger in ``pycsw.admin."
"setup_db``). Also the native geometries must be filled manually from the `WKT`_ "
"be created manually (along with the update trigger in ``pycsw.core.repository."
"setup``). Also the native geometries must be filled manually from the `WKT`_ "
"field. Next versions of pycsw will automate this process"
msgstr ""
"当从普通的数据库plain PostgreSQL移入PostGIS时, 为了启用本地geometry支持,需要手"
"动创建一个名为 \"wkb_geometry\"\"GEOMETRY\" 列(随着 ``pycsw.admin."
"setup_db`` 一起更新)。本地geometries也必须在 `WKT`_ 中手动填充。pycsw的下一个版"
"动创建一个名为 \"wkb_geometry\"\"GEOMETRY\" 列(随着 ``pycsw.core.repository."
"setup`` 一起更新)。本地geometries也必须在 `WKT`_ 中手动填充。pycsw的下一个版"
"本就会将此过程自动化运行"

#: ../../administration.rst:135
Expand Down
Loading

0 comments on commit ef31777

Please sign in to comment.