Skip to content

Commit

Permalink
move set_ca_bundle_path to network and add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
snowman2 committed Aug 22, 2020
1 parent 6d83854 commit 5c06b13
Show file tree
Hide file tree
Showing 13 changed files with 137 additions and 59 deletions.
12 changes: 3 additions & 9 deletions docs/api/datadir.rst
@@ -1,7 +1,7 @@
.. _data_and_ca_bundle_directory:
.. _data_directory:

Data Directory & CA Bundle Path
===============================
Data Directory
===============

pyproj.datadir.get_data_dir
---------------------------
Expand All @@ -25,9 +25,3 @@ pyproj.datadir.get_user_data_dir
---------------------------------

.. autofunction:: pyproj.datadir.get_user_data_dir


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

.. autofunction:: pyproj.set_ca_bundle_path
1 change: 1 addition & 0 deletions docs/api/index.rst
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
@@ -0,0 +1,10 @@
.. _network:

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


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

.. autofunction:: pyproj.network.set_ca_bundle_path
2 changes: 1 addition & 1 deletion docs/history.rst
Expand Up @@ -22,7 +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.set_ca_bundle_path` (pull #691)
* 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
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_and_ca_bundle_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
4 changes: 2 additions & 2 deletions pyproj/__init__.py
Expand Up @@ -46,10 +46,10 @@
]
import warnings

import pyproj.network
from pyproj._datadir import ( # noqa: F401
_pyproj_global_context_initialize,
is_global_context_network_enabled,
set_ca_bundle_path,
set_global_context_network,
set_use_global_context,
)
Expand Down Expand Up @@ -81,4 +81,4 @@
except DataDirError as err:
warnings.warn(str(err))

set_ca_bundle_path()
pyproj.network.set_ca_bundle_path()
4 changes: 1 addition & 3 deletions pyproj/_datadir.pyi
@@ -1,9 +1,7 @@
from pathlib import Path
from typing import Optional, Union
from typing import Optional

def _pyproj_global_context_initialize() -> None: ...
def get_user_data_dir(create: bool = False) -> str: ...
def set_ca_bundle_path(ca_bundle_path: Union[Path, str, bool, None] = None) -> None: ...
def _global_context_set_data_dir() -> None: ...
def set_use_global_context(active: Optional[bool] = None) -> None: ...
def set_global_context_network(active: Optional[bool] = None) -> None: ...
Expand Down
43 changes: 0 additions & 43 deletions pyproj/_datadir.pyx
@@ -1,9 +1,7 @@
import os
import warnings
from distutils.util import strtobool
from pathlib import Path

import certifi
from libc.stdlib cimport free, malloc

from pyproj.compat import cstrencode, pystrdecode
Expand Down Expand Up @@ -113,47 +111,6 @@ def get_user_data_dir(create=False):
return pystrdecode(proj_context_get_user_writable_directory(NULL, bool(create)))


def set_ca_bundle_path(ca_bundle_path=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 None

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):
proj_context_set_ca_bundle_path(NULL, cstrencode(ca_bundle_path))


cdef void pyproj_log_function(void *user_data, int level, const char *error_msg):
"""
Log function for catching PROJ errors.
Expand Down
1 change: 1 addition & 0 deletions pyproj/_network.pyi
@@ -0,0 +1 @@
def _set_ca_bundle_path(ca_bundle_path: str) -> None: ...
16 changes: 16 additions & 0 deletions pyproj/_network.pyx
@@ -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
@@ -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 setup.py
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
49 changes: 49 additions & 0 deletions test/test_network.py
@@ -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")

0 comments on commit 5c06b13

Please sign in to comment.