Skip to content

Commit

Permalink
Merge pull request #215 from snowman2/exceptions
Browse files Browse the repository at this point in the history
add proj error message to exceptions
  • Loading branch information
snowman2 committed Mar 23, 2019
2 parents e77dad7 + 8cdf277 commit 2abfe4f
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 7 deletions.
1 change: 0 additions & 1 deletion pyproj/_datadir.pxd
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
include "proj.pxi"


cdef PJ_CONTEXT* get_pyproj_context()
14 changes: 12 additions & 2 deletions pyproj/_datadir.pyx
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@

from libc.stdlib cimport malloc, free

from pyproj.compat import cstrencode
from pyproj.compat import cstrencode, pystrdecode
from pyproj.datadir import get_data_dir
from pyproj.exceptions import ProjError

cdef void pyproj_log_function(void *user_data, int level, const char *error_msg):
"""
Log function for proj.4 errors with CRS class.
"""
if level == PJ_LOG_ERROR:
ProjError.internal_proj_error = pystrdecode(error_msg)


cdef PJ_CONTEXT* get_pyproj_context():
Expand All @@ -16,11 +24,13 @@ cdef PJ_CONTEXT* get_pyproj_context():
b_data_dir = cstrencode(data_dir_list[iii])
c_data_dir[iii] = b_data_dir
proj_context_set_search_paths(pyproj_context, len(data_dir_list), c_data_dir)
proj_context_use_proj4_init_rules(pyproj_context, 1)
except:
if pyproj_context != NULL:
proj_context_destroy(pyproj_context)
raise
finally:
free(c_data_dir)
proj_context_use_proj4_init_rules(pyproj_context, 1)
proj_log_func(pyproj_context, NULL, pyproj_log_function)

return pyproj_context
21 changes: 17 additions & 4 deletions pyproj/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,26 @@
"""


class CRSError(RuntimeError):
"""Raised when a CRS error occurs."""


class ProjError(RuntimeError):
"""Raised when a Proj error occurs."""

internal_proj_error = None

def __init__(self, error_message):
if self.internal_proj_error is not None:
error_message = (
"{error_message}: (Internal Proj Error: {internal_proj_error})"
).format(
error_message=error_message,
internal_proj_error=self.internal_proj_error,
)
self.internal_proj_error = None
super(ProjError, self).__init__(error_message)


class CRSError(ProjError):
"""Raised when a CRS error occurs."""


class GeodError(RuntimeError):
"""Raised when a Geod error occurs."""
Expand Down
10 changes: 10 additions & 0 deletions pyproj/proj.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@ cdef extern from "proj.h":
ctypedef struct PJ_CONTEXT
PJ_CONTEXT *proj_context_create ()
PJ_CONTEXT *proj_context_destroy (PJ_CONTEXT *ctx)

ctypedef enum PJ_LOG_LEVEL:
PJ_LOG_NONE = 0
PJ_LOG_ERROR = 1
PJ_LOG_DEBUG = 2
PJ_LOG_TRACE = 3
PJ_LOG_TELL = 4
ctypedef void (*PJ_LOG_FUNCTION)(void *, int, const char *)
void proj_log_func (PJ_CONTEXT *ctx, void *app_data, PJ_LOG_FUNCTION logf)

int proj_errno (const PJ *P)
int proj_context_errno (PJ_CONTEXT *ctx)
const char * proj_errno_string (int err)
Expand Down
14 changes: 14 additions & 0 deletions unittest/test_exception_logging.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import pytest

from pyproj import CRS, Proj
from pyproj.exceptions import CRSError, ProjError


def test_proj_exception():
with pytest.raises(ProjError, match="Internal Proj Error"):
Proj("+proj=bobbyjoe")


def test_crs_exception():
with pytest.raises(CRSError, match="Internal Proj Error"):
CRS("+proj=bobbyjoe")

0 comments on commit 2abfe4f

Please sign in to comment.