Skip to content

ENH: Added pyproj.network.set_ca_bundle_path #694

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 22, 2020
Merged
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
2 changes: 1 addition & 1 deletion docs/api/datadir.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.. _data_directory:

Data Directory
==============
===============

pyproj.datadir.get_data_dir
---------------------------
Expand Down
1 change: 1 addition & 0 deletions docs/api/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ API Documentation
proj
list
datadir
network
sync
global_context
enums
Expand Down
10 changes: 10 additions & 0 deletions docs/api/network.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.. _network:

PROJ Network Settings
======================


pyproj.network.set_ca_bundle_path
----------------------------------

.. autofunction:: pyproj.network.set_ca_bundle_path
1 change: 1 addition & 0 deletions docs/history.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Change Log
* ENH: Added ability to use global context (issue #661)
* ENH: Add support for temporal CRS CF coordinate system (issue #672)
* BUG: Fix handling of polygon holes when calculating area in Geod (pull #686)
* ENH: Added :func:`pyproj.network.set_ca_bundle_path` (pull #691)

2.6.1
~~~~~
Expand Down
2 changes: 1 addition & 1 deletion docs/transformation_grids.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ More information about the data available is located under the PROJ
`resource files <https://proj.org/resource_files.html#transformation-grids>`__
documentation.

`pyproj` API for managing the :ref:`data_directory`
`pyproj` API for managing the :ref:`data_directory` and :ref:`network`.

.. warning:: pyproj 2 includes datumgrid 1.8 in the wheels. pyproj 3 will not include any datum grids.

Expand Down
3 changes: 3 additions & 0 deletions pyproj/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
]
import warnings

import pyproj.network
from pyproj._datadir import ( # noqa: F401
_pyproj_global_context_initialize,
is_global_context_network_enabled,
Expand Down Expand Up @@ -79,3 +80,5 @@
_pyproj_global_context_initialize()
except DataDirError as err:
warnings.warn(str(err))

pyproj.network.set_ca_bundle_path()
1 change: 1 addition & 0 deletions pyproj/_network.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
def _set_ca_bundle_path(ca_bundle_path: str) -> None: ...
16 changes: 16 additions & 0 deletions pyproj/_network.pyx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
include "proj.pxi"

from pyproj.compat import cstrencode


def _set_ca_bundle_path(ca_bundle_path):
"""
Sets the path to the CA Bundle used by the `curl`
built into PROJ.

Parameters
----------
ca_bundle_path: str
The path to the CA Bundle.
"""
proj_context_set_ca_bundle_path(NULL, cstrencode(ca_bundle_path))
51 changes: 51 additions & 0 deletions pyproj/network.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"""
Module for managing the PROJ network settings.
"""
import os
from pathlib import Path
from typing import Union

import certifi

from pyproj._network import _set_ca_bundle_path


def set_ca_bundle_path(ca_bundle_path: Union[Path, str, bool, None] = None) -> None:
"""
.. versionadded:: 3.0.0

Sets the path to the CA Bundle used by the `curl`
built into PROJ.

Environment variables that can be used with PROJ 7.2+:

- PROJ_CURL_CA_BUNDLE
- CURL_CA_BUNDLE
- SSL_CERT_FILE

Parameters
----------
ca_bundle_path: Union[Path, str, bool, None], optional
Default is None, which only uses the `certifi` package path as a fallback if
the environment variables are not set. If a path is passed in, then
that will be the path used. If it is set to True, then it will default
to using the path provied by the `certifi` package. If it is set to False,
then it will not set the path.
"""
if ca_bundle_path is False:
return

env_var_names = (
"PROJ_CURL_CA_BUNDLE",
"CURL_CA_BUNDLE",
"SSL_CERT_FILE",
)
if isinstance(ca_bundle_path, (str, Path)):
ca_bundle_path = str(ca_bundle_path)
elif (ca_bundle_path is True) or not any(
env_var_name in os.environ for env_var_name in env_var_names
):
ca_bundle_path = certifi.where()

if isinstance(ca_bundle_path, str):
_set_ca_bundle_path(ca_bundle_path)
1 change: 1 addition & 0 deletions pyproj/proj.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ cdef extern from "proj.h":
const char *dbPath,
const char *const *auxDbPaths,
const char* const *options)
void proj_context_set_ca_bundle_path(PJ_CONTEXT *ctx, const char *path);

# projCtx has been replaced by PJ_CONTEXT *.
# projPJ has been replaced by PJ *
Expand Down
2 changes: 2 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ def get_extension_modules():
),
Extension("pyproj._datadir", ["pyproj/_datadir.pyx"], **ext_options),
Extension("pyproj._list", ["pyproj/_list.pyx"], **ext_options),
Extension("pyproj._network", ["pyproj/_network.pyx"], **ext_options),
Extension("pyproj._sync", ["pyproj/_sync.pyx"], **ext_options),
],
quiet=True,
Expand Down Expand Up @@ -244,4 +245,5 @@ def get_long_description():
ext_modules=get_extension_modules(),
package_data=get_package_data(),
zip_safe=False, # https://mypy.readthedocs.io/en/stable/installed_packages.html
install_requires=["certifi"],
)
49 changes: 49 additions & 0 deletions test/test_network.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import certifi
import pytest
from mock import patch

from pyproj.network import set_ca_bundle_path


@patch.dict("os.environ", {}, clear=True)
@patch("pyproj.network._set_ca_bundle_path")
def test_ca_bundle_path__default(c_set_ca_bundle_path_mock):
set_ca_bundle_path()
c_set_ca_bundle_path_mock.assert_called_with(certifi.where())


@pytest.mark.parametrize(
"env_var", ["PROJ_CURL_CA_BUNDLE", "CURL_CA_BUNDLE", "SSL_CERT_FILE"]
)
@patch("pyproj.network._set_ca_bundle_path")
def test_ca_bundle_path__always_certifi(c_set_ca_bundle_path_mock, env_var):
with patch.dict("os.environ", {env_var: "/tmp/dummy/path/cacert.pem"}, clear=True):
set_ca_bundle_path(True)
c_set_ca_bundle_path_mock.assert_called_with(certifi.where())


@patch.dict("os.environ", {}, clear=True)
@patch("pyproj.network._set_ca_bundle_path")
def test_ca_bundle_path__skip(c_set_ca_bundle_path_mock):
set_ca_bundle_path(False)
c_set_ca_bundle_path_mock.assert_not_called()


@pytest.mark.parametrize(
"env_var", ["PROJ_CURL_CA_BUNDLE", "CURL_CA_BUNDLE", "SSL_CERT_FILE"]
)
@patch("pyproj.network._set_ca_bundle_path")
def test_ca_bundle_path__env_var_skip(c_set_ca_bundle_path_mock, env_var):
with patch.dict("os.environ", {env_var: "/tmp/dummy/path/cacert.pem"}, clear=True):
set_ca_bundle_path()
c_set_ca_bundle_path_mock.assert_not_called()


@pytest.mark.parametrize(
"env_var", ["PROJ_CURL_CA_BUNDLE", "CURL_CA_BUNDLE", "SSL_CERT_FILE"]
)
@patch("pyproj.network._set_ca_bundle_path")
def test_ca_bundle_path__custom_path(c_set_ca_bundle_path_mock, env_var):
with patch.dict("os.environ", {env_var: "/tmp/dummy/path/cacert.pem"}, clear=True):
set_ca_bundle_path("/my/path/to/cacert.pem")
c_set_ca_bundle_path_mock.assert_called_with("/my/path/to/cacert.pem")