Skip to content

Commit 0c507f6

Browse files
committed
move set_ca_bundle_path to network and add tests
1 parent 6d83854 commit 0c507f6

12 files changed

+136
-58
lines changed

docs/api/datadir.rst

+3-9
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
.. _data_and_ca_bundle_directory:
1+
.. _data_directory:
22

3-
Data Directory & CA Bundle Path
4-
===============================
3+
Data Directory
4+
===============
55

66
pyproj.datadir.get_data_dir
77
---------------------------
@@ -25,9 +25,3 @@ pyproj.datadir.get_user_data_dir
2525
---------------------------------
2626

2727
.. autofunction:: pyproj.datadir.get_user_data_dir
28-
29-
30-
pyproj.set_ca_bundle_path
31-
--------------------------
32-
33-
.. autofunction:: pyproj.set_ca_bundle_path

docs/api/index.rst

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ API Documentation
1111
proj
1212
list
1313
datadir
14+
network
1415
sync
1516
global_context
1617
enums

docs/api/network.rst

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
.. _network:
2+
3+
PROJ Network Settings
4+
======================
5+
6+
7+
pyproj.network.set_ca_bundle_path
8+
----------------------------------
9+
10+
.. autofunction:: pyproj.network.set_ca_bundle_path

docs/transformation_grids.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ More information about the data available is located under the PROJ
99
`resource files <https://proj.org/resource_files.html#transformation-grids>`__
1010
documentation.
1111

12-
`pyproj` API for managing the :ref:`data_and_ca_bundle_directory`
12+
`pyproj` API for managing the :ref:`data_directory` and :ref:`network`.
1313

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

pyproj/__init__.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,10 @@
4646
]
4747
import warnings
4848

49+
import pyproj.network
4950
from pyproj._datadir import ( # noqa: F401
5051
_pyproj_global_context_initialize,
5152
is_global_context_network_enabled,
52-
set_ca_bundle_path,
5353
set_global_context_network,
5454
set_use_global_context,
5555
)
@@ -81,4 +81,4 @@
8181
except DataDirError as err:
8282
warnings.warn(str(err))
8383

84-
set_ca_bundle_path()
84+
pyproj.network.set_ca_bundle_path()

pyproj/_datadir.pyi

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
1-
from pathlib import Path
2-
from typing import Optional, Union
1+
from typing import Optional
32

43
def _pyproj_global_context_initialize() -> None: ...
54
def get_user_data_dir(create: bool = False) -> str: ...
6-
def set_ca_bundle_path(ca_bundle_path: Union[Path, str, bool, None] = None) -> None: ...
75
def _global_context_set_data_dir() -> None: ...
86
def set_use_global_context(active: Optional[bool] = None) -> None: ...
97
def set_global_context_network(active: Optional[bool] = None) -> None: ...

pyproj/_datadir.pyx

-43
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import os
22
import warnings
33
from distutils.util import strtobool
4-
from pathlib import Path
54

6-
import certifi
75
from libc.stdlib cimport free, malloc
86

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

115113

116-
def set_ca_bundle_path(ca_bundle_path=None):
117-
"""
118-
.. versionadded:: 3.0.0
119-
120-
Sets the path to the CA Bundle used by the `curl`
121-
built into PROJ.
122-
123-
Environment variables that can be used with PROJ 7.2+:
124-
- PROJ_CURL_CA_BUNDLE
125-
- CURL_CA_BUNDLE
126-
- SSL_CERT_FILE
127-
128-
Parameters
129-
----------
130-
ca_bundle_path: Union[Path, str, bool, None], optional
131-
Default is None, which only uses the `certifi` package path as a fallback if
132-
the environment variables are not set. If a path is passed in, then
133-
that will be the path used. If it is set to True, then it will default
134-
to using the path provied by the `certifi` package. If it is set to False,
135-
then it will not set the path.
136-
"""
137-
if ca_bundle_path is False:
138-
return None
139-
140-
env_var_names = (
141-
"PROJ_CURL_CA_BUNDLE",
142-
"CURL_CA_BUNDLE",
143-
"SSL_CERT_FILE",
144-
)
145-
if isinstance(ca_bundle_path, (str, Path)):
146-
ca_bundle_path = str(ca_bundle_path)
147-
elif (
148-
(ca_bundle_path is True) or
149-
not any(env_var_name in os.environ for env_var_name in env_var_names)
150-
):
151-
ca_bundle_path = certifi.where()
152-
153-
if isinstance(ca_bundle_path, str):
154-
proj_context_set_ca_bundle_path(NULL, cstrencode(ca_bundle_path))
155-
156-
157114
cdef void pyproj_log_function(void *user_data, int level, const char *error_msg):
158115
"""
159116
Log function for catching PROJ errors.

pyproj/_network.pyi

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
def _set_ca_bundle_path(ca_bundle_path: str) -> None: ...

pyproj/_network.pyx

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
include "proj.pxi"
2+
3+
from pyproj.compat import cstrencode
4+
5+
6+
def _set_ca_bundle_path(ca_bundle_path):
7+
"""
8+
Sets the path to the CA Bundle used by the `curl`
9+
built into PROJ.
10+
11+
Parameters
12+
----------
13+
ca_bundle_path: str
14+
The path to the CA Bundle.
15+
"""
16+
proj_context_set_ca_bundle_path(NULL, cstrencode(ca_bundle_path))

pyproj/network.py

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
"""
2+
Module for managing the PROJ network settings.
3+
"""
4+
import os
5+
from pathlib import Path
6+
from typing import Union
7+
8+
import certifi
9+
10+
from pyproj._network import _set_ca_bundle_path
11+
12+
13+
def set_ca_bundle_path(ca_bundle_path: Union[Path, str, bool, None] = None) -> None:
14+
"""
15+
.. versionadded:: 3.0.0
16+
17+
Sets the path to the CA Bundle used by the `curl`
18+
built into PROJ.
19+
20+
Environment variables that can be used with PROJ 7.2+:
21+
22+
- PROJ_CURL_CA_BUNDLE
23+
- CURL_CA_BUNDLE
24+
- SSL_CERT_FILE
25+
26+
Parameters
27+
----------
28+
ca_bundle_path: Union[Path, str, bool, None], optional
29+
Default is None, which only uses the `certifi` package path as a fallback if
30+
the environment variables are not set. If a path is passed in, then
31+
that will be the path used. If it is set to True, then it will default
32+
to using the path provied by the `certifi` package. If it is set to False,
33+
then it will not set the path.
34+
"""
35+
if ca_bundle_path is False:
36+
return None
37+
38+
env_var_names = (
39+
"PROJ_CURL_CA_BUNDLE",
40+
"CURL_CA_BUNDLE",
41+
"SSL_CERT_FILE",
42+
)
43+
if isinstance(ca_bundle_path, (str, Path)):
44+
ca_bundle_path = str(ca_bundle_path)
45+
elif (ca_bundle_path is True) or not any(
46+
env_var_name in os.environ for env_var_name in env_var_names
47+
):
48+
ca_bundle_path = certifi.where()
49+
50+
if isinstance(ca_bundle_path, str):
51+
_set_ca_bundle_path(ca_bundle_path)

setup.py

+1
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ def get_extension_modules():
166166
),
167167
Extension("pyproj._datadir", ["pyproj/_datadir.pyx"], **ext_options),
168168
Extension("pyproj._list", ["pyproj/_list.pyx"], **ext_options),
169+
Extension("pyproj._network", ["pyproj/_network.pyx"], **ext_options),
169170
Extension("pyproj._sync", ["pyproj/_sync.pyx"], **ext_options),
170171
],
171172
quiet=True,

test/test_network.py

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import certifi
2+
import pytest
3+
from mock import patch
4+
5+
from pyproj.network import set_ca_bundle_path
6+
7+
8+
@patch.dict("os.environ", {}, clear=True)
9+
@patch("pyproj.network._set_ca_bundle_path")
10+
def test_ca_bundle_path__default(c_set_ca_bundle_path_mock):
11+
set_ca_bundle_path()
12+
c_set_ca_bundle_path_mock.assert_called_with(certifi.where())
13+
14+
15+
@pytest.mark.parametrize(
16+
"env_var", ["PROJ_CURL_CA_BUNDLE", "CURL_CA_BUNDLE", "SSL_CERT_FILE"]
17+
)
18+
@patch("pyproj.network._set_ca_bundle_path")
19+
def test_ca_bundle_path__always_certifi(c_set_ca_bundle_path_mock, env_var):
20+
with patch.dict("os.environ", {env_var: "/tmp/dummy/path/cacert.pem"}, clear=True):
21+
set_ca_bundle_path(True)
22+
c_set_ca_bundle_path_mock.assert_called_with(certifi.where())
23+
24+
25+
@patch.dict("os.environ", {}, clear=True)
26+
@patch("pyproj.network._set_ca_bundle_path")
27+
def test_ca_bundle_path__skip(c_set_ca_bundle_path_mock):
28+
set_ca_bundle_path(False)
29+
c_set_ca_bundle_path_mock.assert_not_called()
30+
31+
32+
@pytest.mark.parametrize(
33+
"env_var", ["PROJ_CURL_CA_BUNDLE", "CURL_CA_BUNDLE", "SSL_CERT_FILE"]
34+
)
35+
@patch("pyproj.network._set_ca_bundle_path")
36+
def test_ca_bundle_path__env_var_skip(c_set_ca_bundle_path_mock, env_var):
37+
with patch.dict("os.environ", {env_var: "/tmp/dummy/path/cacert.pem"}, clear=True):
38+
set_ca_bundle_path()
39+
c_set_ca_bundle_path_mock.assert_not_called()
40+
41+
42+
@pytest.mark.parametrize(
43+
"env_var", ["PROJ_CURL_CA_BUNDLE", "CURL_CA_BUNDLE", "SSL_CERT_FILE"]
44+
)
45+
@patch("pyproj.network._set_ca_bundle_path")
46+
def test_ca_bundle_path__custom_path(c_set_ca_bundle_path_mock, env_var):
47+
with patch.dict("os.environ", {env_var: "/tmp/dummy/path/cacert.pem"}, clear=True):
48+
set_ca_bundle_path("/my/path/to/cacert.pem")
49+
c_set_ca_bundle_path_mock.assert_called_with("/my/path/to/cacert.pem")

0 commit comments

Comments
 (0)