Skip to content

Commit

Permalink
ENH: Added Transformer.get_last_used_operation (#1124)
Browse files Browse the repository at this point in the history
  • Loading branch information
snowman2 committed Aug 25, 2022
1 parent b6a4fcd commit a190b76
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ disable=cyclic-import,


[FORMAT]
max-module-lines=1300
max-module-lines=1350
1 change: 1 addition & 0 deletions docs/history.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Latest
- BUG: Fix transformer list for 3D transformations in :class:`.TransformerGroup` (discussion #1072)
- ENH: Added authority, accuracy, and allow_ballpark kwargs to :class:`.TransformerGroup` (pull #1076)
- ENH: Added ``force_over`` kwarg to :meth:`.Transformer.from_crs` (issue #997)
- ENH: Added :meth:`.Transformer.get_last_used_operation` (issue #1071)
- CLN: Remove deprecated ``skip_equivalent`` kwarg from transformers and ``errcheck`` kwarg from :meth:`.CRS.from_cf` (pull #1077)
- REF: use regex to process PROJ strings in :meth:`.CRS.to_dict` (pull #1086)
- BUG: :class:`.MercatorAConversion` defined only for lat_0 = 0 (issue #1089)
Expand Down
1 change: 1 addition & 0 deletions pyproj/_transformer.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class _Transformer(Base):
def target_crs(self) -> Optional[_CRS]: ...
@property
def operations(self) -> Union[Tuple[CoordinateOperation], None]: ...
def get_last_used_operation(self) -> _Transformer: ...
@property
def is_network_enabled(self) -> bool: ...
def to_proj4(
Expand Down
27 changes: 27 additions & 0 deletions pyproj/_transformer.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ proj_version_str = f"{PROJ_VERSION_MAJOR}.{PROJ_VERSION_MINOR}.{PROJ_VERSION_PAT
PROJ_VERSION = (PROJ_VERSION_MAJOR, PROJ_VERSION_MINOR, PROJ_VERSION_PATCH)
_AUTH_CODE_RE = re.compile(r"(?P<authority>\w+)\:(?P<code>\w+)")

IF (CTE_PROJ_VERSION_MAJOR, CTE_PROJ_VERSION_MINOR) >= (9, 1):
cdef extern from "proj.h" nogil:
PJ* proj_trans_get_last_used_operation(PJ *P)


cdef dict _PJ_DIRECTION_MAP = {
TransformDirection.FORWARD: PJ_FWD,
Expand Down Expand Up @@ -427,6 +431,29 @@ cdef class _Transformer(Base):
self._operations = _get_concatenated_operations(self.context, self.projobj)
return self._operations

def get_last_used_operation(self):
IF (CTE_PROJ_VERSION_MAJOR, CTE_PROJ_VERSION_MINOR) >= (9, 1):
cdef PJ* last_used_operation = proj_trans_get_last_used_operation(self.projobj)
if last_used_operation == NULL:
raise ProjError(
"Last used operation not found. "
"This is likely due to not initiating a transform."
)
cdef PJ_CONTEXT* context = NULL
try:
context = pyproj_context_create()
except:
proj_destroy(last_used_operation)
raise
proj_assign_context(last_used_operation, context)
return _Transformer._from_pj(
context,
last_used_operation,
False,
)
ELSE:
raise NotImplementedError("PROJ 9.1+ required to get last used operation.")

@property
def is_network_enabled(self):
"""
Expand Down
1 change: 1 addition & 0 deletions pyproj/proj.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ cdef extern from "proj.h" nogil:
PJ_CONTEXT *proj_context_create ()
PJ_CONTEXT *proj_context_clone (PJ_CONTEXT *ctx)
PJ_CONTEXT *proj_context_destroy (PJ_CONTEXT *ctx)
void proj_assign_context(PJ* pj, PJ_CONTEXT* ctx)

ctypedef enum PJ_LOG_LEVEL:
PJ_LOG_NONE = 0
Expand Down
17 changes: 17 additions & 0 deletions pyproj/transformer.py
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,23 @@ def operations(self) -> Optional[Tuple[CoordinateOperation]]:
"""
return self._transformer.operations

def get_last_used_operation(self) -> "Transformer":
"""
.. versionadded:: 3.4.0
.. note:: Requires PROJ 9.1+
See: :c:func:`proj_trans_get_last_used_operation`
Returns
-------
Transformer:
The operation used in the transform call.
"""
return Transformer(
TransformerUnsafe(self._transformer.get_last_used_operation())
)

@property
def is_network_enabled(self) -> bool:
"""
Expand Down
23 changes: 23 additions & 0 deletions test/test_transformer.py
Original file line number Diff line number Diff line change
Expand Up @@ -1598,3 +1598,26 @@ def test_transformer_force_over():
else:
with pytest.raises(NotImplementedError, match="force_over requires PROJ 9"):
Transformer.from_crs("EPSG:4326", "EPSG:3857", force_over=True)


def test_transformer__get_last_used_operation():
transformer = Transformer.from_crs("EPSG:4326", "EPSG:3857")
if PROJ_GTE_91:
with pytest.raises(
ProjError,
match=(
r"Last used operation not found\. "
r"This is likely due to not initiating a transform\."
),
):
transformer.get_last_used_operation()
xxx, yyy = transformer.transform(1, 2)
operation = transformer.get_last_used_operation()
assert isinstance(operation, Transformer)
assert xxx, yyy == operation.transform(1, 2)
else:
with pytest.raises(
NotImplementedError,
match=r"PROJ 9\.1\+ required to get last used operation\.",
):
transformer.get_last_used_operation()

0 comments on commit a190b76

Please sign in to comment.